目录
[2.3PRI(Priority进程优先级)和 NI(Nice进程谦让值)](#2.3PRI(Priority进程优先级)和 NI(Nice进程谦让值))
[2.4查看 / 修改进程优先级的命令](#2.4查看 / 修改进程优先级的命令)
1.进程状态
1.1Linux内核源代码怎么说
- 为了弄明⽩正在运⾏的进程是什么意思,我们需要知道进程的不同状态。⼀个进程可以有⼏个状 态(在Linux内核⾥,进程有时候也叫做任务)。 下⾯的状态在kernel源代码⾥定义:
cpp
/*
*The task state array is a strange "bitmap" of
*reasons to sleep. Thus "running" is zero, and
*you can test for combinations of others with
*simple bit tests.
*/
static const char *const task_state_array[] = {
"R (running)", /*0 */
"S (sleeping)", /*1 */
"D (disk sleep)", /*2 */
"T (stopped)", /*4 */
"t (tracing stop)", /*8 */
"X (dead)", /*16 */
"Z (zombie)", /*32 */
};
- R运⾏状态(running):并不意味着进程⼀定在运⾏中,它表明进程要么是在运⾏中要么在运⾏队列⾥。
- S睡眠状态(sleeping):意味着进程在等待事件完成(这⾥的睡眠有时候也叫做可中断睡眠 (interruptible sleep))。
- D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个 状态的进程通常会等待IO的结束。
- T停⽌状态(stopped):可以通过发送 SIGSTOP 信号给进程来停⽌(T)进程。这个被暂停的 进程可以通过发送 SIGCONT 信号让进程继续运⾏。
- X死亡状态(dead):这个状态只是⼀个返回状态,你不会在任务列表⾥看到这个状态。
- 运行:即进程在调度队列中,进程的状态都是running!
- 阻塞:等待某种设备或者资源就绪(键盘,显示器,网卡,磁盘,摄像头,话筒...)
- OS要管理系统种的各种硬件资源,先描述,再组织!因此,进程状态的变化,表现之一,就是要在不同的队列中进行流动。本质都是数据结构的增删查改。
1.2进程状态查看
- ps aux / ps axj 命令
- ps ajx | head -1 && ps ajx | grep 关键字 打印表头并过滤想要的信息(grep -v反向过滤)
- while :; do ps ajx | head -1 && ps ajx | grep myprocess;sleep 1; done(1秒查一次)
- a:显⽰⼀个终端所有的进程,包括其他⽤⼾的进程。
- x:显⽰没有控制终端的进程,例如后台运⾏的守护进程。
- j:显⽰进程归属的进程组ID、会话ID、⽗进程ID,以及与作业控制相关的信息
- u:以⽤⼾为中⼼的格式显⽰进程信息,提供进程的详细信息,如⽤⼾、CPU和内存使⽤情况等

1.3Z(zombie)-僵⼫进程
- 僵死状态(Zombies)是⼀个⽐较特殊的状态。当进程退出并且⽗进程(使⽤wait()系统调⽤,后⾯讲)没有读取到⼦进程退出的返回代码时就会产⽣僵死(⼫)进程
- 僵死进程会以终⽌状态保持在进程表中,并且会⼀直在等待⽗进程读取退出状态代码。
- 所以,只要⼦进程退出,⽗进程还在运⾏,但⽗进程没有读取⼦进程状态,⼦进程进⼊Z状态
总结产生僵尸进程的原因:子进程已经退出,但父进程没调用 wait () 读取它的退出状态,导致子进程的进程描述符还留在系统进程表里,这种状态就是僵尸进程,标识为 Z。
cpp
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main() {
// 创建子进程
pid_t id = fork();
if (id < 0) {
// fork 失败
perror("fork");
return 1;
}
else if (id > 0) {
// 父进程逻辑:睡眠30秒,期间不处理子进程退出状态
printf("parent[%d] is sleeping...\n", getpid());
sleep(30);
}
else {
// 子进程逻辑:睡眠5秒后退出,成为僵尸进程
printf("child[%d] is begin Z...\n", getpid());
sleep(5);
exit(EXIT_SUCCESS);
}
return 0;
}
上述代码子进程5秒后退出,但父进程没使用wait()

我们可是在父进程部分的代码增加:
cpp
int status;
wait(&status);
wait(&status) 调用后,父进程会立即进入阻塞状态,直到有子进程退出,然后内核会回收这个子进程的资源(避免僵尸),并把退出状态写入 status,之后父进程才会继续执行后续代码。

1.4僵⼫进程危害
- 进程的退出状态必须被维持下去,因为他要告诉关⼼它的进程(⽗进程),你交给我的任务,我办的怎么样了。可⽗进程如果⼀直不读取,那⼦进程就⼀直处于Z状态?------是的!
- 维护退出状态本⾝就是要⽤数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中, 换句话说,Z状态⼀直不退出,PCB⼀直都要维护?------是的!
- 那⼀个⽗进程创建了很多⼦进程,就是不回收,是不是就会造成内存资源的浪费?------是的!因为数 据结构对象本⾝就要占⽤内存,想想C中定义⼀个结构体变量(对象),是要在内存的某个位置 进⾏开辟空间!
- 内存泄漏?------是的!
1.5孤⼉进程
- ⽗进程如果提前退出,那么⼦进程后退出,进⼊Z之后,那该如何处理呢?
- ⽗进程先退出,⼦进程就称之为"孤⼉进程"
- 孤⼉进程被1号init进程领养,当然要有init进程回收喽。
- 孤儿进程会被1号进程(通常是
init或systemd)接管并回收,以避免资源泄漏。
cpp
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h> // 补充pid_t类型的头文件,避免编译警告
int main() {
// 创建子进程
pid_t id = fork();
// 检查fork是否失败
if (id < 0) {
perror("fork");
return 1;
}
// 子进程逻辑
else if (id == 0) {
printf("I am child, pid : %d\n", getpid());
sleep(10); // 子进程睡眠10秒
}
// 父进程逻辑
else {
printf("I am parent, pid: %d\n", getpid());
sleep(3); // 父进程睡眠3秒后退出
exit(0);
}
return 0;
}

1.5.1如何结束孤儿进程
如下,我们看见父进程退出后孤儿进程无法用 Ctrl+C 结束,因为Ctrl+C 发送的 SIGINT 信号仅作用于终端前台进程组,父进程退出后,孤儿进程被 1 号进程接管并脱离原前台进程组,进入后台,因此收不到该信号,无法响应 Ctrl+C。
我们可以使用kill指令结束孤儿进程
kill -9 进程号

2.进程优先级
2.1基本概念
- cpu资源分配的先后顺序,就是指进程的优先权(priority)。
- 优先权⾼的进程有优先执⾏权利。配置进程优先权对多任务环境的linux很有⽤,可以改善系统性 能。
- 还可以把进程运⾏到指定的CPU上,这样⼀来,把不重要的进程安排到某个CPU,可以⼤ 改善 系统整体性能。
总结:
是什么?
是进程得到CPU资源的先后顺序
为什么?
目标资源稀缺,导致通过优先级确认谁先谁后的问题!
怎么办?
优先级在linux中也是一种数字,int,task_struct
值越低,优先级越高,反之,优先级越低
基于时间片的分时操作系统,考虑公平性,优先级可能变化,但是变化幅度不能太大
优先级vs权限
优先级:能得到资源,先后的问题。
权限:是都能得到某种资源。
2.2查看系统进程
在linux或者unix系统中,⽤ps‒l命令则会类似输出以下⼏个内容:

我们很容易注意到其中的⼏个重要信息,有下:
- UID: 代表执⾏者的⾝份
- PID: 代表这个进程的代号
- PPID:代表这个进程是由哪个进程发展衍⽣⽽来的,亦即⽗进程的代号
- PRI:代表这个进程可被执⾏的优先级,其值越⼩越早被执⾏
- NI:代表这个进程的nice值
ls -n:用数字 UID/GID 代替用户名 / 组名
所以Linux系统通过比对当前用户的UID与文件权限设置,来判断用户是否具备操作该文件的权限。

2.3PRI(Priority进程优先级 )和 NI(Nice进程谦让值)
- PRI也还是⽐较好理解的,即进程的优先级,或者通俗点说就是程序被CPU执⾏的先后顺序,此 值越⼩进程的优先级别越⾼
- 那NI呢?就是我们所要说的nice值了,其表⽰进程可被执⾏的优先级的修正数值
- PRI值越⼩越快被执⾏,那么加⼊nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice
- 这样,当nice值为负值的时候,那么该程序将会优先级值将变⼩,即其优先级会变⾼,则其越快 被执⾏
- 所以,调整进程优先级,在Linux下,就是调整进程nice值
- nice其取值范围是-20⾄19,⼀共40个级别。
- PRI:进程的优先级,默认:80
- NI:进程优先级的修正数据,又称nice值
- 进程真实的优先级=默认PRI值(80)+ NI
2.4查看 / 修改进程优先级的命令
修改进程优先级:
- 使用top指令后按"r"‒>输⼊进程PID‒>输⼊nice值
- 其他调整优先级的命令:nice,renice
- 系统函数:
查看进程优先级:
ps -al | head -1 && ps -al | grep 进程名

2.5竞争、独⽴、并⾏、并发
- 竞争性: 系统进程数⽬众多,⽽CPU资源只有少量,甚⾄1个,所以进程之间是具有竞争属性的。为 了⾼效完成任务,更合理竞争相关资源,便具有了优先级
- 独⽴性: 多进程运⾏,需要独享各种资源,多进程运⾏期间互不⼲扰
- 并⾏: 多个进程在多个CPU下分别,同时进⾏运⾏,这称之为并⾏(比如有两个CPU,两个进程在不同CPU上同时运行,这两个进程称之为并行)
- 并发: 多个进程在⼀个CPU下采⽤进程切换的⽅式,在⼀段时间之内,让多个进程都得以推进,称之为并发(多个进程共享同一个CPU资源)
