Linux——进程与资源利用

进程与资源利用

进程跟踪

top命令将系统中最活跃的进程(即当前消耗CPU时间最多的那些进程)显示在最上方。

你可以通过键盘向top发送命令。下面是一些比较重要的键盘命令

命令含义
空格键立即更新显示内容。
M按照当前内存使用量排序。
T按照CPU累计使用量排序。
P按照当前CPU使用量(默认)排序。
u仅显示某位用户的进程。
f选择不同的统计信息来显示。
?为所有top命令显示使用情况统计。

使用lsof查看打开的文件

lsof命令列出打开的文件以及使用它们的进程。由于Unix系统大量使用文件,所以lsof在系统排错方面是最有用的命令之一。

lsof输出

lsof的输出结果通常信息量很大,。这一输出结果中包含init进程中打开的文件和运行中的vi进程:

$ lsof
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
init 1 root cwd DIR 8,1 4096 2 /
init 1 root rtd DIR 8,1 4096 2 /
init 1 root mem REG 8, 47040 9705817 /lib/i386-linux-gnu/libnss_files-2.15.so
init 1 root mem REG 8,1 42652 9705821 /lib/i386-linux-gnu/libnss_nis-2.15.so
init 1 root mem REG 8,1 92016 9705833 /lib/i386-linux-gnu/libnsl-2.15.so
--snip--
vi 22728 juser cwd DIR 8,1 4096 14945078 /home/juser/w/c
vi 22728 juser 4u REG 8,1 1288 1056519 /home/juser/w/c/f
--snip--

其中包含以下字段:

  • COMMAND:拥有文件描述符的的进程对应的命令名。
  • PIM:PID
  • USER:运行进程的用户。
  • FD:该列包含两种元素。本例中FD列显示文件的作用。该列还能够显示打开文件的描述符。文件描述符是一个数字,进程通过它使用系统库和内核来进行文件标识和操作。
  • TYPE:文件类型(如常规文件、目录、套接字等)。
  • DEVICE:包含该文件的设备的主要代码和次要代码。
  • SIZE:文件大小
  • NODE:文件的索引节点编号。
  • NAME:文件名

lsof的使用

运行lsof有以下两种基本方式。

  • 输出完整的结果,然后将输出结果通过管道命令less显示,然后在其中搜索你想要的内容。
  • 使用命令行选项来过滤lsof的输出结果。

下面的命令显示/usr目录中所有打开的文件:

$ lsof /usr

根据PID列出打开文件,使用以下命令:

$ lsof -p pid

你可以运行lsof -h查看lsof所有的选项。大部分选项和输出格式有关。

跟踪程序执行和系统调用

strace(系统调用跟踪)和ltrace(系统库跟踪)命令能够帮助你了解程序试图执行哪些操作。

strace命令

strace能够显示进程涉及的所有系统调用

$ strace cat /dev/null

如果一个进程想启动另一个进程,该进程会使用fork()系统调用来从自身创建出一个副本,然后副本调用exec()系统调用集来启动和运行新的程序。

strace命令在fork()系统调用之后开始监控新创建的进程(即源进程的副本)。因而该命令输出结果的一开始
几行应该显示execve()的执行情况,随后是内存初始化系统调用brk()。

execve("/bin/cat", ["cat", "/dev/null"], [/* 58 vars */]) = 0
brk(0) = 0x9b65000

输出的后续部分涉及共享库的加载。除非你想知道加载共享库的细节,否则你可以忽略这些信息。

ltrace命令

ltrace命令跟踪对共享库的调用。它的输出结果和strace类似,所以我们在这里提一下。但是它不跟踪内核级的内容。请记住,共享库调用比系统调用数量多得多。所以你有必要过滤ltrace命令的输出结果。ltrace命令有很多选项可以帮到你。

线程

在Linux中,一些进程被细分为更小的部分,我们称为线程(thread)。线程和进程很类似,它有一个标识符(即TID)。内核运行线程的方式和运行进程基本相同。但有一点不同,即进程之间不共享内存和I/O这样的系统资源,而同一个进程中的所有线程则共享该进程占用的系统资源和一些内存。

单线程进程和多线程进程

很多进程只有一个线程,叫单线程进程。有超过一个线程的叫多线程进程。所有进程最开始都是单线程,起始线程通常称为主线程。主线程随后可能会启动新的线程,这样进程就变为多线程。这个过程和进程使用fork()创建新进程类似。

