银医网站建设方案,汕头建设银行协华支行,高端网站建设推来客网络,wordpress 固定链接404文章目录1 阻塞与挂起1.1 阻塞1.2 挂起2 进程状态前言#xff1a; 当我们在Windows下双击运行一个程序#xff0c;或是在Linux下通过 ./ 加载运行一个程序#xff0c;是否就代表对应的进程就一直处在运行状态呢#xff1f;其实不然#xff0c;一个进程有许多不同的状态。当…
文章目录1 阻塞与挂起1.1 阻塞1.2 挂起2 进程状态前言 当我们在Windows下双击运行一个程序或是在Linux下通过 ./ 加载运行一个程序是否就代表对应的进程就一直处在运行状态呢其实不然一个进程有许多不同的状态。当我们加载运行一个程序时并不表示其对应的进程就是一直在运行的以Windows下运行程序来说我们可以打开多个软件多个应用“同时”运行但实际上这些进程并不是同时处在运行状态的CPU会不断切换调度每个需要运行的进程分时运行由于其切换调度的速度远超人的感知范围因此会让人觉得所有程序在同时运行。在Linux内核里进程有时也叫做任务如下是kernel源代码中定义的不同的进程状态也是本文接下来要讲述的内容。 Linux内核中进程状态定义
/*
* 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 */
};1 阻塞与挂起
1.1 阻塞 阻塞 进程因为等待某种条件资源就绪而导致的一种不推进的状态如我们常说的卡住了一般页面无法响应、因网络中断下载任务无法继续执行等。或者说阻塞就是当前进程不被CPU调度。事实上进程要通过等待的方式等某个具体的资源被别人用完或者有了某个资源之后再使用该资源。 我们知道操作系统对软硬件做管理其方式可以被总结为先描述再组织 。其中进程被描述为结构体 task_struct 硬件被管理时同样也是被描述为一个结构体如 struct dev 每个软硬件对应的结构体中都包括了关于自身的信息。值得注意的是在每个硬件对应的结构体中还包含了指向进程控制块 PCBtask_struct 的指针可以认为该指针指向了一个进程队列的队头通过该指针可以对某个进程队列进行管理。事实上一个进程处在运行状态时可以表示该进程处在CPU进程调度的运行队列中而当某个进程因等待某种资源而无法继续推进时通常是等待某种硬件资源如磁盘、网卡、键盘等CPU就会将该进程调出当前的运行队列并调入其所等待资源对应的等待队列中此时该进程就处在一种 阻塞 状态。换句话说当某个进程处于阻塞状态时就表示该进程对应的结构体 task_struct 正在某种被操作系统管理的资源下排队当该资源准备就绪后再将该进程调回CPU的运行队列中继续排队运行。 1.2 挂起 挂起 当因为等待某种资源就绪进程对应PCB由运行队列转至资源下的等待队列时考虑到内存空间紧张CPU会将因为等待而暂时无法运行的进程对应的代码和数据先由内存转移到磁盘中此时进程即为挂起状态等到该进程可以被运行时再将对应的代码和数据由磁盘转移回内存中。 2 进程状态 R(running)运行状态 当进程处于 R 状态时并不表示该进程一定在运行中它表示了该进程要么是在运行中要么是在运行队列中排队。 S(sleeping)睡眠状态 意味着进程在等待某种资源就绪该状态有时也称为 可中断睡眠状态interruptible sleep 其本质就是一种阻塞状态。 D(disk sleep)磁盘休眠状态 有时也称为 不可中断睡眠状态uninterruptible sleep 在这个状态的进程通常会等待IO的结束。一旦一个进程处于 D 状态则该进程不可被杀死只有当该进程主动 “醒来切换为其它状态” 其才能被终止。在绝大部分情况下都不会出现 D 状态哪怕出现了一个 D 状态的进程则表示当前的系统濒临崩溃。因为在正常情况下 D 状态只是一瞬间的状态而出现该状态则表示当前磁盘空间严重不足磁盘无法满足数据写入的需求所以对应进程只能一直等待进而出现 D 状态若此时再出现几个 D 状态进程系统就很可能崩溃死机最后只能重启。
示例
这里编写了一个死循环代码 test01.c 通过 ./ 的方式运行编译生成的二进制文件 mytest 后通过命令 ps axj | head -1 ps axj | grep mytest | grep -v grep 查看对应的进程状态如下 可以发现虽然该进程看上去似乎一直在运行但所显示的进程状态却表示其处于 S睡眠状态 。这是由于在这段死循环中代码中我们需要显示器资源来显示输出内容这是一个进程显然显示器资源不会一直只供该进程使用即该进程的运行需要等待显示器资源的就绪也就是上述所说的睡眠状态。
下面我们又将代码中的输出语句注释使该死循环中为空重新编译运行再次查看相应进程状态此时可以看到该进程处于 R运行状态 这是因为此时该进程不需要等待某个资源就绪因此其一直处于运行状态。 需要注意 与上述所说的 R / S 状态不同这里示例中所显示的状态都多了一个 号这是表示该进程在前台运行此时我们可以通过 Ctrl C 的方式来终止进程如果没有 号则表示该进程在后台运行此时可以通过 kill -9 进程PID 的方式来终止进程。
T(stopped)停止状态 可以通过 kill 命令发送 SIGSTOP 信号给进程来使其进入停止状态。被暂停的进程可以再通过发送 SIGCONT 信号让进程继续运行。 示例 t(tracing stop)追踪状态 当进程正在被跟踪时就处于 t 这个特殊状态其本质上也是一种停止状态。例如调试程序时触发断点而停止运行此时对应进程就处在 t 状态。
示例 X(dead)死亡状态 该状态只是一个返回状态瞬时状态我们不会在任务列表里看到这个状态。事实上我们创建进程无非是想通过进程完成一些任务而对于任务完成结果我们可能关心也可能不关心这就涉及到一个概念 – 退出码 。所谓 退出码 其实就是我们编写的代码中最常见的 main()主函数中的{return 0}也就是return的那个数字 我们可以通过 echo $ 命令来查看进程退出码。
示例 Z(zombie)僵尸状态 / 僵尸进程 僵尸状态 是一个比较特殊的状态。当进程退出并且父进程使用wait() 系统调用没有读取到子进程退出的返回代码时就会出现僵尸状态。 僵尸进程会以终止状态保持在进程表中并且会一直等待父进程读取退出状态代码。 只要子进程退出父进程还在运行但父进程没有读取子进程状态子进程就会进入僵尸状态。 示例 僵尸进程的危害 进程的退出状态必须被维持下去因为它要告诉关心它的进程父进程你交给我的任务我办的怎么样了。可如果父进程一直不读取子进程状态那子进程就会一直处于僵尸状态。维护退出状态本身需要用数据维护也属于进程基本信息所以保存在 task_struct(PCB) 中换句话说僵尸状态一直持续其进程对应 PCB 就需要一直被维护。如果一个父进程创建了很多子进程但就是不回收将造成内存资源的浪费内存泄漏因为数据结构对象本身就要占用内存。 以上是我对Linux中进程状态相关的一些学习记录总结如有错误希望大家帮忙指正也欢迎大家给予建议和讨论谢谢