1.首先讲一下进程的退出
进程的退出分为正常退出和异常退出:
正常退出:
(1)main函数调用return
(2)进程调用exit(),标准C库
(3)进程调用_exit()或_Exit(),属于系统调用
(4)进程最后一个线程返回
(5)最后一个线程调用pthread_exit

异常退出:
(1)调用abort
(2)当进程收到某些信号时,例如Ctrl+c
(3)最后一个线程对取消(cancellation)请求做出响应




以上三张图片是对进程退出的补充,
在第二第三张图中的exit(),_exit()_Exit(),这三个函数其实一样的,但习惯用exit()。exit相当于是_exit和_Exit的一个组合。

2.接下来我们介绍一下等待子进程退出以及为什么要等待子进程的退出
在之前我们没学习到等待子进程退出的时候,都是没做等待子进程的操作的,那么这样的子进程都是会变成僵尸进程的。
(1)父进程等待子进程的退出并收集子进程的退出状态,子进程的退出状态不被收集,子进程就会变成僵死进程(僵尸进程)。

介绍一下等待子进程的相关函数:


上图中的waip写错了,应该是wait,waitpid中的有一个选项,可以使调用者不阻塞的选项时options,

这里的阻塞就是相当于vfork方式创建子进程,父进程处于阻塞状态,让子进程先执行,当父进程收到子进程的退出信号的时候,父进程开始执行。而waitpid不阻塞的机制就有点像fork方式创建的子进程一样,父子进程交替执行,所以这就搞的以waitpid的方式等待有点多余了,所以等待子进程退出还是使用wait函数多,但也有场景需要用waitpid的,所以只是少用waitpid而已。

僵尸进程:Z+
正常进程:即有父进程等待的进程,S+

这里的11328就是正常进程,11329就是僵尸进程,有时候调用waitpid函数等待子进程的时候在linux 底下有时候子进程是僵尸进程,有时候又是正常的进程,这以自己跑起来相应的程序查看的为准,而调用wait等待子进程的时候,这时子进程是正常的进程。

(2)以wait函数等待子进程:
直接上代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>int main()
{pid_t pid;int status;int cnt = 0;pid = fork();if(pid > 0){wait(&status);while(1){printf("the process of child is Quit,the status is:%d\n",WEXITSTATUS(status));printf("the process is father process,pid is:%d\n",pid);printf("cnt = %d\n",cnt);sleep(3);}}else if(pid == 0){while(1){cnt++;printf("the process is child process,pid is:%d\n",getpid());printf("cnt = %d\n",cnt);sleep(3);if(cnt == 3){exit(3);}}}return 0;
}

结果:

从结果中可以看出,父进程先是等待子进程执行三次接收到子进程的返回后,才开始执行。
在父进程中我们看到一个WEXITSTATUS(status),这个就是打印出子进程的返回的状态值,子进程的状态值就是exit括号里的,例如exit(3),状态值就是3。

(3)以waitpid的方式等待子进程



status参数是一个整型指针:
非空:子进程退出状态放在它所指向的地址中;
空:不关心退出状态