多线程的主要优势在于,当进程要做的事情很多时,多个线程可以同时在多个处理器上运行,这样可以加快进程的运行速度。虽然你也可以同时在多个处理器上运行多个进程,但线程相对进程来说启动更快,并且线程间通过共享的进程内存来相互通信,比进程间通过网络和管道相互通信更加便捷高效。

一些应用程序使用线程来解决在管理多个I/O资源时遇到的问题。传统上来说,进程有时候会使用fork()创建新的子进程来处理新的输入输出流。线程提供相似的机制,但却省去了启动新进程的麻烦。

查看线程

默认情况下,ps和top命令只显示进程的信息。如果想查看线程的信息,可以添加一个m选项,如下例所示。

$ ps m
PID TTY STAT TIME COMMAND
3587 pts/3 - 0:00 bash➊
- - Ss 0:00 -
3592 pts/4 - 0:00 bash➋
- - Ss 0:00 -
12287 pts/8 - 0:54 /usr/bin/python /usr/bin/gm-notify➌
- - SL1 0:48 -
- - SL1 0:00 -
- - SL1 0:06 -
- - SL1 0:00 -

该例显示进程和线程的信息。每一行有一个PID字段(其中➊、➋、➌行的PID值是数字),代表一个进程,和一般的ps输出一样。PID字段值为-的那些行代表进程中的线程。本例中进程➊和➋只有一个线程,进程➌(PID值为12287)有四个线程。

如果想要使用ps查看TID,需要使用自定义的输出格式。下面的例子显示PID、TID以及相关命令。

$ ps m -o pid,tid,command
PID TID COMMAND
3587 - bash
- 3587 -
3592 - bash
- 3592 -
12287 - /usr/bin/python /usr/bin/gm-notify
- 12287 -
- 12288 -
- 12289 -
- 12295 -

资源监控

测试CPU时间

如果要监控进程,可以使用top命令加-p选项,如下所示:

$ top -p pid1 [-p pid2 ...]

使用time命令可以查看命令整个执行过程中占用的CPU时间。大部分shell提供的time命令只显示一些基本信息,所以你可能需要运行/usr/bin/time。例如,如果要查看ls命令占用的CPU时间,可以运行以下命令:

$ /usr/bin/time ls

time在ls结束后会显示像下面这样的结果,关键的字段我们使用粗体字标出:

0.05user 0.09system 0:00.44elapsed 31%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (125major+51minor)pagefaults 0swaps

  • user:用户时间,指CPU用来运行程序代码的时间,以秒为单位。在现在的处理器中,命令的运行速度很快,有些不超过一秒,time命令会将他们四舍五入为0。
  • system:系统时间,指内核用来执行进程任务的时间,例如读取文件和目录
  • elapsed:消耗时间,指进程从开始到结束的全部时间,包括CPU执行其他任务的时间。这个数字在检测性方面不是很有帮助,不过将消耗时间减少用户时间和系统时间所剩余的时间,能够让你得知进程等待系统资源所消耗的时间。

调节进程优先级

你可以更改内核对进程的调度方式,从而增加或减少安排给进程的CPU时间。内核按照每个进程的调度优先级来运行进程,这些优先级用-20和+20之间的数字表示。有些古怪的是,-20是最高的优先级。

ps -l命令显示当前进程的优先级,不过使用top命令更容易一点

$ top
Tasks: 244 total, 2 running, 242 sleeping, 0 stopped, 0 zombie
Cpu(s): 31.7%us, 2.8%sy, 0.0%ni, 65.4%id, 0.2%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 6137216k total, 5583560k used, 553656k free, 72008k buffers
Swap: 4135932k total, 694192k used, 3441740k free, 767640k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
28883 bri 20 0 1280m 763m 32m S 58 12.7 213:00.65 chromium-browse
1175 root 20 0 210m 43m 28m R 44 0.7 14292:35 Xorg
4022 bri 20 0 413m 201m 28m S 29 3.4 3640:13 chromium-browse
4029 bri 20 0 378m 206m 19m S 2 3.5 32:50.86 chromium-browse
3971 bri 20 0 881m 359m 32m S 2 6.0 563:06.88 chromium-browse
5378 bri 20 0 152m 10m 7064 S 1 0.2 24:30.21 compiz
3821 bri 20 0 312m 37m 14m S 0 0.6 29:25.57 soffice.bin
4117 bri 20 0 321m 105m 18m S 0 1.8 34:55.01 chromium-browse
4138 bri 20 0 331m 99m 21m S 0 1.7 121:44.19 chromium-browse
4274 bri 20 0 232m 60m 13m S 0 1.0 37:33.78 chromium-browse
4267 bri 20 0 1102m 844m 11m S 0 14.1 29:59.27 chromium-browse
2327 bri 20 0 301m 43m 16m S 0 0.7 109:55.65 unity-2d-shell

