Linux——让我们来聊聊进程2(进程的状态)

本节课我们将介绍如何用fork函数创建子进程,对fork函数的理解,以及进程的各种状态等。

一、fork函数

我们在Linux下看一下fork函数的具体用法。

fork是由系统提供的一个接口,它需要unisted.h这个头文件。其中这个返回值类型是pid_t的,不需要任何的形参。

fork函数如果说创建子进程成功的话,会为父进程返回子进程的PID,为子进程返回0。这听上去有点奇怪,为什么一个函数会有两个返回值呢?

请各位看上面这张图,当进入fork函数后, 自然就有相应的创建子进程的代码,当运行完核心的代码后,子进程自然就已经被创建出来了。从那一刻起,就有了两个不同的进程分别走完fork函数,一个是父进程,一个是子进程,自然要被return两次。

 既然已经讲完了fork函数的返回情况,那我们来简单的测试一下吧!

 上面的代码当fork执行完后,就创建了一个子进程,子进程收到的ret是0,它自然要走else if的那条分支,反之父进程要走最后一个,好滴,下面来看结果吧!

 确实,我们看到两个不同的打印结果,这就是子进程创建后的结果,子进程收到的返回值是0,父进程的返回值是子进程的PID!

上面的代码也是fork函数的标准用法,一般都要用if,else if来分流,用子进程做不同的事。

 二、进程的状态

接下来我们来了解一下进程的状态。我主要介绍新建,运行,阻塞,挂起,这四种状态,然后会具体的介绍Linux下的进程状态。

新建进程:

当程序被载入到内存中,成为一个进程,并创建了相应的PCB后,就是一个新建的进程。

新建进程我们不多讲解,概念也十分好理解。在讲下面一个状态前,我们先来介绍一下运行队列的概念。

当我们的进程在内存中,需要被CPU处理的时候,它的PCB就会被链入CPU的运行队列(也就是我们数据结构意义上的队列),它是CPU管理进程的一种方式。

 运行:
当一个进程PCB进入到运行队列等待CPU处理或正在被CPU处理的时候,处于运行状态。

 有了上面运行队列的铺垫,相信这个状态也很好理解了!

为了理解阻塞状态,我们也要说一下阻塞队列的概念。当CPU在处理一个进程的时候,它的代码进入CPU处理,可能这个代码内部对于其余的硬件有要求,比如想要打印一个值(显示屏),写入一些数据(磁盘),scanf读入一个值(键盘)。这时CPU可是不能为你服务这些要求的,它只能暂停一下这个进程的处理,将这个进程交给对应的硬件去处理,这时PCB就被链入到硬件的阻塞队列。它对应的状态叫做阻塞状态。

阻塞:

当一个进程正在等待非CPU资源的处理,它的状态处于阻塞。

 在系统中,如果此时的内存快要用完了,操作系统必定不会干等着,它是要帮咱干事的啊。

它会看看有没有哪些不干事但是确长期占用内存的进程,然后把它的代码和数据换到磁盘中。

此时这个进程就处于挂起状态。

挂起:

当内存即将用完,但存在不被执行代码的进程,这时操作系统会将它的代码和数据换到磁盘中,但其PCB仍在内存中,进程就进入了挂起状态。

介绍完这些一般性的状态后,我们到Linux下来查看具体的状态。

三、Linux下的进程状态

 R(运行)

当一个进程PCB进入运行队列后或者正在被CPU处理,它处于运行状态。

运行的意义是和我们上面讲的运行是一样的。我们可以写一个死循环代码运行起来然后查看这个进程的状态。

 上面的代码不断的打印hello,然后sleep一秒钟。咱们运行起来吧。

 

此时这个进程的状态是:

 S?并不是我们预期的R,这个状态是我们后面要讲的休眠状态。为什么呢?

这是因为进程被CPU处理的速度是相当的快的,而我们的进程中要求打印hello,它就需要进入显示器的阻塞队列,它的大部分时间都消耗在阻塞队列上了,并不在运行队列中,所以我们看的时候是休眠状态。只要我们把打印的代码注释掉就好了。

 此时就是运行状态了,很多人可能会有疑问,R后面的加号是什么意思?

它表示当前的进程是前台进程,就是说如果我们运行起来这个进程,就无法使用任何的命令行。

 如果我们在运行的时候在后面加上&符号,就可以转为后台进程。

 这是命令行是可以正常使用的!实际上在window下也存在着许多的后台进程,只是我们平时并不注意。

 S(睡眠状态):

当进程处于阻塞队列中,实际上就进入了睡眠状态。

注意,这里的睡眠状态是一种可中断的睡眠,也就是说我们可以通过发送信号的方式中断它的睡眠,比如可以直接kill掉这个进程。

我们就用刚刚那个睡眠状态的进程,试着杀掉它。

实际上有各种信号,我们可以通过kill -l的方式查看,大家可以自行了解哦,我不多赘述啦。

有可中断睡眠,自然就有不可中断的睡眠,也就是Disk Sleep。

有时候,我们的系统可能压力很大,此时系统会选择杀掉某些进程(比如长期阻塞等不到资源,挂起状态的)。

如果此时的进程处于Disk Sleep状态,那么就不会被系统kill掉。因为这个状态不好演示,我不演示了,大家可以下去用dd命令来测试一下这个状态。

D(不可中断睡眠):

处于睡眠状态,但不可被kill掉的进程。

 接下来要介绍一种比较简单的状态:暂停状态,实际上就是字面意思,就是进程暂停了。像我们调试代码打断点,运行起来后程序停在了断点处,这时就处于一种暂停的状态。

当然我们可以通过对进程发送信号(kill -20)的方式,让它进入暂停状态。而kill -18就可以继续进程。

 X:退出

当一个进程运行完毕后,其资源可以被OS回收的时候,就处于退出状态。

退出状态也是比较好理解的状态,当进程的核心代码运行完后,它会通知(发送信号)操作系统可以来回收它的资源,这时进程会处于退出状态。 但是系统往往会忽略掉它的信号,可能操作系统在忙着处理其他的东西。

Z:僵尸状态

当一个子进程先于父进程退出的时候,就进入的了僵尸状态。

 我们可以这样理解僵尸进程,进程退出后它的资源无法被回收,就处于僵尸状态。僵尸状态的资源没有被回收,它会有资源的浪费,因为PCB还存在于内存中,如果有大量的僵尸进程,那么会影响新进程的创建,因为新进程没有了可被分配的PID,这时就会影响系统的任务。所以说我们要尽量减少僵尸进程。

还有一个孤儿进程的概念作者将在下次讲解,希望大家好好理解进程这块的知识,这是十分重要的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值