此时的pid其实就是此时子进程的ID号,而waitpid是不阻塞机制的,可以看看上面介绍
直接上代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>int main()
{pid_t pid;int status;int cnt = 0;pid = fork();if(pid > 0){//              wait(&status);waitpid(pid,&status,WNOHANG);printf("pid = %d\n",pid);while(1){//  printf("the process of child is Quit,the status is:%d\n",WEXITSTATUS(status));printf("the process is father process,pid is:%d\n",getpid());printf("cnt = %d\n",cnt);sleep(3);}}else if(pid == 0){while(1){cnt++;printf("the process is child process,pid is:%d\n",getpid());printf("cnt = %d\n",cnt);sleep(3);if(cnt == 3){exit(3);}}}return 0;
}

结果:

可以看到这里是父进程跟子进程交替执行,当子进程执行三次后退出进程,所以这就是waitpid跟wait的本质区别。

(4)接下来我们来讲一下孤儿进程
孤儿进程:父进程如果不等待子进程退出,在子进程之前就结束了自己的“生命”,此时的子进程就叫做孤儿进程。
而linux避免系统存在过多的孤儿进程,init进程(进程ID号为1)收留孤儿进程,变成孤儿进程的父进程

直接上代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>int main()
{pid_t pid;int cnt = 0;pid = fork();if(pid > 0){printf("this is father process,pid is:%d\n",getpid());}else if(pid == 0){while(1){printf("this is child process,the father is:%d\n",getppid());sleep(3);cnt++;if(cnt == 5){exit(0);}}}return 0;
}

结果:

从结果中可见除了第一个子进程的父进程的ID号为正常的ID号,下面的那些父进程的ID号都是1,即为init进程。

学习笔记,仅供参考!

Linux系统编程之进程退出,父进程等待子进程退出相关推荐

  1. Linux系统编程(六)守护进程

    Linux系统编程(六)守护进程 一.进程组 概念 二.会话 创建会话的条件 守护进程 概念 守护进程模型 创建守护进程 一.进程组 概念 进程组,也称之为作业.代表一个或多个进程的集合.每个进程都属 ...

  2. Linux系统编程(二)孤儿进程和僵尸进程

    Linux系统编程(二) 一.exec函数族 1.exec函数 二.孤儿进程和僵尸进程 三.wait和waitpid 1.wait函数 2.waitpid函数 一.exec函数族 exec函数使用时, ...

  3. 嵌入式Linux系统编程学习之十二守护进程

    文章目录 前言 一.守护进程的特性 二.daemon 进程的编程规则 1.创建子进程,父进程退出 2.在子进程中创建新会话 前言   daemon 运行在后台,也称作"后台服务进程" ...

  4. Linux系统编程【文件IO、进程、进程间通信、信号、线程、互斥】

    linux系统编程 个人通过学习,手打了一份48000字的Linux系统编程的笔记,包含了[文件IO.进程.进程间通信.信号.多线程.互斥]等知识点,并给出了大量的代码案例对每个重要的知识点进行了代码 ...

  5. Linux系统编程--2(环境变量,进程控制)

    环境变量 环境变量 是指在操作系统中用来指定操作系统运行环境的一些参数 每个人用电脑的习惯不一样,比如一般把文件放到磁盘,怎么管理文件,用什么编译器,所以,环境变量就是根据每个人使用操作系统的习惯来规 ...

  6. Linux系统编程:习题,父子进程通过信号通信,实现交替数数

    Linux练习题,父子进程通过信号通信,实现交替数数. 习题思路 父子进程交替发信号进行驱动从而实现数数,值得注意的是 不管是父进程或者子进程谁先发送信号 都会面临一个问题,另外一个进程的信号捕捉函数 ...

  7. Linux系统编程----15(线程与进程函数之间的对比,线程属性及其函数,线程属性控制流程,线程使用注意事项,线程库)

    对比 进程 线程 fork pthread_create exit (10) pthread_exit (void *) wait (int *) pthread_join (,void **)阻塞 ...

  8. Linux系统编程 进程控制

    文章目录 01. 学习目标 02. 进程和程序 (理解) 03. 单道.多道程序设计(了解) 3.1 单道程序设计 3.2 多道程序设计 04. 并行和并发(理解) 05. MMU(了解) 06. 进 ...

  9. linux终端和执行进程的关系,Linux系统编程第04期:打通进程与终端的任督二脉

    本课程是<嵌入式工程师自我修养>自学教程六步走中的第3步:Linux系统编程第04期. 进程,是Linux系统中任务调度运行的基本单元:一个程序的运行,都要被操作系统包装成"进程 ...

  10. Linux系统编程总结

    day2 vim的三种工作模式 命令模式 vi hello.c zz 保存退出 2.编辑模式 i a o s (有大写)可以写东西 3.末行模式: 文本和末行模式不能直接切换 要切换回命令模式 再到末 ...

最新文章

  1. NTP时间同步服务器搭建
  2. 如何找到调用当前方法的方法?
  3. NLP之词向量:利用word2vec对20类新闻文本数据集进行词向量训练、测试(某个单词的相关词汇)
  4. BZOJ 1087状态压缩DP
  5. 【Kafka】kafka 创建 topic的时候 Replication factor 参数理解
  6. flex AdvancedDataGrid 高级表格 介绍 教程
  7. Hibenate连接mysql错误_hibernate连接数据库问题,注意是表名的大小写
  8. ASP.NET 4.0尚未在 Web 服务器上注册 解决方法
  9. IAR EWARM教程
  10. PXE网络安装Linux操作系统原理与详细过程
  11. Python爬取图片之家
  12. 小米蓝牙键盘怎么连接_不是吐槽,是推荐!买了个小米旗下的蓝牙双模键盘。。。...
  13. ubuntu搜狗输入法显示简体中文,输入却是繁体中文解决方案
  14. 评定职称/积分落户,原来软考证书含金量这么大!
  15. VS code 快速配置C语言编写环境
  16. Silver Efex Pro 2 for Mac(黑白处理调试滤镜)
  17. 验证短信延迟?是哪里出现问题
  18. 移动硬盘的“磁盘结构损坏且无法读取”问题的解决方法
  19. torch学习 (二十四):卷积神经网络之GoogleNet
  20. html 计算器 ansi转换,HTML ANSI

热门文章

  1. 用Delphi创建音乐站点维护程序
  2. 类似超时空要塞的java_常用java代码(转 http://www.itjhwd.com/java_code/)
  3. sharesdk QQ空间分享经验
  4. 字符串和字符数组作为函数参数传递
  5. 国际空间站直播 ISS直播
  6. R语言使用pdf函数将可视化图像结果保存到pdf文件中、使用pdf函数打开图像设备、使用dev.off函数关闭图像设备、自定义paper参数指定pdf的纸张类型(多使用A4)
  7. 二、连接usg600
  8. vlc3.0.4在ubuntu16.04x64上的交叉编译全过程记录
  9. php 集成 pdf.js,JavaScript_js插件方式打开pdf文件(浏览器pdf插件分享),两种方案:一种直接链接,把p - phpStudy...
  10. 未来会是云计算的时代吗?