【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行

这篇具有很好参考价值的文章主要介绍了【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

个人主页 : zxctscl
如有转载请先通知

1. 前言

上一篇博客中提到 【Linux】进程初步理解,这次继续来分享与进程有关的知识。

2. Linux的进程状态

Linux的进程状态就是struct task_struct内部的一个属性。
为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态(在Linux内核里,进程有时候也叫做任务)。
下面的状态在kernel源代码里定义:

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):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。

2.1 S状态

检测一下这些状态:
先写一个测试代码:

  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<unistd.h>
  4
  5 int main()
  6 {
  7
  8   while(1)
  9   {
 10     printf("I am a process,pid:%d\n",getpid());
 11   }
 12   return 0;
 13 }

运行代码:发现进程都是出于s状态:
【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行,Linux从入门到入土,linux,chrome,运维
printf在显示器上打的时候,根据冯诺依曼特体系结构,显示器是一个外设,所以CPU在跑当前程序时,要把数据写到内存中,然后刷新到外设上,但是不能保证,每一次打印的时候显示器都是就绪的。相比较CPU来讲,大部分时间这个进程都在等待设备资源是否就绪,如果资源不就绪,当前进程就一直出于S状态。

把代码在printf之前先休眠10秒:
【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行,Linux从入门到入土,linux,chrome,运维

此时发现进程一直出于S状态,可以直接ctrl+c把处于S状态的进程终止掉:
【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行,Linux从入门到入土,linux,chrome,运维
把S的这种状态叫做可中断睡眠,就是处于睡眠状态,依旧可以被外部信息随时打断。

2.2 R状态

那么把代码里面的printf给注释了:
【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行,Linux从入门到入土,linux,chrome,运维
此时进程都是R状态:
【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行,Linux从入门到入土,linux,chrome,运维

2.3 T/t状态

在kill命令中的19号命令,让进程暂停:

【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行,Linux从入门到入土,linux,chrome,运维
直接使用:

kill -19 pid

此时进程就处于T状态
【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行,Linux从入门到入土,linux,chrome,运维

【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行,Linux从入门到入土,linux,chrome,运维

要想让暂停的进程继续运行起来就用18号信号
【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行,Linux从入门到入土,linux,chrome,运维

此时进程又重新运行起来:
【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行,Linux从入门到入土,linux,chrome,运维
但是此时是在后台运行的,要想终止进程,只能使用kill -9。

【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行,Linux从入门到入土,linux,chrome,运维
暂停在之间调试的时候就已经用到了。

打开Makefile加-g选项

  1 testStatus:testStatus.c
  2   gcc -o $@ $^ -g
  3 .PHONY:clean
  4 clean:
  5   rm -f testStatus

在10行打一个断点,然后查看一下进程的运行状态:
【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行,Linux从入门到入土,linux,chrome,运维
遇到断点,进程就暂停下来。

2.4 D状态

D状态是Linux系统比较特有的状态。

D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。

操作系统杀进程的时候时毫无类别的去杀,在写入关键数据的进程是不能被杀掉的,所以操作系统规定,凡是进程在就行数据IO,在等待外设,像磁盘资源时,把状态设为D状态。
D状态不可被杀,深度睡眠,不可中断睡眠,就是一种sleep状态。

消除D状态:1. 让进程自己醒来;2. 重启–断点

3. 僵尸进程和孤儿进程

3.1 僵尸进程

Linux中一个进程的退出,它会将自己的退出信息保留在自己的PCB中。如果不读取PCB中的进程退出消息,那么进程就一直不释放,一般会释放掉代码和数据,但PCB的内核数据结构是一直存在的,直到将来对进程进行等待;如果不等待,那么进程就一直出于僵尸状态。如果读取了这个进程的退出信息或者等待了,那么这个进程才会变成X,进而将进程的信息全部释放。

