进程终止、进程等待

目录

一、进程终止

二、进程等待

1.我们为什么要进程等待?

2.waitpid

3.尝试

4.非阻塞式的等待的轮询检测


一、进程终止

        我们在c/c++中,总是在main函数中的结尾设置 return 0,那为什么要返回0呢?返回其他的可不可以。

        当然可以,return 0代表代码跑完了,结果正确。return 非0代表结果不正确。以前一股脑的都写return 0当然是不正确的。

        我们成功了,自然是好,失败了,我们最关心的就是为什么失败?return 非0的数来表示不同的原因。

        我们把main函数中的返回值叫做进程退出码。

        在上一篇文章中,我们说了,fork可以创建一个子进程,可以让子进程去干我们要他干的事情,那究竟有没有干好,这个进程退出码由父进程来接受去判断有没有执行成功结果对不对。在linux环境下我们可以说这个return X就是给父进程返回的。

我们简单看下:

我们在main函数中,return 3,这个3要被返回给父进程,但这个进程据我们了解并不是通过fork得来的,返回给谁。在这里我们要知道我们在命令行启动的进程,父进程都是BASH。

        通过,echo $?来获取BASH中的接受到的进程退出码。

        所以结果是: 

        我们还可以获得上一个在命令行中启动的进程的进程退出码。

        我们在命令行输入ls

         这个ls进程执行成功了,所以返回0。

        那如果ls进程执行失败呢?

        则返回2,所以查看子进程运行结果,通过进程退出码来判断,这是它的作用。

        在linux中这些,进程退出码都是什么意思?我们可以用strerror来了解一下,这个函数可以将退出码转换成char*,在这里我们打印下0-19的退出码所表示的错误信息。

     当然我们可以自己设置退出码所对应的退出信息。 

     也可以通过exit退出程序,exit(退出码)。

二、进程等待

1.我们为什么要进程等待?

        在先前我们了解到子进程比父进程先退出,如果父进程不管不顾,子进程就会大杀四方,会导致内存泄漏,就算大名鼎鼎的Kill -9都干不掉他,所以我们通过进程等待的方式,来回收子进程的资源,获取子进程的退出信息。

        我们来尝试下如何等待,先使用wait这个函数。

        我们通过这样的代码来看看结果,先将它运行起来。

        通过kill -9 加子进程代码,杀掉子进程,父进程就可以等待成功。

        

        所以,证明wait可以回收子进程。

        其实,我们平常用的最多的是waitpid,这是今天的重头戏。

        注意:wait/waitpid()是系统调用。

2.waitpid

先讲讲返回值pid_t  :     

        分两种情况如果返回值>0,则说明等待成功,返回值是等待的子进程的pid

                                            <0,意味着等待失败。

第一个参数pid:

        是几,就代表等待的是哪一个子进程,如果是123,就代表的是等待pid为123的子进程。

        为-1,代表等待任意进程,和上文的wait一样,wait的功能就是等待任意进程。

参数二status

        这个参数是一个输出形参数,通过调用该函数从函数内部拿出来特定的数据。

        内部是哪里?要知道wait/waitpid()是系统调用,是从操作系统中拿。前一篇文章讲过,os在创建一个进程时要建立内核数据结构(struct mm_struct task_struct 页表)+代码继承父进程,数据以写时拷贝的形式,与父进程独立或共享。拿什么?从os中哪里拿?子进程结束后,进程的退出信息将被写入task_struct进程控制块。我们就要从task_struct进程控制块拿子进程的退出信息。

        我们看下linux中的源码:在进程控制块中,有其中几个信息exit_code(退出码) exit_signal

       聊了参数从哪里来,我们看看拿来的参数具体是什么

       我们不能把它当作整形来看待,虽然它的类型是整形,但我们只用关注低16位 中的 次低8位

         我们可以用(status>>8)&0xFF来获取退出码。

参数三options

        0代表阻塞等待,子进程退出了我才能等待成功,等待子进程结束了再回收。为WNOHANG,则不再等待,如果要回收的⼦进程都在运⾏,则直接返回0,然后接着执⾏后续程序;为WUNTRACED,如果⼦进程由于被停⽌产⽣的SIGCHLD,waitpid则⽴即返回;WCONTINUED,如果⼦进程由于被SIGCONT唤醒⽽产⽣的SIGCHLD,waitpid则⽴即返回。

3.尝试

        说了这么多,我们来尝试下用waitpid去等待一下子进程的退出码。

        运行结果如图,我们等待成功了,并获得了子进程的返回码。

         

        当然对status一顿操作,很是麻烦,linux提供了宏

        WIFEXITED(status):若为正常终止子进程返回的状态,则为真。(查看是否正常退出)

        WEXITSTATUS(status):若WIFEXITED非零(真),提取子进程的退出码。(提取子进程的退出码)

        代码可以改写成这样:

        运行结果如图:

4.非阻塞式的等待的轮询检测

        waitpid的第三个参数改为WNOHANG,则为非阻塞式等待。

        非阻塞等待就是,我直接去等待子进程,无论子进程是否在进行还是已经退出,等待一次,如果返回值为子进程的pid说明等待成功,子进程退出。如果等于0,说明等待成功了,但是子进程没有退出。

        因为只等待一次,一般我们都会用轮询检测,其实就是一直循环调用waitpid()去等待子进程。

        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值