上面的输出结果中,PR(意思是优先级)字段显示内核当前赋予进程的调度优先级。这个数字越大,内核调用该进程的几率越小。决定内核分配给进程CPU时间的不仅仅是优先级,并且优先级在进程执行过程中也会根据其消耗的CPU时间而频繁改变

PR字段旁边是NI(意思是优先值)字段,显示有关内核进程调度的少许信息,如果你想干预内核的进程调度,这个信息会对你有用。内核使用NI值来决定进程下一次在什么时间运行。

NI默认值是0。例如,你在后台运行一个计算量很大的进程,且不希望它影响到前台的交互,想让它在其他进程空闲的时候再运行,就可以使用renice命令将NI设置为20(pid是你要设置的进程的ID):

$ renice 20 pid

如果你是超级用户,你可以将NI设置为一个负数,但这并不是一个好方法,因为系统级进程也许无法获得足够的CPU时间。

平均负载

CPU的性能比较容易来衡量。**平均负载(load average)**是准备就绪待执行的进程的平均数。也就是某一时刻可以使用CPU的进程数的一个估计值。只有那些真正在运行的进程才计入平均负载。

uptime的使用

uptime命令显示三个平均负载值和内核已经运行的时长:

$ uptime
... up 91 days, ... load average: 0.08, 0.03, 0.01

以上三个数字分别代表过去1分钟、5分钟和15分钟的平均负载值。

如果平均负载值接近1,说明某个进程可能完全占用了CPU。这时可以使用top命令来查看,通常出现在列表最上方的就是那个进程。

现在很多系统有多个处理器核心(或CPU),它们使得进程能够同时运行。如果你有两个核心并且平均负载为1,这意味着只有其中一个处于活跃状态,如果平均负载为2,说明两个都处于忙状态。

高负载

如果平均负载值高并且系统响应速度很慢的话,可能意味着内存性能有问题。当系统出现内存不足的情况时,内核会开始执行一个机械性的反复动作,或者说在磁盘和内存间交换进程数据。此时很多进程会处于执行准备就绪状态,但是可能没有足够内存。这种情况下,它们保持准备就绪状态的时间要比平时久一些。

内存

查看系统内存状态最简单的方法之一是使用free命令,或者查看/proc/meminfo文件来了解系统内存被作为缓存和缓冲区的实际使用情况。

内存的工作原理

CPU通过MMU(内存管理单元)将进程使用的虚拟地址转换为实际的内存地址。内核帮助MMU把进程使用的内存划分为更小的区域,我们称为页面。内核负责维护一个数据结构,我们称为页面表,其中包含从虚拟页面地址到实际内存地址的映射关系。当进程访问内存时,MMU根据此表将进程使用的虚拟地址转换为实际的内存地址。

进程执行时并不需要立即加载它所有的内存页面。内核通常在进程需要的时候加载和分配内存页面,我们称为按需内存分页(on-demand paging或者demand paging)

进程是如何启动和运行的:

  1. 内核将程序指令代码的开始部分加载到内存页面内。
  2. 内核可能还会为新进程分配一些内存页面供其运行使用。
  3. 进程执行过程中,可能代码中的下一个指令在已加载的内存页面中不存在。这时内核接管控制,加载需要的内存页面,然后让程序恢复运行。
  4. 同样地,如果进程需要使用更多的内存,内核接管控制,并且获得空闲的内存空间(或者腾出一些内存空间)分配给进程。

内存页面错误

如果内存页面在进程想要使用时没有准备就绪,进程会产生内存页面错误(page fault)。错误产生时,内核从进程接管CPU的控制权,然后使内存页面准备就绪。内存页面错误有两种:轻微错误和严重错误。

