1、基础
1.1、什么是进程
开发写的代码我们称为程序,那么将开发的代码运行起来。我们称为进程。总结一句话就是:当我们运行一个程序,那么我们将运行的程序叫进程。
1、当程序运行为进程后,系统会为该进程分配内存,以及进程运行的身份和权限。
2、在进程运行的过程中,系统会有各种指标来表示当前运行的状态。
1.2、程序和进程的区别
1、程序是数据和指令的集合,是一个静态的概念。
比如/bin/ls、/bin/cp等二进制文件。同时程序可以长期存在系统中
2、进程是程序运行的过程,是一个动态的概念。
进程是存在生命周期的概念的,也就是说进程会随着程序的终止而销毁,不会永久运行在系统中。
1.3、进程的生命周期
1.3.1、进程生命周期图

1.3.2、进程生命流程说明
当父进程接收到任务调度时,会通过fock派生子进程来处理,那么子进程会继承父进程属性。
1、子进程在处理任务代码时,父进程其实不会进入等待,其运行过程是由linux系统进行调度的。
2、子进程在处理任务代码后,会执行退出,然后唤醒父进程来回收子进程的资源。
3、如果子进程在处理任务代码过程中异常退出,而父进程却没有回收子进程资源,会导致子进程虽然运行实体已经消失,但仍然在内核的进程表中占据一条记录,长期下去对于系统资源是一个浪费。(僵尸进程)
4、如果子进程在处理任务过程中,父进程退出了,子进程没有退出,那么这些子进程就没有父进程来管理了,由系统的system进程管理。(孤儿进程)
PS:每个进程都父进程的PPID,子进程则叫PID。
1.4、僵尸进程与孤儿进程区别
我们知道在unix/linux中,正常情况下,子进程是通过父进程创建的,子进程在创建新的进程。任何一个子进程(init除外)在exit()之后,并非马上就消失掉,而是留下一个称为僵尸进程(Zombie)的数据结构,等待父进程处理。
孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。
僵尸状态是一个比较特殊的状态,当进程退出父进程(使用wait()系统调用)没有读取到子进程退出的返回代码时就会产生僵尸进程。僵尸进程会在以终止状态保持在进程表中,并且会一直等待父进程读取退出状态代码。
僵尸进程与孤儿进程的区别:
孤儿进程是子进程还在运行,而父进程挂了,子进程被init进程收养。僵尸进程是父进程还在运行但是子进程挂了,但是父进程却没有使用wait来清理子进程的进程信息,导致子进程虽然运行实体已经消失,
但是仍然在内核的进程表中占据一条记录,这样长期下去对于系统资源是一个浪费。僵尸进程将会导致资源浪费,而孤儿则不会。
那么如何避免僵尸进程呢
(1)fork两次
原理是将子进程成为孤儿进程,从而其的父进程变为init进程,通过init进程可以处理僵尸进程
(2)通过信号机制
子进程退出时向父进程发送SIGCHILD信号,父进程处理SIGCHILD信号。在信号处理函数中调用wait进行处理僵尸进程
————————————————
版权声明:本文为CSDN博主「Cynthia_wpp」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_41050155/article/details/81945208
2、监控进程状态
2.1、静态查看进程
2.1.1、ps命令
~]# ps -aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.2 125368 3920 ? Ss 07:19 0:00 /usr/lib/systemd/systemd --s
root 2 0.0 0.0 0 0 ? S 07:19 0:00 [kthreadd]
root 4 0.0 0.0 0 0 ? S< 07:19 0:00 [kworker/0:0H]
root 6 0.0 0.0 0 0 ? S 07:19 0:00 [ksoftirqd/0]
root 7 0.0 0.0 0 0 ? S 07:19 0:00 [migration/0]
root 8 0.0 0.0 0 0 ? S 07:19 0:00 [rcu_bh]
USER 启动进程的用户
PID 进程运行的ID号
%CPU 进程占用CPU百分比
%MEM 进程占用内存百分比
vSz 进程占用虚拟内存大小(单位KB)
RSS 进程占用物理内存实际大小(单位KB)
TTY 进程是由哪个终端运行启动的tty1、pts/O等 ?表示内核程序与终端无关
STAT 进程运行过程中的状态 man ps (/STATE)
START 进程的启动时间
TIME 进程占用CPU的总时间(为0表示还没超过秒)
COMMAND 程序的运行指令,[方括号]属于内核态的进程。没有[]的是用户态进程。
2.1.2、STAT状态含义
]# ps -aux | awk -F ' ' '{print $8}' | sort | uniq -c | sort -k1 -nr
54 S<
21 S
11 Ss
4 Ssl
3 S+
2 Ss+
2 SN
2 R+
1 STAT
1 S<sl
1 R
STAT基本状态 描述 STAT状态+符号 描述
R 进程运行 s 进程是控制进程,Ss进程的领导者,父进程
S 可中断睡眠 < 进程运行在高优先级上,S<优先级较高的进程
T 进程被暂停 N 进程运行在低优先级上,SN优先级较低的进程
D 不可中断进程 + 当前进程运行在前台,R+该表示进程在前台运行
Z 僵尸进程 | 进程是多线程的,SI表示进程是以线程方式运行
2.2、动态查看进程
2.2.1、top命令
~]# top
top - 13:18:11 up 5:58, 2 users, load average: 0.00, 0.01, 0.05
Tasks: 97 total, 1 running, 96 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.3 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 1910108 total, 1537404 free, 165272 used, 207432 buff/cache
KiB Swap: 2002940 total, 2002940 free, 0 used. 1594380 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
2518 root 20 0 0 0 0 S 0.3 0.0 0:04.07 kworker/0:1
2698 root 20 0 162096 2232 1548 R 0.3 0.1 0:00.01 top
1 root 20 0 125368 3920 2588 S 0.0 0.2 0:00.80 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd
4 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H
6 root 20 0 0 0 0 S 0.0 0.0 0:00.06 ksoftirqd/0
7 root rt 0 0 0 0 S 0.0 0.0 0:00.00 migration/0
8 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_bh
2.2.2、top常用按键显示介绍
字母 含义
h 查看帮助
1 数字1,显示所有CPU核心的负载
z 以高亮显示数据
b 高亮显示处于R状态的进程
M 按内存使用百分比排序输出
P 按CPU使用百分比排序输出
q 退出top
2.2.3、top-每列含义详解
]# top
top - 13:25:30 up 6:06, 2 users, load average: 0.00, 0.01, 0.05
Tasks: 98 total, 1 running, 97 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 1910108 total, 1537468 free, 165172 used, 207468 buff/cache
KiB Swap: 2002940 total, 2002940 free, 0 used. 1594464 avail Mem
Tasks: 98 total 当然进程的总数
1 running 正在运行的进程数
128 sleeping 睡眠的进程数
0 stopped 停止的进程数
0 zombie 僵尸进程数
%Cpu(s): 0.7 us 系统用户进程使用CPU百分比
0.0 sy 内核中的进程占用CPU百分比,通常内核是于硬件进行交互
100.0 id 空闲CPU的百分比
0.0 wa CPU等待lO完成的时间
0.0 hi 硬中断,占的CPU百分比
o.0 si 软中断,占的CPU百分比
0.0 st 比如虚拟机占用物理CPU的时间
2.2.4、什么是系统中断
3、进程状态切换-实战
3.1、示例1-进程状态切换
3.1.1、终端1-vi操作
3.1.2、终端2-查看进程状态-S+
S 表示睡眠模式
+ 表示前台运行
]# ps aux | grep test | grep -v grep
root 2752 0.0 0.0 126300 1696 pts/0 S+ 13:47 0:00 vi test
3.1.3、终端1-挂起操作
3.1.4、终端2-查看进程状态-T
T 表示停止
]# ps aux | grep test | grep -v grep
root 2752 0.0 0.0 126300 1696 pts/0 T 13:47 0:00 vi test
3.2、示例2-不可中断进程
3.2.1、使用tar打包文件时,可以通过终端不断查看状态,由S+,R+、D+
S+ 表示可中断睡眠,在前台运行
~]# ps -aux | grep etc.tar | grep -v grep
root 2843 17.0 0.1 124580 2292 pts/0 S+ 14:22 0:03 tar czvf etc.tar.gz /etc/ /usr/ /var/
R+ 表示进程运行,在前台运行
~]# ps -aux | grep etc.tar | grep -v grep
root 2843 17.5 0.1 124672 2380 pts/0 R+ 14:22 0:03 tar czvf etc.tar.gz /etc/ /usr/ /var/
D+ 不可中断进程,在前台运行
~]# ps -aux | grep etc.tar | grep -v grep
root 2843 17.5 0.1 124672 2380 pts/0 D+ 14:22 0:03 tar czvf etc.tar.gz /etc/ /usr/ /var/
3.3、示例3-僵尸进程
3.3.1、安装gcc编译器
3.3.2、准备C语言代码
cat >zombie_test.c<<'EOF'
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
pid_t pid;
pid = fork();
if (pid==0) {
int iPid =(int)getpid();
fprintf(stderr,"子进程,%d\n",iPid);
sleep(1);
fprintf(stderr,"Child exits\n");
return EXIT_SUCCESS;
}
int iPid = (int)getpid();
fprintf(stderr,"父进程,%d\n",iPid);
fprintf(stderr,"sleep....\n");
sleep(360);
fprintf(stderr,"parent exits\n");
return EXIT_SUCCESS;
}
EOF
3.3.3、编译程序
~]# gcc zombie_test.c -o zombie_test
~]# ll
-rwxr-xr-x 1 root root 8656 Apr 22 14:33 zombie_test
-rw-r--r-- 1 root root 520 Apr 22 14:31 zombie_test.c
3.3.4、运行程序
]# ./zombie_test
父进程,3055
sleep....
子进程,3056
Child exits
# 此时子进程,运行退出
3.3.5、查询进程状态
]# ps -aux | grep test | grep -v grep
root 3055 0.0 0.0 4212 352 pts/1 S+ 14:34 0:00 ./zombie_test
root 3056 0.0 0.0 0 0 pts/1 Z+ 14:34 0:00 [zombie_test] <defunct> # 此时发现子进程已经是僵尸进程了
3.3.6、kill僵尸进程,发现kill不掉
[root@192 tmp]# kill -9 3056
[root@192 tmp]# ps -aux | grep test | grep -v grep
root 3055 0.0 0.0 4212 348 pts/1 S+ 14:38 0:00 ./zombie_test
root 3056 0.0 0.0 0 0 pts/1 Z+ 14:38 0:00 [zombie_test] <defunct> # 还是存在,杀不掉
3.3.7、只能kill掉主进程,让僵尸进程变为孤儿进程,由init进程进行接管回收
kill -9 3055
找到僵死进程的父进程,kill掉父进程,那么僵死进程将变为孤儿进程,孤儿进程在系统中由init进程接管,init进程将回收僵死进程的资源;或者reboot
因为僵尸进程不会被杀死;