为了测试重新写一个父子进程代码:

  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<unistd.h>
  4
  5 int main()
  6 {
  7
  8   pid_t id=fork();
  9   if(id==0)
 10   {
 11     //child
 12     int cnt=5;
 13     while(cnt)
 14     {
 15       printf("I am a child,cnt:%d,pid:%d\n",cnt,getpid());
 16       sleep(1);
 17       cnt--;
 18     }
 19
 20   }
 21   else{
 22     //parent
 23     while(1)
 24     { printf("I am parent,running always,pid:%d\n",getpid());
 25       sleep(1);
 26       }
 27   }
 28   return 0;
 29 }

来看一下这个状态:
【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行,Linux从入门到入土,linux,chrome,运维

Z状态:已经运行完毕,但是需要维护自己的退出信息,在自己的进程task_struct会记录自己的退出信息,未来让父进程读取。
如果没有父进程读取,僵尸进程就会一直存在。
如果对僵尸进程一直不回收,就会引起内存泄漏问题,操作系统会调用waitpid来进行进程状态的改变,变为X,再由操作系统进行释放。

一个进程已经出于僵尸了,就不能kill,无法杀掉已经死掉的进程。
【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行,Linux从入门到入土,linux,chrome,运维

3.2 孤儿进程

如果一个进程在运行的时候,它的父进程先退出了,那么这个进程就是孤儿进程。

来代码看看:

  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<unistd.h>
  4
  5 int main()
  6 {
  7
  8   pid_t id=fork();
  9   if(id==0)
 10   {
 11     //child
 12     int cnt=5;
 13     while(cnt)
 14     {
 15       printf("I am a child,cnt:%d,pid:%d\n",cnt,getpid());
 16       sleep(1);
 17 
 18     }
 19 
 20   }
 21   else{
 22     //parent
 23     int cnt=5;
 24     while(cnt)
 25     { printf("I am parent,running always,pid:%d\n",getpid());
 26       sleep(1);
 27       cnt--;
 28     }
 29   }
 30  // while(1)
 31  // {
 32  //   sleep(1);
 33 //    printf("I am a process,pid:%d\n",getpid());
 34 //  }
 35   return 0;
 36 }

来看看现象:

【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行,Linux从入门到入土,linux,chrome,运维
父进程如果先退出,子进程就会变成孤儿进程, 而孤儿进程一般会被1号进程(OS本身)进行领养。
为了保证孤儿进程正常被回收,孤儿进程会被操作系统领养。

可以直接kill掉孤儿进程:
【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行,Linux从入门到入土,linux,chrome,运维

在之前在Linux上写的代码,怎么出来没有关系过僵尸呢?或者内存泄漏?
因为直接在命令行中启动的进程,它的父进程是bash,bash会自动回收新进程的Z。

4. 进程的阻塞、挂起和运行

【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行,Linux从入门到入土,linux,chrome,运维

在网上找的一张进程状态图:

【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行,Linux从入门到入土,linux,chrome,运维
终止状态就等价于Z状态和X状态。

4.1 运行

进程运行一般在CPU上运行。
进程=task_struct+进程的代码和数据

每一个进程都有task_struct,为了对当前所有的进程进行管理,用链表将它们链接起来。而每一个CPU都会有一个运行队列struct runqueue,要运行进程,就得将进程放入运行队列struct runqueue中。从此CPU要运行已经进程,就在运行队列的头部取出一个进程,然后把相关的代码和数据拿到CPU寄存器中,进而就可以调度这个进程了。
一般而言一个进程被放到CPU上这个进程状态就是R,但是大部分教材中说的是进程在运行队列中,该进程的状态就是R状态,这里意思就是进程已经准备好了,可以随时被调度。

【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行,Linux从入门到入土,linux,chrome,运维

一个进程一旦持有CPU,会一直只运行这个进程吗?
不会,进程基于时间片进行轮转调度的。(而Linux中并不是以这种方法调度的,在之后的博客中会提到,请多多关注。)
让多个进程以切换的方式进程调度,在一个时间段内同时得以推进代码,就叫做并发。

把任何时刻,都有多个进程在真的同时运行,叫做并行。

4.2 阻塞状态

在C语言中用过一个scanf,如果不往里面输入数据,会一直处于什么状态?