轻微内存页面错误

进程需要的内存页面在主内存中但是MMU无法找到时,会产生轻微内存页面错误。通常发生在进程需要更多内存时或MMU没有足够内存空间来为进程存放所有页面时。这时内核会通知MMU,并且让进程继续执行。轻微内存页面错误不是很严重,在进程执行过程中可能会出现。通常你不需要对此太在意,除非是那些对性能和内存要求很高的应用。

严重内存页面错误

严重内存页面错误发生在进程需要的内存页面在主内存中不存在时,意味着内核需要从磁盘或者其他低速存储媒介中加载。太多此类错误会影响系统性能,因为内核必须做大量的工作来为进程加载内存页面,占用大量CPU时间,妨碍其他进程的运行。

查看内存页面错误

你可以使用ps、top或time命令为某个进程的内存页面错误查找原因。下面是一个例子,列举time命令提供的内存页面错误信息。(cal命令的输出可以忽略,我们将其重定向到/dev/null。)

$ /usr/bin/time cal > /dev/null
0.00user 0.00system 0:00.06elapsed 0%CPU (0avgtext+0avgdata 3328maxresident)k
648inputs+0outputs (2major+254minor)pagefaults 0swaps

从以上加粗的信息可以看出,程序运行过程中产生了两个严重内存页面错误和254个轻微内存页面错误。严重内存页面错误发生在当内核首次从磁盘加载一个程序的时候。如果再次运行该程序,你可能不会再碰到严重内存页面错误,因为内核可能已经将从磁盘加载的内存页面放入缓存了。

如果你想在进程运行过程中查看产生的内存页面错误,可以使用top或者ps命令。可以使用top命令加f选项设置显示的字段,u选项显示严重内存页面错误的数目。(结果会显示在一个新的列nFLT中,轻微内存页面错误不显示。)

使用ps命令时,你可以使用自定义输出格式来查看某个进程产生的内存页面错误。下面是进程20365的一个例子:

$ ps -o pid,min_flt,maj_flt 20365
PID MINFL MAJFL
20365 834182 23

MINFL和MAJFL列显示轻微和严重内存页面错误数目。在此基础上,你还可以加入其他的进程选择参数。

使用vmstat监控CPU和内存性能

在众多系统性能监控工具中,vmstat命令是较为陈旧的一个,但也是运行开销最小的一个。你可以使用它来清晰地了解内核交换内存页面的频率、CPU的繁忙程度以及IO的使用情况。

通过查看vmstat的输出结果能够获得很多有用的信息。下面是vmstat 2命令的输出结果,统计信息每2秒刷新一次:

$ vmstat 2
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
2 0 320416 3027696 198636 1072568 0 0 1 1 2 0 15 2 83 0
2 0 320416 3027288 198636 1072564 0 0 0 1182 407 636 1 0 99 0
1 0 320416 3026792 198640 1072572 0 0 0 58 281 537 1 0 99 0
0 0 320416 3024932 198648 1074924 0 0 0 308 318 541 0 0 99 1
0 0 320416 3024932 198648 1074968 0 0 0 0 208 416 0 0 99 0
0 0 320416 3026800 198648 1072616 0 0 0 0 207 389 0 0 100 0

输出结果可以归为这几类:procs(进程)、memory(内存使用)、swap(内存页面交换)、io(磁盘使用)、system(内核切换到内核代码的次数)以及cpu(系统各组件使用CPU的时间)。

上例中的输出结果是系统负载不大的一种典型情况。通常我们会从第二行看起,因为第一行是系统整个运行时期的平均值。上例中,系统有320 416 KB内存被交换到磁盘(swpd),有大约3025000 KB(3 GB)空闲内存(free)。虽然有一部分交换空间正在被占用,但是si(换入,swap-in)和so(换出,swap-out)列仍显示内核没有在磁盘交换内存。buff列显示内核用于磁盘缓冲区的内存。

在最右边的cpu列,你可以看到CPU时间被分为us、sy、id和wa列。它们依次代表用户任务、系统(内核)任务、空闲时间和I/O等待时间占用的CPU时间的百分比

I/O监控

默认情况下,vmstat显示常用的I/O统计信息

使用iostat

和vmstat类似,iostat在不带任何参数时显示系统当前的运行时间信息:

