【Linux系统编程】进程退出和回收进程资源
00. 目录
文章目录
- 00. 目录
- 01. 进程退出函数
- 02. 进程退出讨论
- 03. 回收进程资源
- 04. 附录
01. 进程退出函数
#include <stdlib.h>void exit(int status);
功能:结束调用此函数的进程。
参数:status:返回给父进程的参数(低 8 位有效),至于这个参数是多少根据需要来填写。
返回值:无#include <unistd.h>void _exit(int status);
功能:结束调用此函数的进程。
参数:status:返回给父进程的参数(低 8 位有效),至于这个参数是多少根据需要来填写。
返回值:无#include <stdlib.h>void _Exit(int status);
功能:结束调用此函数的进程。
参数:status:返回给父进程的参数(低 8 位有效),至于这个参数是多少根据需要来填写。
返回值:无
exit() 和 _exit() 函数功能和用法是一样的,无非时所包含的头文件不一样,还有的区别就是:exit()属于标准库函数,_exit()属于系统调用函数。
02. 进程退出讨论
下面的例子验证调用 exit() 函数,会刷新 I/O 缓冲区 。
测试程序:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(int argc, char *argv[])
{printf("hello world"); // 打印,没有换行符"\n"exit(0); // 结束进程,标准库函数,刷新缓冲区,printf()的内容能打印出来// _exit(0); // 结束进程,系统调用函数,printf()的内容不会显示到屏幕while(1); // 不让程序结束return 0;
}
测试结果如下:
上面的例子,结束进程的时候改为调用 _exit(),代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(int argc, char *argv[])
{printf("hello world"); // 打印,没有换行符"\n"//exit(0); // 结束进程,标准库函数,刷新缓冲区,printf()的内容能打印出来_exit(0); // 结束进程,系统调用函数,printf()的内容不会显示到屏幕while(1); // 不让程序结束return 0;
}
printf() 的内容是不会显示出来的,运行结果如下:
接下来,我们一起验证一下结束函数( return )和结束进程( exit() )的区别。
测试代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>void fun()
{sleep(2);return; // 结束 fun() 函数while(1);
}int main(int argc, char *argv[])
{fun();printf("after fun\n");while(1); // 不让程序结束return 0;
}
测试结果如下:
通过上面的运行结果得知,return 的作用只是结束调用 return 的所在函数,只要这个函数不是主函数( main() ),只要主函数没有结束,return 并不能结束进程。
我们将上面例子 fun() 里的 return 改为 exit():
测试代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>void fun()
{sleep(2);exit(0); // 结束当前进程while(1);
}int main(int argc, char *argv[])
{fun();printf("after fun\n");while(1); // 不让程序结束return 0;
}
测试结果:
03. 回收进程资源
3.1 概述
在每个进程退出的时候,内核释放该进程所有的资源、包括打开的文件、占用的内存等。但是仍然为其保留一定的信息,这些信息主要主要指进程控制块PCB的信息(包括进程号、退出状态、运行时间等)。
当一个进程正常或异常终止时,内核就向其父进程发送 SIGCHLD 信号,相当于告诉父亲他哪个儿子挂了,而父进程可以通过 wait() 或 waitpid() 函数等待子进程结束,获取子进程结束时的状态,同时回收他们的资源(相当于,父亲听听死去儿子的遗言同时好好安葬它)。
父进程可以通过调用wait或waitpid得到它的退出状态同时彻底清除掉这个进程。
wait() 和 waitpid() 函数的功能一样,区别在于,wait() 函数会阻塞,waitpid() 可以设置不阻塞,waitpid() 还可以指定等待哪个子进程结束。
注意:
一次wait或waitpid调用只能清理一个子进程,清理多个子进程应使用循环。
3.2 wait函数
#include <sys/types.h>
#include <sys/wait.h>pid_t wait(int *status);
功能:等待任意一个子进程结束,如果任意一个子进程结束了,此函数会回收该子进程的资源。
参数:status : 进程退出时的状态信息。
返回值:成功:已经结束子进程的进程号失败: -1这个退出信息在一个 int 中包含了多个字段,直接使用这个值是没有意义的,我们需要用宏定义取出其中的每个字段。下面我们来学习一下其中最常用的两个宏定义,取出子进程的退出信息:WIFEXITED(status)如果子进程是正常终止的,取出的字段值非零。
WEXITSTATUS(status)返回子进程的退出状态,退出状态保存在 status 变量的 8~16 位。在用此宏前应先用宏 WIFEXITED 判断子进程是否正常退出,正常退出才可以使用此宏。
从本质上讲,系统调用 waitpid() 和 wait() 的作用是完全相同的,但 waitpid() 多出了两个可由用户控制的参数 pid 和 options,从而为我们编程提供了另一种更灵活的方式。
#include <sys/types.h>
#include <sys/wait.h>pid_t waitpid(pid_t pid, int *status, int options);
功能:等待子进程终止,如果子进程终止了,此函数会回收子进程的资源。参数:pid : 参数 pid 的值有以下几种类型:pid > 0 等待进程 ID 等于 pid 的子进程。pid = 0 等待同一个进程组中的任何子进程,如果子进程已经加入了别的进程组,waitpid 不会等待它。pid = -1 等待任一子进程,此时 waitpid 和 wait 作用一样。pid < -1 等待指定进程组中的任何子进程,这个进程组的 ID 等于 pid 的绝对值。status : 进程退出时的状态信息。和 wait() 用法一样。options : options 提供了一些额外的选项来控制 waitpid()。0:同 wait(),阻塞父进程,等待子进程退出。WNOHANG:没有任何已经结束的子进程,则立即返回。WUNTRACED:如果子进程暂停了则此函数马上返回,并且不予以理会子进程的结束状态。(由于涉及到一些跟踪调试方面的知识,加之极少用到)返回值:waitpid() 的返回值比 wait() 稍微复杂一些,一共有 3 种情况:1) 当正常返回的时候,waitpid() 返回收集到的已经回收子进程的进程号;2) 如果设置了选项 WNOHANG,而调用中 waitpid() 发现没有已退出的子进程可等待,则返回 0;3) 如果调用中出错,则返回-1,这时 errno 会被设置成相应的值以指示错误所在,如:当 pid 所对应的子进程不存在,或此进程存在,但不是调用进程的子进程,waitpid() 就会出错返回,这时 errno 被设置为 ECHILD;
waitpid测试代码
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>int main(void)
{pid_t pid = -1;int i = 0;int status;//创建一个子进程pid = fork();if (pid < 0){perror("fork"); }//子进程if (0 == pid){for (i = 0; i < 10; i++){printf("I am child process pid: %d %d\n", getpid(), i); //usleep(500000);sleep(1);}exit(10);}//父进程//wait(&status); //等待子进程的状态改变//WNOHANG 如果没有子进程退出 立即返回//waitpid(pid, &status, WNOHANG);waitpid(pid, &status, WUNTRACED);//如果正常退出 就返回真if (WIFEXITED(status)){printf("正常退出 %d...\n", WEXITSTATUS(status));}else if (WIFSIGNALED(status)){printf("被信号杀死 %d..\n", WTERMSIG(status)); }else if (WIFSTOPPED(status)){printf("the child process was stopped by delivery of a signal %d\n", WSTOPSIG(status)); }else if (WIFCONTINUED(status)){printf("the child process was resumed by delivery of SIGCONT\n"); }printf("I am parent process\n"); printf("child pid: %d pid: %d ppid: %d\n", pid, getpid(), getppid());return 0;
}
执行结果:
04. 附录
4.1 参考博客:【Linux系统编程】进程的控制:结束进程、等待进程结束
【Linux系统编程】进程退出和回收进程资源相关推荐
- Linux系统编程(六)守护进程
Linux系统编程(六)守护进程 一.进程组 概念 二.会话 创建会话的条件 守护进程 概念 守护进程模型 创建守护进程 一.进程组 概念 进程组,也称之为作业.代表一个或多个进程的集合.每个进程都属 ...
- Linux系统编程(二)孤儿进程和僵尸进程
Linux系统编程(二) 一.exec函数族 1.exec函数 二.孤儿进程和僵尸进程 三.wait和waitpid 1.wait函数 2.waitpid函数 一.exec函数族 exec函数使用时, ...
- Linux系统编程【文件IO、进程、进程间通信、信号、线程、互斥】
linux系统编程 个人通过学习,手打了一份48000字的Linux系统编程的笔记,包含了[文件IO.进程.进程间通信.信号.多线程.互斥]等知识点,并给出了大量的代码案例对每个重要的知识点进行了代码 ...
- 嵌入式Linux系统编程学习之十二守护进程
文章目录 前言 一.守护进程的特性 二.daemon 进程的编程规则 1.创建子进程,父进程退出 2.在子进程中创建新会话 前言 daemon 运行在后台,也称作"后台服务进程" ...
- Linux系统编程----15(线程与进程函数之间的对比,线程属性及其函数,线程属性控制流程,线程使用注意事项,线程库)
对比 进程 线程 fork pthread_create exit (10) pthread_exit (void *) wait (int *) pthread_join (,void **)阻塞 ...
- Linux系统编程--2(环境变量,进程控制)
环境变量 环境变量 是指在操作系统中用来指定操作系统运行环境的一些参数 每个人用电脑的习惯不一样,比如一般把文件放到磁盘,怎么管理文件,用什么编译器,所以,环境变量就是根据每个人使用操作系统的习惯来规 ...
- Linux系统编程:习题,父子进程通过信号通信,实现交替数数
Linux练习题,父子进程通过信号通信,实现交替数数. 习题思路 父子进程交替发信号进行驱动从而实现数数,值得注意的是 不管是父进程或者子进程谁先发送信号 都会面临一个问题,另外一个进程的信号捕捉函数 ...
- 【Linux系统编程】特殊进程之僵尸进程
00. 目录 文章目录 00. 目录 01. 僵尸进程概述 02. 僵尸进程案例 03. 避免僵尸进程 04. 附录 01. 僵尸进程概述 进程已运行结束,但进程的占用的资源未被回收,这样的进程称为僵 ...
- Linux系统编程——特殊进程之僵尸进程
僵尸进程(Zombie Process) 进程已运行结束,但进程的占用的资源未被回收,这样的进程称为僵尸进程. 在每个进程退出的时候,内核释放该进程所有的资源.包括打开的文件.占用的内存等. 但是仍然 ...
最新文章
- C#.NET 轻量级通用快速开发平台,DevExpress DXperience 12.2
- python操作系统-PYTHON-操作系统基础
- 我的第一个python 代码
- 理解复杂的C/C++声明 const, typedef , 函数指针(转贴)
- EM算法最完整易懂讲解
- HTTP报文字段说明
- dos命令大全 基础命令+网络的常用命令
- [bzoj3202][SDOI2013]项链
- 手机唯一标识IMEI以及与IMSI的区别
- 谷歌正式发布Android 12,UI更好看,应用更快,打造独属于自己的定制化属性
- 计算机网络期末试题及答案
- JavaScript--20 深入理解 Ajax
- 面试官:说一下你们线上JVM是如何优化的?一不小心聊了2个小时!!
- python情人节之玫瑰花与表白方式
- VUE + Element-UI 表单校验input框数据已存在
- java毕业设计道路桥梁工程知识文库系统Mybatis+系统+数据库+调试部署
- 医院云存储服务器项目背景,医疗影像云存储解决方案
- Linux的inode作用,Linux下inode知识
- 预测性维护:工业 4.0下人工智能如何改变机器设备维护方式
- SwiftUI——推送通知(Notifications)二三事
热门文章
- 西山小菜鸟之Scrapy学习笔记---爬取企查查网站公司基本信息
- 计算机毕业设计java+ssm妇女联合会信息网站(源码+系统+mysql数据库+Lw文档)
- 人工智能知识全面讲解:生成对抗网络的应用
- 苹果XS怎么截屏_苹果发布iOS14,有哪些值得一说的亮点
- at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
- ins 登录发现未知网络_如何发现未知的知识
- C语言图形化推箱子完整代码
- 什么是android应用程序未安装,应用程序未安装,教您安卓系统应用程序未安装怎么解决...
- 性能服务器漫画免费下拉式,奇妙漫画免费漫画
- Find 7 Faster Than John Von Neumann