【Linux】进程(2):进程状态

大家好,我是苏貝,本篇博客带大家了解Linux进程(1),如果你觉得我写的还不错的话,可以给我一个赞👍吗,感谢❤️
在这里插入图片描述


其实进程状态只是PCB的一个属性,即是Linux下task_struct结构体的一个属性
在这里插入图片描述

所以如果进程状态被修改了,即task_struct结构体里的status属性被修改了

下图是进程的7种状态
在这里插入图片描述

(A)R/S/D/T/t状态

进程一共有7种状态,下面我们来一一介绍

1. R:程序运行的状态

先来写makefile文件,将上面的makefile文件复制过来,内容如下:
在这里插入图片描述

这时我决定将新的.c文件命名为testStatus.c,可执行文件命名为testStatus,为了方便,我们可以在尾行模式下执行下面代码,一键将myprocess替换成testStatus
在这里插入图片描述

不过这只对单纯的myprocess替换,若后面带了.c或其它后缀,可能不能替换

在这里插入图片描述

写出下面代码
在这里插入图片描述

编译.c文件,运行进程,通过每秒显示的进程信息中我们发现,进程处于S+状态,而非R状态(运行状态),这是为什么?
在这里插入图片描述

将.c文件修改一下,去掉打印
在这里插入图片描述

再来看看进程的状态,发现这时又是R状态,这又是什么原因呢?
在这里插入图片描述

第一种情况:
需要打印,所以要与外设显示器打交道。CPU将处理的结果传到内存中,再从内存传到显示器文件里。在此期间,CPU处理得到1个结果可能只需要几纳秒,而显示器打印可能需要几毫秒,所以在第二次得到CPU处理的结果时,进程要等待显示器响应。在我们循环打印时,进程在绝大多数情况下都要等待显示器响应,所以进程显示S状态。

第二种情况:
不需要打印,所以不需要和外设打交道,因此进程不需要等待响应,所以进程处于R状态

2. S:休眠状态

处于S状态有两种可能:
一是进程在等待资源就绪(上面的第一种情况),二是可中断睡眠

可中断睡眠:处于睡眠状态,但是随时可以被外部因素(如CTRL+C)打断

展示一下:修改.c文件
在这里插入图片描述

运行进程2秒后CTRL+C可以结束进程

在这里插入图片描述

我们发现,S状态后面还跟着一个+,这是什么意思?
S+:表示进程在前台运行
S:表示进程在后台运行

用下面命令就能用代码让进程在后台运行
在这里插入图片描述

后台运行的进程不能被CTRL+C结束,需要用kill -9 pid结束
在这里插入图片描述

3. T/t:暂停进程

暂停的进程会等待被唤醒。如何暂停进程呢?也要用kill命令

先来查看所有的kill信号
在这里插入图片描述

我们上面的kill -9 pid就是使用了9号信号:SIGKILL,作用是杀掉进程。现在来学习19号和18号信号:SIGSTOP和SIGCONT,作用分别是暂停进程和唤醒进程

先修改.c文件
在这里插入图片描述

用了kill -19 pid后,进程状态确实变成了T(暂停状态)
在这里插入图片描述

我们继续让暂停的进程被唤醒,用kill -18 pid

在这里插入图片描述

注意:一个进程在被暂停和被唤醒后,会自动变成后台运行(状态后面没有+)

其实我们在学习进程状态之前就有用过暂停进程,比如:调试

调试时,遇到断点就会暂停进程

在调试前,注意要在gcc后面加-g,这样形成的才是可被调试的debug模式,否则默认是不可被调试的release模式
在这里插入图片描述

进入调试,在第10行打断点,运行进程。到断点位置,进程暂停,T状态。gdb里执行c(continue)继续进程,S状态。再到断点位置,进程暂停,T状态
在这里插入图片描述

4. D(disk sleep):不可被kill杀,深度睡眠,不可中断睡眠

D状态是Linux系统比较特有的一种状态,不可被kill杀,只能等待进程自己醒来。如果想杀掉进程,只能重启,甚至于断电

(B)僵尸进程(Z)

在Linux中,进程=内核数据结构task_struct+进程的代码和数据。一个已经运行完毕的进程,代码和数据都不再使用,所以它们的空间会被释放。但进程要维持自己的退出信息,退出信息位于内核数据结构task_struct中,未来让父进程进行读取。如果没有父进程读取,该进程虽然已经运行完毕但task_struct会一直存在,即僵尸进程,task_struct占的空间非常大,这就导致内存泄漏。

先修改.c文件
在这里插入图片描述

上面代码是说,子进程循环3次就结束进程,父进程一直存在但不会读取子进程的退出信息
在这里插入图片描述

我们可以看到,在子进程结束后,并没有退出,而是以僵尸进程的形式存在。
在这里插入图片描述

我们同样发现,处于Z状态时进程名会发生改变,且后面带有,这也是在告诉我们该进程是僵尸进程
在这里插入图片描述

在后面我们还会学习让父进程读取子进程的退出信息的函数waitpid(),读取的瞬间子进程变成X状态,再由操作系统释放

我们以前启动的所有的进程,为什么没有关心过僵尸进程呢?也就是为什么我们没有关心内存泄漏问题?因为直接在命令行中启动的进程,它的父进程是bash,bash会自动读取新进程的退出信息,然后由操作系统释放

(C)孤儿进程

父进程如果先退出,子进程就会变成孤儿进程。为了保证子进程被正常回收,孤儿进程一般都会被1号进程(可以理解为操作系统)领养。

修改.c文件

在这里插入图片描述

父进程退出后,子进程(pid=7966)就变成孤儿进程,此时的父进程为1号进程
在这里插入图片描述


好了,那么本篇博客就到此结束了,如果你觉得本篇博客对你有些帮助,可以给个大大的赞👍吗,感谢看到这里,我们下篇博客见❤️

  • 32
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值