官方网站建设维护合作协议,ppt模板去哪个网站下载,各类企业网站案例,十大正规交易平台#x1f308;个人主页#xff1a;Yui_ #x1f308;Linux专栏#xff1a;Linux #x1f308;C语言笔记专栏#xff1a;C语言笔记 #x1f308;数据结构专栏#xff1a;数据结构 #x1f308;C专栏#xff1a;C 文章目录 1. 为什么需要进行进程等待2. 进程等待的方法2…个人主页Yui_ Linux专栏Linux C语言笔记专栏C语言笔记 数据结构专栏数据结构 C专栏C 文章目录 1. 为什么需要进行进程等待2. 进程等待的方法2.1 wait方法2.2 waitpid方法2.3 获取子进程status2.4 进程的堵塞等待方式2.5 进程的非堵塞等待方法 3.解释堵塞与非堵塞 1. 为什么需要进行进程等待
进程等待是多进程编程中至关重要的一部分主要原因是为了让父进程正确管理子进程生命周期并避免各种问题。
进行资源回收当子进程结束后操作系统不会立即释放与该进程相关的所有资源需要父进程来获取子进程的终止状态并释放这些资源。避免僵尸进程虽然子进程已经结束运行但是它在进程中仍然回保留占位条目需要父进程回收。获取子进程的退出状态用来判断子进程是否成功执行完成任务
2. 进程等待的方法
2.1 wait方法
头文件
#include sys/types.h
#include sys/swit.h语法格式
pid_t wait(int*status);放回值 成功返回被等待进程的pid失败返回-1 参数: 输出型参数获取子进程的退出状态不甘心则可以设置为NULL 测试代码
#include stdio.h
#include unistd.h
#include sys/types.h
#include stdlib.h
#include sys/wait.h
int main()
{pid_t id fork();if (id 0){perror(fork error);exit(-1);//错误情况 }if (id 0){//child process int cnt 5;while (cnt--){printf(i am a child process pid:%d\n, getpid());;sleep(1);}exit(0);//process exit }sleep(10);//wait child process printf(i am a father pid:%d\n, getpid());pid_t ret wait(NULL);if (ret 0) printf(father wait:%d,success\n, ret);else (father wait failed\n);sleep(10);return 0;
}查看进程状态
ubuntuVM-20-9-ubuntu:~/processWait$ while :; do ps axj | head -1 ps axj | grep process| grep -v grep; sleep 1; echo #######################################; donePPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
#######################################PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
#######################################PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND651091 668279 668279 651091 pts/0 668279 S 1000 0:00 ./process668279 668280 668279 651091 pts/0 668279 S 1000 0:00 ./process
#######################################PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND651091 668279 668279 651091 pts/0 668279 S 1000 0:00 ./process668279 668280 668279 651091 pts/0 668279 S 1000 0:00 ./process
#######################################PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND651091 668279 668279 651091 pts/0 668279 S 1000 0:00 ./process668279 668280 668279 651091 pts/0 668279 S 1000 0:00 ./process
#######################################PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND651091 668279 668279 651091 pts/0 668279 S 1000 0:00 ./process668279 668280 668279 651091 pts/0 668279 S 1000 0:00 ./process
#######################################PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND651091 668279 668279 651091 pts/0 668279 S 1000 0:00 ./process668279 668280 668279 651091 pts/0 668279 S 1000 0:00 ./process
#######################################PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND651091 668279 668279 651091 pts/0 668279 S 1000 0:00 ./process668279 668280 668279 651091 pts/0 668279 Z 1000 0:00 [process] defunct
#######################################PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND651091 668279 668279 651091 pts/0 668279 S 1000 0:00 ./process668279 668280 668279 651091 pts/0 668279 Z 1000 0:00 [process] defunct
#######################################PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND651091 668279 668279 651091 pts/0 668279 S 1000 0:00 ./process668279 668280 668279 651091 pts/0 668279 Z 1000 0:00 [process] defunct
#######################################PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND651091 668279 668279 651091 pts/0 668279 S 1000 0:00 ./process668279 668280 668279 651091 pts/0 668279 Z 1000 0:00 [process] defunct
#######################################PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND651091 668279 668279 651091 pts/0 668279 S 1000 0:00 ./process668279 668280 668279 651091 pts/0 668279 Z 1000 0:00 [process] defunct
#######################################PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND651091 668279 668279 651091 pts/0 668279 S 1000 0:00 ./process
#######################################PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND651091 668279 668279 651091 pts/0 668279 S 1000 0:00 ./process
#######################################PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND651091 668279 668279 651091 pts/0 668279 S 1000 0:00 ./process
#######################################PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND651091 668279 668279 651091 pts/0 668279 S 1000 0:00 ./process
#######################################PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND651091 668279 668279 651091 pts/0 668279 S 1000 0:00 ./process
#######################################PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND651091 668279 668279 651091 pts/0 668279 S 1000 0:00 ./process
#######################################PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND651091 668279 668279 651091 pts/0 668279 S 1000 0:00 ./process
#######################################PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND651091 668279 668279 651091 pts/0 668279 S 1000 0:00 ./process
#######################################PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND651091 668279 668279 651091 pts/0 668279 S 1000 0:00 ./process
#######################################PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND651091 668279 668279 651091 pts/0 668279 S 1000 0:00 ./process
#######################################PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
#######################################PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND查看上面的情况我们可以发现在中间有段时间子进程进入了僵尸状态后来就被父进程给回收了。
2.2 waitpid方法
头文件
#include sys/types.h
#include sys/swit.h语法格式
pid_t waitpid(pid_t pid,int* status,int options);返回值
当正常放回的时候waitpid返回搜集到的子进程进程ID
如果设置了选项WNOHANG而调用中waitpid发现没有已退出的子进程可收集则返回0。
如果调用中出错则返回-1这时error会被设置成相对应的值以指示错误所在。参数
pid:pid-1,等待任意一个子进程与wait等效。pid0等待其进程ID与pid相等的子进程。
status:WIFEXITED(status):如果正常终止子进程返回的状态则为真。查看进程是否是正常退出WEXISTATUS(status):如果WIFEXIED非0提取子进程退出码。查看进程退出码
options:WNOHANG:如果pid指定的子进程没有结束则waitpid()函数返回0不予以等待如果正常结束则返回该子进程的ID。如果子进程已经退出调用wait/waitpid会立即返回并且释放资源获取子进程退出信息。如果任意时刻调用wait/waitpid子进程存在且正常运行则可能阻塞。如果不存在该进程则立即出错放回。
2.3 获取子进程status
wait和waitpid都有一个status参数该参数是一个输出型参数由操作系统填充。如果传递NULL表示不关心子进程的退出状态信息。如果不传递NULL操作系统会会根据该参数将子进程的退出信息反馈给父进程。status不能简单的当作整型来看应该当作位图来看待。
测试代码
#include stdio.h
#include stdlib.h
#include unistd.h
#include sys/wait.h
#include sys/types.h
int main()
{pid_t id fork();if(id0){perror(fork fail);exit(1);}if(id 0){//childprintf(i am a child pid:%d\n,getpid());sleep(20);exit(10);}else{//fatherint status;int ret wait(status);if(ret0(status0x7F)0){//normal exitprintf(child exit code:%d\n,(status8)0xFF);}else if(ret0){printf(sig code:%d\n,status0x7F);}}return 0;
}
正常退出会打印child exit code:10 运行过程中被kill掉sig code:9
2.4 进程的堵塞等待方式
#include stdio.h
#include stdlib.h
#include unistd.h
#include sys/wait.h
#include sys/types.hint main()
{pid_t id fork();if(id 0){perror(fork fail);exit(1);}else if(id 0){//childprintf(i am a child,pid is:%d\n,getpid());sleep(5);exit(257);}else{ //fatherint status 0;pid_t ret waitpid(-1,status,0);//阻塞等待printf(This is test for wait\n);if(WIFEXITED(status)ret id){printf(wait child 5s success,child return code is:%d\n,WEXITSTATUS(status));}else{printf(wait child failed,return\n);return 1;}}return 0;
}
执行过程 因为阻塞等待的缘故在子进程结束前父进程都不会执行下一条语句。会一直卡在pid_t ret waitpid(-1,status,0);者句语句。 执行结果
i am a child,pid is:701810
This is test for wait
wait child 5s success,child return code is:1提问为什么会放回1呢 回答 在上面的图中我们得知了但程序正常退出后其退出状态存储在低8位中而257的二进制位为0001 0000 0001会被截断为1
2.5 进程的非堵塞等待方法
#include stdio.h
#include stdlib.h
#include unistd.h
#include sys/wait.h
#include sys/types.hint main()
{pid_t id fork();if(id 0){perror(fork fail);exit(1);}else if(id 0){//childprintf(i am a child,pid is:%d\n,getpid());sleep(5);exit(1);}else{ //fatherint status 0;pid_t ret 0;do{ret waitpid(-1,status,WNOHANG);//非阻塞等待if(ret 0){printf(child is running\n);}sleep(1);}while(ret 0);if(WIFEXITED(status)ret id){printf(wait child 5s success,child return code is:%d\n,WEXITSTATUS(status));}else{printf(wait child failed,return\n);return 1;}}return 0;
}
执行结果
child is running
i am a child,pid is:711095
child is running
child is running
child is running
child is running
wait child 5s success,child return code is:1从这两段代码大家肯定可以分的清楚堵塞和非堵塞的区别了吧。就是还不理解下面我在来一个例子相信大家一定就没有问题了。
3.解释堵塞与非堵塞
阻塞场景打电话等朋友接听 你拨打朋友的电话直到朋友接通之前你什么都做不了。这就像阻塞调用你必须等着事情完成。 非阻塞场景发消息等待回复 你给朋友发了个消息等他们回你。你不用一直盯着手机看而是可以去做别的事情等收到消息后再查看。这就像非阻塞调用你不需要等着完成才能做其他事情。
就是如此感谢观看本篇文文章提前感谢大家的点赞与收藏~