来看看代码:

  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<unistd.h>
  4 
  5 int main()
  6 {
  7
  8    int a=0;
  9
 10    scanf("%d",&a);
 11
 12    printf("a=%d\n",a);

【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行,Linux从入门到入土,linux,chrome,运维
阻塞状态就相当于S状态或者是D状态。

等待:等待键盘资源是否就绪,键盘上有没有被用户按下按键,按键数据交给进程:
【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行,Linux从入门到入土,linux,chrome,运维

操作系统是软硬件资源的管理者。
进程本身就是软件。
堆硬件的管理也是先描述在组织。

操作系统里面有一个结构体对设备就行管理,每一个结构体里面包含设备的状态,种类,还有指向其他设备的指针。
【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行,Linux从入门到入土,linux,chrome,运维
在等待说明进程并没有被调度,说明进程并不在运行队列中。

如果还有进程要等待键盘资源,就把对应的进程从运行队列放在等待队列里面。拿到对应的资源后,就回到运行队列里面,这个过程一般叫唤醒。
不是只有CPU才有运行队列,各种设备都有自己的等待队列。

阻塞和运行的状态变化,往往伴随进程PCB被连入到不同的队列中。

4.3 挂起

操作系统在运行进程的时候内存时比较吃紧的,一旦进程出于阻塞状态,那么就意味着当前进程不会被调度,这个进程的代码和数据就不会被访问,此时就会把这个进程的代码和数据唤出到磁盘上。那么曾经代码和数据占用的空间就空出来了,一旦获取到相应的资源,又会被唤起。
【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行,Linux从入门到入土,linux,chrome,运维

这个进程的PCB还在内存中,只是它的代码和数据在磁盘的swap分区,此时把这种状态叫做阻塞挂起。
这样操作系统就会更合理使用内存资源。

在用户层是感知不到的。
频繁的换入换出,会导致效率问题。这个是牺牲效率换取空间。

一般swap分区的大小不会太大,为了减少操作系统频繁的使用swap带来效率问题。

4.4 进程切换

CPU内部会有很多寄存器。
函数调用返回的临时变量,就用到了寄存器。

当一个进程被CPU调度的时候,CPU的寄存器中会保存当前进程的临时数据。如果这个进程的时间片到了,那么就会把这个进程从CPU上剥离下来,把下一个进程放上去。如果想要把这个进程恢复,就得保存上下文,然后CPU运行到这个进程又继续执行。
【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行,Linux从入门到入土,linux,chrome,运维

CPU内部的所有寄存器中的临时数据,叫做进程的上下文。

进程在切换,最重要的一件事就是:上下文数据的保护和恢复。

CPU内的寄存器:寄存器本身是硬件,具有数据的存储能力,CPU的寄存器硬件只有一套。
CPU内部的数据,可以有多套,有几个进程,就有几套和该进程对应的上下文数据。
所以寄存器!=寄存器内容

有问题请指出,大家一起进步!!!文章来源地址https://www.toymoban.com/news/detail-850662.html

到了这里,关于【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Linux】详解进程状态之僵尸进程——孤儿进程

    目录 🌞专栏导读 🌛什么是进程 ⭐什么是PCB?  🌛查看进程  🌛如何通过系统调用查看进程PID 🌛fork 🌞认识进程状态 🌛查看进程状态  🌛R状态  ⭐例如: 🌛S状态  🌛D状态  🌛T状态 🌛t状态: 🌛X状态  🌛Z状态 ⭐僵尸进程 ⭐僵尸进程的危害  🌛孤儿进程 🌟作

    2024年02月13日
    浏览(59)
  • 探索Linux下进程状态 | 僵尸进程 | 孤儿进程

    任何进程在运行时都会有自己的状态 下面的状态在kernel源代码里定义: 常见的几种状态: R运行状态(running) : 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。 S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断

    2024年04月17日
    浏览(30)
  • 【Linux深入剖析】进程状态---进程僵尸与孤儿

    📙 作者简介 :RO-BERRY 📗 学习方向:致力于C、C++、数据结构、TCP/IP、数据库等等一系列知识 📒 日后方向 : 偏向于CPP开发以及大数据方向,欢迎各位关注,谢谢各位的支持 进程 = taskk_stuct + 可执行程序 进程不是一直在运行的 进程放在cpu上也不会一直运行的 它可能在等待某

    2024年03月18日
    浏览(46)
  • 【Linux取经路】探索进程状态之僵尸进程 | 孤儿进程

    进程状态是指在操作系统中,一个进程所处的不同运行状态,进程状态就决定了该进程接下来要执行什么任务。常见的进程状态有以下几种: 新建状态 :进程被创建但还没有被操作系统接受和分配资源。 就绪状态 :进程已经获得了所需的资源,并等待被调度执行。 运行状

    2024年02月12日
    浏览(28)
  • 【Linux】进程排队的理解&&进程状态的表述&&僵尸进程和孤儿进程的理解

             进程不是一直运行的,进程可能会在等待某种软硬件资源。即使把进程加载到CPU中,也不是一直会运行的。而进程排队,一定是在等待某种软硬件资源(可以是CPU,键盘,磁盘,网卡等等设备......), 排队时是进程的PCB在排队 。 在这里就需要引入一个概念: 一

    2024年03月21日
    浏览(35)
  • 【Linux从入门到放弃】进程状态的理解以及什么是僵尸进程和孤儿进程?

    🧑‍💻作者: @情话0.0 📝专栏:《Linux从入门到放弃》 👦个人简介:一名双非编程菜鸟,在这里分享自己的编程学习笔记,欢迎大家的指正与点赞,谢谢! 此篇博客依然是在之前的学习基础之上继续探究关于进程的知识。   首先大家可以思考一个问题,当电脑打开一个

    2024年02月13日
    浏览(36)
  • 【Linux进程】进程状态 {进程状态的介绍,进程状态的转换,Linux中的进程状态,浅度睡眠VS深度睡眠,僵尸进程VS孤儿进程,调度器的作用}

    1.1 进程状态介绍 创建状态:当一个进程被创建时,它处于创建状态。在这个阶段,操作系统为进程 分配必要的资源 (将代码和数据拷贝到内存,创建PCB结构体等),并为其分配一个唯一的进程标识符(PID)。 就绪状态:进程就绪状态是指进程已经满足了运行的条件, 进程

    2024年02月12日
    浏览(33)
  • 【从浅学到熟知Linux】进程状态与进程优先级(含进程R/S/T/t/D/X/Z状态介绍、僵尸进程、孤儿进程、使用top及renice调整进程优先级)

    🏠关于专栏:Linux的浅学到熟知专栏用于记录Linux系统编程、网络编程等内容。 🎯每天努力一点点,技术变化看得见 操作系统进程状态概览(理论版),实际的一款操作系统进程状态与理论状态会有一定区别。↓↓↓ 新建状态 :字面意思,当进程刚创建时,就是新建状态。

    2024年04月18日
    浏览(38)
  • 【Linux】僵尸与孤儿 && 进程等待

    目录 一,僵尸进程 1,僵尸进程 2,僵尸进程的危害 二,孤儿进程 1,孤儿进程 三,进程等待 1,进程等待的必要性 2,wait 方法 3,waitpid 方法 4,回收小结 1,僵尸进程 僵死状态(Zombies)是一个比较特殊的状态。 当进程退出并且父进程(使用wait()系统调用,后面讲) 没有读取

    2024年02月04日
    浏览(28)
  • Linux操作命令&静态库和动态库区别&大小端&孤儿僵尸进程

    cd:切换当前目录 ls:查看当前文件与目录 grep:通常与管道符命令一起使用,用于对一些命令的输出进行筛选和加工 cp:复制文件或文件夹 mv:移动文件或文件夹 rm:删除文件或文件夹 ps:查看进程情况 kill:向进程发送信号 tar:对文件进行打包 cat:查看文件内容 top:查看

    2024年02月16日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包