进程(Process)
概念
进程,其实就是一个运行中的程序副本,之所有称为副本,是因为同一个程序是可以运行为多个进程的。
在进程的运行过程中,内核需要记录进程的运行状态,Linux 内核使用固定格式为 task struct(任务结构体)的结构来存储进程信息。
父子进程
内核启动完毕后,创建的第一个进程是 init (初始化)进程,它是负责用户空间所有进程管理的进程,进程号为 1。
除了 init 进程外,每一个进程都是由其父进程创建的,所以进程实际上是有父子关系的。
父进程创建子进程是通过 fork 自身而来,创建子进程时父进程还需要向内核发起申请,fork 就是向内核申请的一个操作。
并且,如果要销毁一个子进程,这个销毁操作也是由父进程操作的。
在 github 里面 fork 别人的项目实际上就是把别人的项目往自己的仓库 copy 了一份,在这里子进程实际上也是父进程按照自己的模样来创建的。
其实存在进程号为 0 的进程,该进程的作用是用来启动 init 进程,启动完毕后就自动销毁了。
进程的优先级
当有多个进程需要被执行时,该优先执行哪个进程是由进程的优先级决定的。
在 Linux 内核 2.6 后,进程的优先级被限定在 0 到 139,一共 140 个优先级。
这些优先级又可分为如下几类:
- 1-99:实时优先级,数字越大,优先级越高,用户不可管理;
- 100-139:静态优先级,数字越小,优先级越高,用户可管理;
Linux 内核,为了能快速找到各个优先级的进程,创建了 140 个执行队列,每个优先级对应一个队列。
所以当内核需要调度某个优先级的进程时,直接到对应的队列取得即可。
由于进程的执行过程中 CPU 调度是根据时间片轮转来的,所以一个进程并不是从开始执行就一直执行到结束,中间 CPU 可能会调用其它进程的,此时没执行完的队列该放在哪儿呢?
副本队列。
每个执行队列有一个副本队列,存放着已经执行过的过期进程,所以实际上有 280 个进程队列。
进程的Nice值
在 Linux 系统中,Nice 值的范围从 -20 到 +19(不同系统的值范围是不一样的),正值表示低优先级,负值表示高优先级,值为零则表示不会调整该进程的优先级。具有最高优先级的程序,其 Nice 值最低,所以在 Linux 系统中,值 -20 使得一项任务变得非常重要;与之相反,如果任务的 Nice 为 +19,则表示它是一个高尚的、无私的任务,允许所有其他任务比自己享有宝贵的 CPU 时间的更大使用份额,这也就是 Nice 的名称的来意。
进程在创建时被赋予不同的优先级值,而如前面所说,Nice 的值是表示进程优先级值可被修正数据值,因此,每个进程都在其计划执行时被赋予一个 Nice值,这样系统就可以根据系统的资源以及具体进程的各类资源消耗情况,主动干预进程的优先级值。在通常情况下,子进程会继承父进程的 Nice 值,比如在系统启动的过程中,init 进程会被赋予 0,其他所有进程继承了这个nice值(因为其他进程都是init的子进程)。
进程的优先级调整
进程的优先级可通过 Nice 值来调整,而调整 Nice 值可使用 nice
命令,使用格式如下:
nice [OPTION] [COMMAND [ARG]...]
OPTION:常用选项
-n #:指定 Nice 值为 #,默认为 10;
COMMAND [ARG]...:
COMMAND:要执行的命令(进程);
ARG:参数;
例:以 Nice 值为 5 运行 htop
命令。
nice -n 5 htop
可通过
ps axo pid,comm,ni,pri
查看进程的 Nice 值。
ni
为 Nice 值,pri
为优先级。
如果要对调整正在运行的进程的 Nice 值,则可使用 renice
,使用格式如下:
renice -n <priority> <pid> ...
priority:要调整的优先级;
pid:要调整进程的进程号;
例:调整进程号为 5376 的进程 Nice 值为 8。
renice -n 8 5376
普通用户一般只能调大 Nice 值,调低优先级,而管理员用户则可以随意调整。
进程信息文件
Linux 进程信息保存在 /proc
目录,每个进程的信息按进程号划分在不同的目录,如下:
在每个进程号目录下可通过 cmdline
文件查看到该进程是由什么命令创建。
例:查看初始化进程是由哪个命令启动。
[root@zzehost 1]# cat cmdline
/sbin/init
进程管理工具
pstree
pstree
命令用来显示进程树,下面是使用 CentOS 7 的执行结果:
再看一下 CentOS 6 的执行结果:
systemd和init进程的区别
在上面的介绍中我们已经说了内核启动完毕后创建的第一个进程是 init 进程,为什么我们现在看到的是 systemd 呢?
因为 init 进程是在 Linux 6 的时候,在 CentOS 7 第一个进程被改为了 systemd,下面是它们的区别:
init 进程:
- 一是启动时间长,init 是串行启动,只有前一个进程启动完,才会启动下一个进程;
- 二是启动脚本复杂,init 进程只是执行启动脚本,不管其他事情,脚本需要自己处理各种情况,这往往使得脚本变得很长;
- 由 Linux 内核加载运行,位于
/sbin/init
,是系统中第一个进程,PID 永远为 1;
systemd 进程:
- 按需启动服务,减少系统资源消耗;
- 尽可能并行启动进程,减少系统启动等待时间;
- 由 Linux 内核加载运行,位于
/usr/lib/systemd/systemd
,是系统中第一个进程,PID 永远为 1;
ps
ps
命令可用来查看系统上所有进程在命令执行这一刻的静态信息,使用格式如下:
ps [option]
option 常用选项组合,支持两种风格:
aux:
u:表示以用户为中心组织进程状态信息显示;
a:所有与终端相关的进程;
x:所有与终端无关的进程;
-ef:
-e:所有进程,相当于 ax;
-f:显示完整格式的进程信息;
-ejH:
-j:以任务格式显示;
-H:以进程层级格式显示进程关系;
-eFH:
-F:显示额外的完整格式的进程信息;
axz:
z:显示 SELinux 的安全上下文;
-u <USER>:显示以 USER 身份创建的进程;
-axo, eo:
o:指定列显示;
例:查看所有进程信息。
可以看到很多进程名是
[COMMAND]
,这些进程是内核线程。
该结果中的每列含义如下:
USER
:每个进程必须是以某个用户的身份来运行的,该列标识进程的属主;PID
:进程的数字 ID 号;%CPU
:占据 CPU 的百分比;%MEM
:占据内存空间的百分比;%VSZ
:Virtual memory size,虚拟内存集大小,在线性地址空间占据的真正空间大小;%RSS
:ReSident size,常驻内存集大小,不能被交换分区交换,在进程运行时必须位于内存空间的数据大小;TTY
:以哪个终端启动,?
标识与中终端无关;STAT
:进程状态。START
:启动时间;TIME
:启动时长;COMMAND
:启动该进程的命令;NI
:NICE 值,;PRI
:priority,优先级;PSR
:processor,运行在那颗 CPU;RTPRIO
:实时优先级;
进程状态
STAT
的可选值如下:
R
:running,运行中;S
:interruptable sleeping,可中断睡眠;D
:uninterruptable sleeping,不可中断睡眠;T
:stopped,停止态;Z
:zombie,僵死态;+
:前台进程;l
:多线程进程;N
:低优先级进程;<
:高优先级进程;s
:session leader,会话创建的领导者,一个进程启动后可能会启动很多跟它相关的进程,这种进程就是 session leader 进程;
pgrep&pkill
pgrep
用来筛选指定条件的进程进行查看,而 pkill
则是用来筛选指定条件的进程杀掉,这两个命令的使用格式相同,如下:
pkill [option]
pgrep [option]
optioin:常用选项
-u <user>:筛选有效用户为 user 的进程;
-U <user>:筛选实际用户为 user 的进程;
-t <terminal>:筛选与指定终端相关的进程;
-a:显示完整格式的命令;
-l:显示进程名称;
-P <ppid>:筛选父进程为 ppid 的子进程;
拥有 SUID 的可执行程序运行起来的进程有可能出现执行命令的用户权限和命令实际运行时拥有的用户权限不同,执行命令的用户为实际用户,命令实际运行使用的权限对应的用户为有效用户。
pidof
pidof
可根据进程名获取到进程的 PID 号,使用格式如下:
pidof <pname>
pname:进程名称
例:显示 sshd
服务的进程号。
[root@zzehost ~]# pidof sshd
2907 1305
top
top
命令可以以动态刷新的方式显示当前系统进程信息,默认以占用 CPU 从高到低排序。
使用格式如下:
top [option]
option:常用选项
-d #:指定刷新间隔为 # 秒;
-b:以批次方式翻页刷新;
-n #:显示 # 批次,与 -b 合用;
第一行中各列信息如下:
20:59:54
:当前系统时间;up 10:51
:系统运行时长;1 user
:当前有 1 个用户登入到系统;load average 0.00 0.01 0.05
:平均负载,指的过去 1 分钟、5 分钟、15 分钟内 CPU 队列中等待运行的任务个数/时间,
第二行中各列信息如下:
Tasks:93 total
:当前一共有 93 个进程;1 running
:处于运行状态的有 1 个;92 sleeping
:处于 sleeping 状态的有 92 个;0 stopped
:处于停止状态的有 0 个;0 zombie
:处于僵死状态的有 0 个;
第三行中显示的是不同模式下所占 CPU 时间百分比,具体如下:
us
:user,运行(未调整优先级的)用户进程的 CPU 时间;sy
:system,运行内核进程的 CPU 时间;ni
:niced,运行已调整优先级的用户进程的 CPU 时间;wa
:IO wait,用于等待 IO 完成的 CPU 时间;hi
:处理硬件中断的 CPU 时间;si
:处理软件中断的 CPU 时间;st
:这个虚拟机被 hypervisor 偷去的 CPU 时间(译注:如果当前处于一个 hypervisor 下的 vm,实际上 hypervisor 也是要消耗一部分 CPU 处理时间的);
第四行中各列信息描述的是内存占用信息,如下:
KiB Mem:997956 total
:物理内存总大小;502908 free
:空闲内存大小;136240 used
:已使用大小;358808 buff/cache
:缓冲区/缓存大小;
第五行中各列信息描述的是 Swap 分区的占用信息,如下:
KiB Swap:819196 total
:Swap 分区总大小;819196 free
:空闲大小;0 used
:已用大小;672076 avail Mem
:可用空间;
第五行后各列的信息所表示的信息如下:
PID
:进程号;USER
:属主;PR
:优先级;NI
:Nice 值;VIRT
:虚拟内存集;RES
:常驻内存集;SHR
:共享内存大小;S
:简要状态,R
表示运行;%CPU
:CPU 占用比例;%MEM
:内存占用比例;TIME
:累积运行时长;COMMAND
:启动该进程的命令;
该命令时交互式的,在运行过程中还可根据输入的内置命令内容更改输出信息的排序(从高到低):
P
:以占用的 CPU 百分比从高,占用指的是上次刷新时间到这次刷新的时间内占用的百分比,默认值;T
:以累计占据 CPU 时长排序;M
:以占据内存百分比从高到底排序;l
:显示/不显示第一行内容;1
:分行显示每颗 CPU 的平均负载;t
:切换第三行的显示格式,以及隐藏/显示第二、三行;m
:切换第四、五行的显示格式,以及隐藏/显示第四、五行;q
:退出;s
:修改刷新时间间隔,默认 3 秒;k
:杀死指定进程;
htop
htop
是一个比 top
更强大的交互式的、动态刷新的进程管理工具,
它需要添加 epel 源后才可使用 yum 安装。
直接执行 htop
即可查看到效果:
在底部可以看到可以通过 F1
到 F10
来执行相关的操作,例:
F1
:帮助;F2
:设置;F3
:查找;F4
:过滤;F5
:以树状结构显示进程信息;F6
:指定排序列;F7
:减低进程的 Nice 值;F8
:增加进程的 Nice 值;F9
:杀掉指定进程;F10
:推出;
跟踪选定进程发起的系统调用
选定进程后,按 s
键可查看进程发起了哪些系统调用,例:
跟踪选定进程打开的文件
选定进程后,按 l
键可查看进程打开了哪些文件,例:
有可能出现这种情况:
这是因为该功能是依赖于 lsof
命令的,所以要先安装该命令,如下:
yum install -y lsof
显示进程树
按 t
键可以树状结构查看进程的父子关系,例:
评论区