文章目录
1.百度搜索
2.对进程状态的认识
一个进程所具有的状态为操作系统的进程状态设计提供了理论依据。实际上不同的操作系统设计不同的进程状态
2.0创建状态
当一个进程被创建但没有入队列,即代码和数据被拷贝➕建立PCB结构体➕ 为其分配一个唯一的进程标识符(PID)[不是不就绪的状态]实际上 linux内核不存在这种状态 这种状态只是为了更好的理解而描述的 在实际中 一个进程被创建后就会入运行队列
2.1就绪状态
进程已经满足运行条件,PCB进入CPU运行队列,排队等待系统分配CPU资源
2.2运行状态
PCB被调度到CPU运行队列中且已被分配CPU资源。只有运行状态下的进程才能占用CPU资源
2.3阻塞状态
阻塞状态
- 当一个进程因需要等待某些非CPU资源就绪无法继续执行时,就会进入阻塞状态。如: 等待用户输入、等待磁盘IO操作完成等。在阻塞状态下,进程会被调度到阻塞队列,不会占用CPU资源。只有当进程所等待的非CPU资源就绪后,进程才会从阻塞队列调度到运行队列(就绪状态)。
- 系统中存在各种资源: CPU 网卡 磁盘 显卡 等
- 系统中不只是存在一种队列 : CPU配套的运行队列 阻塞队列等
- 当运行队列某一进程需要使用磁盘资源比如要向磁盘写数据或必须使用磁盘进行操作 此时处于运行队列的这个进程会被安排到磁盘配套队列的后面排队
- 当磁盘配套的进程的第一个轮到访问进程时 此进程会插队到CPU的运行队列 CPU会执行当前进程对应的代码 这段代码的目的就是向磁盘写数据
- 当一个本处于CPU运行队列的进程因需要访问磁盘而去磁盘配套进程排队时 此时CPU会执行后面的其他进程 而此时等待磁盘资源就绪的那些进程 组成的队列叫阻塞队列
- 阻塞队列中的进程不是在等待CPU 所以无法称他们处于运行态 我们称他们处于 阻塞状态
- CPU被很多进程占满了资源或者 进程等待某种资源 长时间等不到调度
2.4挂起状态
- 当内存快不足时,操作系统会将长时间不执行或者处于低优先级状态的进程的代码和数据置换出内存并存储到磁盘上的SWAP分区中。
- PCB(进程控制块)仍存在进程表中。
- 被置换到磁盘中的进程的状态就叫做挂起。
- 挂起状态只是进程的一种状态,表示进程暂时无法执行,仍然需要保留进程的信息以便后续恢复执行。
目的意义作用
释放内存资源,给其他进程提供执行机会。
挂起状态
- 和进程访问某种资源关系不大
- 是内核和操作系统需要维护的状态
挂起状态的认识
- 由于进程太多 内存快被占满时 操作系统会将长时间不执行/无法执行(等待资源) 的进程的代码和数据 移到磁盘 (一个专门的分区[SWAP分区])
- 此时内存中只有一个PCB在
- 被移出的进程的状态就是挂起状态
- 处于挂起状态的进程需要运行时 不是把PCB放到运行队列 而是先把此进程的代码和数据从磁盘移回内存
- 挂起状态/阻塞状态和CPU无关
磁盘的SWAP分区会满吗?
- OS进行置换有成本: 进行IO工作 会影响效率 OS不太喜欢进行置换 除非迫不得已
- 如果磁盘趋于满 此时OS为了让进程得以执行 置换工作极为频繁 OS效率大幅下降 --> 宕机
3.认识LinuxOS下的进程
3.0进程状态的简述
R运行状态(running):
进程正在运行或者在运行队列中等待S睡眠状态(sleeping) /可中断睡眠(interruptible sleep):
即阻塞状态 进程在等待某事件完成 (可被唤醒/中断 如程序中在执行sleep(10);
时 发送kill -19 PID信号)[(阻塞、挂起)]D休眠状态(Disk sleep)/不可中断睡眠状态(uninterruptible sleep):
磁盘休眠/进程休眠 进程通常会等待IO的结束(不可被中断 不可被唤醒)[(IO阻塞、IO挂起)]T信号暂停状态(stopped):
发送 SIGSTOP 信号来暂停进程。可以发送 SIGCONT 信号让进程继续运行。t调试暂停状态(tracing stop):
进程被调试器(如gdb)跟踪调试,暂停了进程的执行。调试器设置了断点或执行了单步调试操作X死亡/终止状态(dead):
多个进程终止 OS需要一个一个回收 但也是一瞬间的 瞬时性很强 只是一个返回状态,无法在任务列表看到这个状态。Z僵尸状态(zombie):
一个已经终止的子进程,但其 父进程/OS 尚未检测到子进程的退出状态。
- 不允许OS释放 处于一个被检测的状态]
- 维持该状态 让父进程/OS识别并回收
- 僵尸进程不会占用系统资源,已经终止并释放了大部分资源。
- 僵尸进程只在进程表中保留一条记录,以便父进程在需要时获取子进程的退出状态。
3.1了解R/S状态
以下代码执行时 状态是S+
while(1)
{
printf("hello linux!\n");
}
- 向显示器(外设)输出数据 显示器不一定准备好 即便准备好 也要等待数据 进程在阻塞队列中待的时间比运行队列长 表现为当前进程为阻塞状态
- 如果注释掉
printf("hello linux!\n");
进程的状态变为R+
不需要访问外设 只运行代码 : 运行状态(可能在运行队列中等待可能正在被CPU调度/执行)
以下代码执行时 状态是S+
int a = 0;
sacnf("%d", &a);
while(1)
{
printf("hello linux!\n");
}
等待输入 – 阻塞状态 S+
+号: 当前进程处于前台进程: 无法执行命令cmd 命令行解释器无法解释命令 可以ctrl+c终止 如何让他在后台执行?
./ test &
.
如何杀死这个进程?
kill -9 PID
3.2D深度睡眠状态
为了省电省钱 企业会在午夜将磁盘转速降低 但是如果此时有大量进程需要访问磁盘 (状态为D) 而磁盘IO效率低下 将有更多的进程处于D状态 此时服务器压力过大 而OS又无法杀死他们 有可能造成OS昏迷或宕机
那么就需要了解以下DD命令
Linux DD命令是一种用于复制和转换文件的命令行工具。它可以从一个文件或设备复制数据,并将其写入另一个文件或设备。DD命令可以用于创建磁盘映像,备份和还原硬盘分区,以及在不同的数据存储格式之间进行转换。以下是一些DD命令的常见用法:
- 复制文件或设备
dd if=/dev/sda of=/dev/sdb
上述命令将/dev/sda设备的内容复制到/dev/sdb设备中。
- 创建磁盘映像
dd if=/dev/sda of=/path/to/image.img
上述命令将/dev/sda设备的内容复制到名为image.img的文件中。
- 转换数据格式
dd if=/path/to/input.img of=/dev/sda bs=512 conv=notrunc
上述命令将名为input.img的文件中的数据写入到/dev/sda设备中,并将块大小设置为512字节。"conv=notrunc"选项表示不截断输出文件。
3.3信号/调试暂停状态
- 当执行死循环时状态为R 发送kill -19 PID 进程暂停 状态为T(不是因为要访问某种资源而主动暂停 而是向他发信号 它被动暂停 ) 发送 kill -18 PID 进程继续 状态变为R
- 对test.c 打开gdb 设置断点 当执行./test 进程开始执行 遇到断点暂停 此时进程状态为t gdb进程状态为S (可以理解为gdb向test发送了kill- 19 PID )
3.4僵尸状态
int main()
{
pid_t id = fork();
if(id < 0)
{
//创建失败
perror("fork");
return 1;
}
else if(id == 0)
{
//child process(task)
while(1)
{
printf("I am child, pid: %d, ppid: %d\n", getpid(), getppid());
sleep(3);
break;
}
exit(0);
}
else
{
//parent process
while(1)
{
printf("I am father, pid: %d, ppid: %d\n", getpid(), getppid());
sleep(1);
}
}
return 0;
}
- 代码和数据已经释放 PCB未释放 且PCB内记录了代码和数据已经退出的信息
- PCB留在内存中 如果不回收 将造成内存泄漏
- 僵尸状态(Zombie)是一个比较特殊的状态。当进程退出并且父进程没有读取到子进程退出的返回代码时就会产生僵死(尸)进程
- 僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
- 只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态
3.5僵尸进程危害
- 僵尸进程的退出状态会一直持续,僵尸进程要告诉父进程/OS 下达的任务执行的如何 父进程一直不读取,那子进程就一直处于Z状态
- 维护退出状态要用数据维护,也属于进程基本信息,保存在task_struct(PCB)中,Z状态一直不退出,PCB一直都要维护 内存中的PCB不及时回收,会造成内存泄漏,导致操作系统内中的可用资源越来越少
- 一个父进程创建了很多子进程,不回收会造成内存资源的浪费 数据结构对象本身就要占用内存 因此会造成内存泄漏
- 僵尸进程本身不会占用系统资源,但如果大量的僵尸进程积累,会占用一定的进程表项和内核资源
- 一个用户能创建的进程是有限的,僵尸进程过多,会导致创建新的子进程失败
3.6孤儿进程
- 父进程提前退出,此时未退出的子进程被称为”孤儿进程“
- 孤儿进程会被1号init进程(可以认为是OS)领养,由init进程回收
- 未来子进程退出,原先的父进程早已不在,需要领养进程将其回收。
3.7僵尸 vs 孤儿
孤儿进程和僵尸进程都可能使系统不能产生新的进程吗
僵尸进程的产生会造成资源泄露需要避免,
孤儿进程的产生一般都是具有目的性的(父进程退出让init回收),并且退出后并不会成为僵尸进程,因此无需特殊处理。
init进程是内核启动的第一个用户级进程,用于完成处理孤儿进程以及其他的一些重要任务。
概念对比理解
僵尸进程:子进程先于父进程退出,父进程没有对子进程的退出进行处理,因此子进程会保存自己的退出信息而无法释放所有资源成为僵尸进程导致资源泄露。 僵尸进程必须使用waitpid/wait接口进行等待 僵尸进程是已经退出运行的进程,无法被杀死
孤儿进程:父进程先于子进程退出,子进程成为孤儿进程,运行在后台,父进程成为1号进程(而孤儿进程的退出,会被1号进程负责任的进行处理,因此不会成为僵尸进程)
守护进程&精灵进程&特殊进程
同一种进程的不同翻译,是特殊的孤儿进程,不但运行在后台,最主要的是脱离了与终端和登录会话的所有联系,也就是默默的运行在后台不想受到任何影响 运行在后台的一种特殊进程,独立于控制终端并周期性地执行某些任务。父进程是1号进程,退出后不会成为僵尸进程
syslogd:系统中的日志服务进程
init:init进程是内核启动的第一个用户级进程,用于完成处理孤儿进程以及其他的一些重要任务。
sshd:远程登录服务进程
vhand:内存置换服务进程