程序和进程
https://www.jianshu.com/p/07173e5e333a
-
程序 (program):通常为 binary program ,放置在储存媒体中 (如硬盘、光盘、软盘、磁带等), 为实体文件的型态存在;
-
进程 (process):程序被触发后,执行者的权限与属性、程序的程序码与所需数据等都会被载入内存中, 操作系统并给予这个内存内的单元一个识别码 (PID),可以说,进程就是一个正在运行中的程序。
子进程和父进程
imagefork and exec:程序调用的流程
子程序与父程序之间的关系还挺复杂的,最大的复杂点在于程序互相之间的调用。在 Linux 的程序调用通常称为 fork-and-exec 的流程 [1]!程序都会借由父程序以复制 (fork) 的方式产生一个一模一样的子程序, 然后被复制出来的子程序再以 exec 的方式来执行实际要进行的程序,最终就成为一个子程序的存在。 整个流程有点像下面这张图:
image- 系统先以 fork 的方式复制一个与父程序相同的暂存程序,这个程序与父程序唯一的差别就是 PID 不同! 但是这个暂存程序还会多一个 PPID 的参数,PPID 就是父程序的程序识别码啦!
- 然后,暂存程序开始以 exec 的方式载入实际要执行的程序,以上述图示来讲,新的程序名称为 qqq ,最终子程序的程序码就会变成 qqq 了
系统或网络服务:常驻在内存的程序
一直在执行的程序,就是常驻在内存当中的程序。
常驻在内存当中的程序通常都是负责一些系统所提供的功能以服务使用者各项任务,因此这些常驻程序就会被我们称为:服务 (daemon)。
系统的服务非常的多, 不过主要大致分成系统本身所需要的服务,例如 crond
计划任务 ,还有 rsyslogd
日志服务等等的。还有一些则是负责网络连接的服务,例如 Apache, named, postfix, vsftpd... 等等的。这些网络服务的程序被执行后,他会启动一个可以负责网络监听的端口 (port) ,以提供外部用户端 (client) 的连线请求。
一般 daemon 类型的程序都会加上 d 在文件名后头,因为 Linux 希望我们可以简单的判断该程序是否为 daemon
多人、多任务、多环境
多重登陆环境的七个基本终端窗口:
在 Linux 当中,默认提供了六个文字界面登陆窗口,以及一个图形界面,你可以使用 [Alt]+[F1].....[F7] 来切换不同的终端机界面,而且每个终端机界面的登陆者还可以不同人
查看系统中的进程
ps :获取到某个时间点的程序运行情况(静态)
ps aux 查看所有的进程信息,注意这里的 aux x选项没有短横线
选项与参数:
-A :所有的 process 均显示出来,与 -e 具有同样的效用;
-a :不与 terminal 有关的所有 process ;
-u :有效使用者 (effective user) 相关的 process ;
x :通常与 a 这个参数一起使用,可列出较完整信息。
输出格式:
l :较长、较详细的将该 PID 的的信息列出;
j :工作的格式 (jobs format)
-f :做一个更为完整的输出。
ps aux 输出各字段意义
USER: 该 process 属于那个使用者帐号的?
PID : 该 process 的程序识别码。
%CPU: 该 process 使用掉的 CPU 资源百分比;
%MEM: 该 process 所占用的实体内存百分比;
VSZ : 该 process 使用掉的虚拟内存量 (KBytes)
RSS : 该 process 占用的固定的内存量 (KBytes)
TTY : 该 process 是在那个终端机上面运行,若与终端机无关则显示 ?,另外, tty1-tty6 是本机上面的登陆者程序,若为 pts/0 等等的,则表示为由网络连接进主机的程序。
STAT: 该程序目前的状态,状态显示与 ps -l 的 S 旗标相同 (R/S/T/Z)
START: 该 process 被触发启动的时间;
TIME : 该 process 实际使用 CPU 运行的时间。
COMMAND:该程序的实际指令为何?
S:代表这个程序的状态 (STAT),主要的状态有:
- R (Running):该程序正在运行中;
- S (Sleep):该程序目前正在睡眠状态(idle),但可以被唤醒(signal)。
- D :不可被唤醒的睡眠状态,通常这支程序可能在等待 I/O 的情况(ex>打印)
- T :停止状态(stop),可能是在
jobs
控制(后台暂停)- Z (Zombie):僵尸状态,程序已经终止但却无法被移除至内存外。
什么是僵尸进程
我们必须要知道的是“僵尸 (zombie) ”程序是什么? 通常,造成僵尸程序的成因是因为该程序应该已经执行完毕,或者是因故应该要终止了, 但是该程序的父程序却无法完整的将该程序结束掉,而造成那个程序一直存在内存当中。 如果你发现在某个程序的 CMD 后面还接上 <defunct>
时,就代表该程序是僵尸程序啦,例如:
当系统不稳定的时候就容易造成所谓的僵尸程序,可能是因为程序写的不好啦,或者是使用者的操作习惯不良等等所造成。 如果你发现系统中很多僵尸程序时,记得啊!要找出该程序的父程序,然后好好的做个追踪,好好的进行主机的环境最优化啊! 看看有什么地方需要改善的,不要只是直接将他 kill 掉而已呢!不然的话,万一他一直产生,那可就麻烦了!
事实上,通常僵尸程序都已经无法控管,而直接是交给 systemd 这支程序来负责了,偏偏 systemd 是系统第一支执行的程序, 他是所有程序的父程序!我们无法杀掉该程序的 (杀掉他,系统就死掉了!),所以啰,如果产生僵尸程序, 而系统过一阵子还没有办法通过核心非经常性的特殊处理来将该程序删除时,那你只好通过 reboot 的方式来将该程序抹去了!
top 动态
top 命令
选项与参数:
-d :后面可以接秒数,就是整个程序画面更新的秒数。默认是 5 秒;
-b :以批次的方式执行 top ,还有更多的参数可以使用喔!
通常会搭配数据流重导向来将批次的结果输出成为文件。
-n :与 -b 搭配,意义是,需要进行几次 top 的输出结果。
-p :指定某些个 PID 来进行观察监测而已。
在 top 执行过程当中可以使用的按键指令:
? :显示在 top 当中可以输入的按键指令;
P :以 CPU 的使用资源排序显示;
M :以 Memory 的使用资源排序显示;
N :以 PID 来排序喔!
T :由该 Process 使用的 CPU 时间累积 (TIME+) 排序。
k :给予某个 PID 一个讯号 (signal)
r :给予某个 PID 重新制订一个 nice 值。
q :离开 top 软件的按键。
top - 19:55:28 up 11:10, 1 user, load average: 0.00, 0.01, 0.05
Tasks: 160 total, 1 running, 159 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni, 99.9 id, 0.0 wa, 0.0 hi, 0.0 si,
KiB Mem : 16251468 total, 15535360 free, 443400 used, 272708 buff/c
KiB Swap: 8257532 total, 8257532 free, 0 used. 15482496 avail
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+
3711 root 20 0 157760 2324 1632 R 0.7 0.0 0:00.02
10 root 20 0 0 0 0 S 0.3 0.0 0:13.99
1 root 20 0 191188 4188 2516 S 0.0 0.0 0:01.91
2 root 20 0 0 0 0 S 0.0 0.0 0:00.00
3 root 20 0 0 0 0 S 0.0 0.0 0:00.12
5 root 0 -20 0 0 0 S 0.0 0.0 0:00.00
7 root 20 0 0 0 0 S 0.0 0.0 0:00.03
8 root rt 0 0 0 0 S 0.0 0.0 0:00.16
9 root 20 0 0 0 0 S 0.0 0.0 0:00.00
11 root rt 0 0 0 0 S 0.0 0.0 0:00.66
12 root rt 0 0 0 0 S 0.0 0.0 0:00.08
13 root rt 0 0 0 0 S 0.0 0.0 0:00.04
14 root 20 0 0 0 0 S 0.0 0.0 0:00.00
16 root 0 -20 0 0 0 S 0.0 0.0 0:00.00
17 root 20 0 0 0 0 S 0.0 0.0 0:00.07
18 root rt 0 0 0 0 S 0.0 0.0 0:00.07
19 root rt 0 0 0 0 S 0.0 0.0 0:00.04
第一行
19:55:28 系统当前时间
up 11:10 系统开机到现在经过了 11 小时 10 分钟了
1 users : 当前 1 个用户在线
load average: 0.00, 0.01, 0.05 系统1分钟、5分钟、15分钟的CPU负载信息
第二行
Tasks: 任务
160 total, 总共160个任务,就是 160 个进程
1 running, 1 个进程是 运行状态
159 sleeping, 159 个进程是 休眠状态
0 stopped, 0 个进程是 停止状态
0 zombie, 0 个进程是僵死状态
第三行
%Cpu(s): 表示这一行显示CPU总体信息 ,单位是百分比
0.0 us, 用户态进程占用CPU时间百分比,不包含renice值为负的任务占用的CPU的时间。
0.0 sy, 内核占用CPU时间百分比
0.0 ni, 改变过优先级的进程占用CPU的百分比
99.9 id, 空闲CPU时间百分比
0.0 wa, 等待I/O的CPU时间百分比
0.0 hi, CPU硬中断时间百分比
0.0 si, CPU软中断时间百分比注:这里显示数据是所有cpu的平均值,如果想看每一个cpu的处理情况,按1即可;收起,再次按1;
第四行
KiB Mem : 内存信息
16251468 total, 物理内存总容量
15535360 free, 空闲物理内容容量
443400 used, 已使用的物理内存
272708 buff/c 用作内核缓存的物理内存量
第五行
KiB Swap: 交互分区
8257532 total, 总共
8257532 free, 空闲
0 used. 已用
15482496 avail 有效提供给程序使用的内存,这个并不是 Swap 分区的容量
需要注意的是,free表示的是当前完全没有被程序使用的内存;而cache在有需要时,是可以被释放出来以供其它进程使用的(当然,并不是所有cache都可以释放,比如当前被用作ramfs的内存)。而available才真正表明系统目前可以提供给应用程序使用的内存。
第六行
PID:进程的ID
USER:进程拥有者
PR:Priority 的简写,进程的优先级别,越小越优先被执行
NI:Nice 的简写,与 Priority 有关,也是越小越早被执行;
VIRT:进程占用的虚拟内存
RES:进程占用的物理内存
SHR:进程使用的共享内存
S:进程的状态。S表示休眠,R表示正在运行,Z表示僵死状态,N表示该进程优先值为负数
%CPU:进程占用CPU的使用率
%MEM:进程使用的物理内存和总内存的百分比
TIME+:该进程启动后占用的总的CPU时间,即占用CPU使用时间的累加值。
top 常用交互命令
q:退出top命令
<Space>:立即刷新
s:设置刷新时间间隔
c:显示命令完全模式
t::显示或隐藏进程和CPU状态信息
m:显示或隐藏内存状态信息
l:显示或隐藏uptime信息
f:增加或减少进程显示标志
S:累计模式,会把已完成或退出的子进程占用的CPU时间累计到父进程的MITE+
P:按%CPU使用率排行
T:按MITE+排行
M:按%MEM排行
u:指定显示用户进程
r:修改进程renice值
kkill:进程
i:只显示正在运行的进程
W:保存对top的设置到文件~/.toprc,下次启动将自动调用toprc文件的设置。
h:帮助命令。
q:退出
pstree 进程树
pstree
选项与参数:
-A :各程序树之间的连接以 ASCII 字符来连接;
-U :各程序树之间的连接以万国码的字符来连接。在某些终端接口下可能会有错误;
-p :并同时列出每个 process 的 PID;
-u :并同时列出每个 process 的所属帐号名称。
[root@kvm-docker ~]# pstree -A -p -u
进程的管理
进程之间是可以互相控制的!举例来说,你可以关闭、重新启动服务器软件,服务器软件本身是个进程, 你既然可以让她关闭或启动,当然就是可以控制该进程。
如何控制进程?
通过给予该进程一个信号 (signal) 去告知该进程你想要让她作什么。
都有哪些信号?
命令
kill -l
输出
kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
主要的讯号代号与名称对应及内容是:
代号 | 名称 | 内容 |
---|---|---|
1 | SIGHUP | 启动被终止的进程,可让该 PID 重新读取自己的配置文件,类似重新启动 |
2 | SIGINT | 相当于用键盘输入 [ctrl]-c 来中断一个进程的进行 |
9 | SIGKILL | 代表强制中断一个进程的进行,如果该进程运行到一半, 那么尚未完成的部分可能会有“半产品”产生,类似 vim会有 .filename.swp 保留下来。 |
15 | SIGTERM | 以正常的结束进程来终止该程序的运行。由于是正常的终止, 所以后续的动作会将他完成。不过,如果该进程已经发生问题,就是无法使用正常的方法终止时, 输入这个信号也是没有用的。 |
19 | SIGSTOP | 相当于用键盘输入 [ctrl]-z 来暂停一个进程的运行 |
一般来说,你只要记得1
, 9
, 15
这三个号码的意义即可。那么我们如何传送一个讯号给某个程序呢?就通过 kill
或 killall
。下面分别来看看:
kill -信号代号 进程的PID号
或者
kill -信号名称 进程的PID号
killall -信号 命名名称
查询进程和已打开文件的关系
fuser:借由文件(或文件系统)找出正在使用该文件的程序
fuser [-umv] [-k [i] [-signal]] file/dir
选项与参数:
-u :除了程序的 PID 之外,同时列出该程序的拥有者;
-m :后面接的那个文件名会主动的上提到该文件系统的最顶层,对 umount 不成功很有效!
-v :可以列出每个文件与程序还有指令的完整相关性!
-k :找出使用该文件/目录的 PID ,并试图以 SIGKILL 这个讯号给予该 PID;
-i :必须与 -k 配合,在删除 PID 之前会先询问使用者意愿!
-signal:例如 -1 -15 等等,若不加的话,默认是 SIGKILL (-9) 啰!
找出目前所在目录的使用 PID/所属帐号/权限
[root@kvm-docker ~]# fuser -uv .
用户 进程号 权限 命令
/root: root 2379 ..c.. (root)bash
root 2419 ..c.. (root)sh
root 2420 ..c.. (root)ntpdate
权限部分
c :此程序在当前的目录下(非次目录);
e :可被触发为执行状态;
f :是一个被打开的文件;
r :代表顶层目录 (root directory);
F :该文件被打开了,不过在等待回应中;
m :可能为分享的动态函数库;
lsof :列出被程序所打开的文件文件名
[root@study ~]# lsof [-aUu] [+d]
选项与参数:
-a :多项数据需要“同时成立”才显示出结果时!
-U :仅列出 Unix like 系统的 socket 文件类型;
-u :后面接 username,列出该使用者相关程序所打开的文件;
+d :后面接目录,亦即找出某个目录下面已经被打开的文件!
[root@shark ~]# lsof /var/log/messages
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
abrt-watc 732 root 4r REG 253,0 50234 41435338 /var/log/messages
rsyslogd 14809 root 9w REG 253,0 50234 41435338 /var/log/messages
[root@shark ~]# lsof -U -a -u 0 |grep nginx
nginx 706 root 3u unix 0xffff8800d662d800 0t0 16052 socket
nginx 706 root 9u unix 0xffff8800d662cc00 0t0 16053 socket
nginx 706 root 10u unix 0xffff8800d67cf800 0t0 16054 socket
nginx 706 root 11u unix 0xffff8800d67cfc00 0t0 16055 socket
工作管理 jobs
jobs
将一个进程放到后台。
vim ~/.bashrc
之后按下 Ctrl+z
将进程放到后台,此时会看到是停止状态
查看后台的工作进程
jobs -l
fg 调取后台进程到前台
➜ src jobs
[1] + suspended vi thanks.c
➜ src jobs
[1] + suspended vi thanks.c
➜ src fg %1
bg 把后台的暂停的进程启动
➜ src find /
接着按下 `Ctrl+z`
➜ src jobs
[1] + suspended find /
➜ src fg %1
制作高负载 cpu
root@study ~]# echo "scale=100000; 4*a(1)" | bc -lq &
[root@study ~]# echo "scale=100000; 4*a(1)" | bc -lq &
[root@study ~]# echo "scale=100000; 4*a(1)" | bc -lq &
[root@study ~]# echo "scale=100000; 4*a(1)" | bc -lq &
网友评论