$ iostat
[kernel information]
avg-cpu: %user %nice %system %iowait %steal %idle
               4.46    0.01    0.67        0.31      0.00    94.55
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
sda      4.67  7.28         49.86       9493727 65011716
sde     0.00   0.00         0.00        1230        0

上面avg-cpu部分和本章介绍的其他工具一样,显示的是CPU的使用信息,往下是各个设备的情况

  • tps:平均每秒数据传输量
  • kB_read/s:平均每秒数据读取量
  • kB/wrtn/s:平均每秒数据写入量
  • kB/read:数据读取总量
  • kB/wrtn:数据写入总量

使用iotop查看进程的I/O使用和监控

使用方法和top一样。它会持续显示使用I/O最多的进程,最顶端是汇总数据

# iotop
Total DISK READ: 4.76 K/s | Total DISK WRITE: 333.31 K/s
TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
260 be/3 root 0.00 B/s 38.09 K/s 0.00 % 6.98 % [jbd2/sda1-8]
2611 be/4 juser 4.76 K/s 10.32 K/s 0.00 % 0.21 % zeitgeist-daemon
2636 be/4 juser 0.00 B/s 84.12 K/s 0.00 % 0.20 % zeitgeist-fts
1329 be/4 juser 0.00 B/s 65.87 K/s 0.00 % 0.03 % soffice.b~ash-pipe=6
6845 be/4 juser 0.00 B/s 812.63 B/s 0.00 % 0.00 % chromium-browser
19069 be/4 juser 0.00 B/s 812.63 B/s 0.00 % 0.00 % rhythmbox

请注意,除了user、command、read、write列之外,还有一列叫TID(也就是线程ID),而非PID(即进程ID)。iotop是为数不多的显示线程而非进程的工具。

PRIO(意思是优先级)列表示I/O的优先级。它类似于我们介绍过的CPU优先级,但它还会决定内核为进程调度I/O读写操作分配多长时间。

如果优先级为be/4,则be代表调度等级,数字代表优先级别。和CPU优先级一样,数字越小,优先级越高。比如内核会为be/3的进程分配比be/4的进程更多的时间。

内核使用调度等级为I/O调度施加更多的控制。iotop中有以下三种调度等级。

  • be:即best-effort(尽力)。内核尽最大努力为其公平地调度I/O。大部分进程是在这类I/O调度等级下运行。
  • rt:即real-time(实时)。内核优先调度实时I/O。
  • idle:空闲。内核只在没有其他I/O工作的时候安排此类I/O工作。该调度等级不具备优先级。

你可以使用ionice工具来查看和更改进程的I/O优先级

使用pidstat 监控进程

pidstat工具能够让你使用vmstat的方式来查看进程在过去某个时间段内的资源使用情况。

对进程1329监控结果,按秒记录

$ pidstat -p 1329 1
Linux 3.2.0-44-generic-pae (duplex) 07/01/2015 _i686_ (4 CPU)
09:26:55 PM PID %usr %system %guest %CPU CPU Command
09:27:03 PM 1329 8.00 0.00 0.00 8.00 1 myprocess
09:27:04 PM 1329 0.00 0.00 0.00 0.00 3 myprocess
09:27:05 PM 1329 3.00 0.00 0.00 3.00 1 myprocess
09:27:06 PM 1329 8.00 0.00 0.00 8.00 3 myprocess
09:27:07 PM 1329 2.00 0.00 0.00 2.00 3 myprocess
09:27:08 PM 1329 6.00 0.00 0.00 6.00 2 myprocess

该命令在默认情况下显示用户时间和系统时间的百分比,以及综合的CPU时间百分比,还显示进程在哪一个CPU上运行。(%guest列有一点奇怪,指进程在虚拟机上运行时间的百分比。除非你是在运行虚拟机,否则可以忽略它。)

其他

资源监控和性能分析的更加深入的工具有以下几方面

  • sar(即系统活动报告,System Activity Reporter):sar包含很多vmstat的持续监控功能,另外还记录系统资源随时间使用情况。sar让你能够查看过去某一时刻的系统状态,这在你需要查看已发生的系统事件时非常有用。
  • acct(即进程统计):acct能够记录进程以及它们的资源使用情况。
  • Quotas(即配额):你可以将某些系统资源限制给某个进程或用户使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值