进程的终止和等待

目录

进程终止

如何获取退出码呢?

进程退出方法有哪些?

对于进程退出,内核OS做了什么?

进程等待

为什么要进行进程等待?

如何进行进程等待?

什么是阻塞和非阻塞等待?


进程终止

对于进程退出是三种情况,第一种就是代码没跑完,程序出现了异常,然后程序退出了,这种情况是进程收到了信号终止的,比如ctrl + c给进程发送9号信号终止进程。

第二种情况是代码跑完了,结果是正确的,main函数中用 return 0 返回0值表示这种情况。  

第三种情况是代码跑完,但是结果不正确,我们自己定义不同的返回值表示不同的情况发生了,这个返回值就是退出码,要知道失败的原因,我们就可以根据进程的退出码对应了,当需要知道程序运行中发生的各种情况可以使用strerror(errno)打印错误码errno对应的错误信息,比如打开文件为什么失败等。

如何获取退出码呢?

1.可以使用命令echo $?打印在bash中最近一次进程退出的退出码

2.让父进程等待退出的子进程,获取进程的退出码

进程退出方法有哪些?

1.直接在main中return。

2.使用库函数调用void exit(int status),status填退出码,这个函数是封装了_exit函数,并在退出前刷新了C语言封装的缓冲区。

3.使用系统调用_exit函数是直接终止进程,因为是系统调用,不刷新C语言的缓冲区。

对于进程退出,内核OS做了什么?

首先将进程的状态设置为Z(僵尸状态),父进程等待成功后,将进程状态设置为X(死亡状态),回收进程代码和数据,LinuxOS可能并不会释放该进程的内核数据结构,Linux中会使用使用slab分派器,构建内核的数据结构缓冲池,将回收的进程的内核数据结构保存起来,下次创建进程时,分派器直接分派缓冲池中的废气内核数据结构,直接将其初始化即可,这样缓冲池的好处是不用重新为创建内核数据申请内存空间,提高创建进程的效率。

进程等待

为什么要进行进程等待?

1.解决僵尸状态的内存泄漏问题:

前面提到,倘若子进程退出,父进程不退出也不等待子进程,子进程就会变成僵尸状态,就会造成内存泄漏,需要父进程等待子进程退出,

2.父进程需要获取子进程的退出信息:

子进程退出的时候会把自己的退出码写入内核数据结构task_struct 中,进行进程等待的时候,OS会把子进程的task_struct中的退出码提取,于是父进程可以通过系统调用拿到子进程的退出码。

如何进行进程等待?

使用OS提供的系统调用:

1.使用pid_t wait ( int * status )函数等待任意一个退出的子进程,返回所等待的子进程的pid,参数status是一个输出型参数,status的次低八位是进程的退出码,低7位是进程的退出信号,第8位是core dump标志位表示进程退出是否产生core文件,这个文件是程序异常退出时OS把程序当前的内存内容存储在其中,可以用gdb查看core文件,查看错误的原因。

这个输出型参数status如何获取的?

        当子进程退出时,会将自己的退出信息写入对应的task_struct,进程等待时,OS从子进程的task_struct 中获取了子进程的退出码。

参数status构成如下:

代码示例:


输出:

2.使用pid_t waitpid(pid_t pid,int*status,int option)函数,以一定方式等待指定的子进程,获得子进程的退出信息。

对于返回值:>0时,表示等待子进程成功,<0表示等待子进程失败 ,=0表示非阻塞等待的子进程还没有退出

当 pid>0,表示等待指定pid的子进程,当pid=-1,表示父进程等待任意退出的子进程 ,status是输出型参数,同1


注意:

        当进程收到信号就异常退出了,程序并没有运行完,所以进程异常时只关心退出信号,不关心退出码,正常退出时,父进程获取的子进程退出信号的值是0,表示正常退出。(没有0号信号)
        代码示例中使用位操作获取退出信息,也可以使用系统提供的宏获取, WIFEXITED(status)当进程正常退出时为真,异常退出时为假,WEXITSTATUS(status)从status中提取进程的退出码。 


什么是阻塞和非阻塞等待?


        什么是阻塞等待呢?简单来说就是父进程等待的时候阻塞住了,不继续往下运行代码,底层是将父进程的PCB放入所等待的子进程的task_struct*queue 等待队列中 ,子进程退出时,代表条件就绪,就会唤醒父进程,于是父进程就可以继续往下执行代码了,对应的option参数传0就代表阻塞等待。对于非阻塞等待,将option参数传WNOHANG 表示非阻塞等待 ,当父进程调用函数时就直接检测条件是否满足,子进程是否退出,直接返回结果,然后父进程继续执行后续的代码,当子进程没有退出就返回0,可见进行一次等待时,子进程未必退出,于是需要父进程多次调用这个函数轮询检测子进程是否退出,同时可以隔一段时间去等待子进程,父进程在此期间可以完成其他工作,这是非阻塞等待的特点。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值