盐城网站建设方案,全景旅游网站项目建设,赣州做网站找谁,app注册推广团队写在前面#xff1a; 我的Linux的学习之路非常坎坷。第一次学习Linux是在大一下的开学没多久#xff0c;结果因为不会安装VMware就无疾而终了#xff0c;可以说是没开始就失败了。第二次学习Linux是在大一下快放暑假#xff08;那个时候刚刚过完考试周#xff09;#xf… 写在前面 我的Linux的学习之路非常坎坷。第一次学习Linux是在大一下的开学没多久结果因为不会安装VMware就无疾而终了可以说是没开始就失败了。第二次学习Linux是在大一下快放暑假那个时候刚刚过完考试周我没什么事做就又重拾Linux不服输的我选择再战Linux这一次学习还算顺利虽然中间有些小插曲但是不影响整体学习进度 我看着B站上的视频一点点学习Linux基本上把Linux的基础指令学完了。学完之后我又遇到问题了视频基本上到这就结束了而我却不知道下一步该学什么于是就没怎么碰Linux结果没过多长时间我就把学的Linux指令忘的一干二净。现在是我第三次学习Linux我决定重新开始学Linux同时为了让自己学习的效果更好我选择以写blog的形式逼迫自己每天把学习到的Linux知识整理下来。这也就是我写这个系列blog的原因。 waitwaitpid函数 我们先来看wait函数
传入参数
一个int类型的指针各位童鞋看名字应该就可以猜出来是表示状态信息的。没错wstate就是表示回收的子进程 信息我们可以调用一些宏函数去判断子进程的信息详细的后面我在说。当然你也可以传NULL也不会报错。
返回值
成功回收进程的pid失败-1设置errno
函数的作用
阻塞等待子进程退出清理子进程残留在内核的 pcb 资源通过传出参数得到子进程结束状态
利用宏函数获取子进程信息
WIFEXITED(status)——为真子进程正常终止。再次调用WSTATUS(status)——得到子进程退出值WIFSIGNALED(status)——为真子进程被信号终止。调用WTERMSIG(status)——得到子进程异常终止的的信号编号。
一个进程终止时会关闭所有文件描述符释放在用户空间分配的内存但它的 PCB 还保留着内 核在其中保存了一些信息如果是正常终止则保存着退出状态如果是异常终止则保存着导致该进程 终止的信号是哪个。这个进程的父进程可以调用wait或者waitpid获取这些信息然后彻底清除掉 这个进程。我们知道一个进程的退出状态可以在 shell 中用特殊变量$查看因为 shell 是它的父 进程当它终止时shell 调用 wait 或者waitpid得到它的退出状态同时彻底清除掉这个进程。
举个栗子
源代码
#includestdio.h
#includesys/wait.h
#includeunistd.h
#includestring.hint main()
{pid_t pid,wpid;int state;pidfork();if(pid0){printf(Im child,my pid is %d\n,getpid());sleep(3);printf(child go to die\n);}else if(pid0){wpidwait(state);if(wpid0)printf(i am parent,wait child id is %d,wait successfully\n,wpid);elseperror(wait error);}return 0;
}效果 接着看waitpid函数 传入参数
pid有四种可能的值 -1:等待回收任何组idgid)等于该值的绝对值的子进程。manpage原文meaning wait for any child process whose process group ID is equal to the absolute value of pid.)-1:等待回收任意一个子进程。manage原文meaning wait for any child process.)0:等待回收任意一个组id和该进程组id一致的子进程。manpage原文meaning wait for any child process whose process group ID is equal to that of the calling process at the time of the call to waitpid())0:等待回收指定pid的子进程这一种是用的最多的。(manpage原文meaning wait for the child whose process ID is equal to the value of pid.) status传出 回收进程的状态。options一般默认是阻塞即一直等待直到回收一个子进程为止。也可以指定为WNOHANG 指定回收方式为非阻塞。
返回值
0: 表成功回收的子进程 pid0 : 函数调用时 参 3 指定了 WNOHANG 并且没有子进程结束。-1: 失败。errno
举个栗子
我们演示一个小demo,之前我们循环创建过5个子进程我们这次就来回收指定子进程下面以回收第三个子进程为例。
错误演示
源代码
#includestdio.h
#includeunistd.h
#includesys/wait.hint main()
{pid_t pid,wpid;int i;for(i0;i5;i){if(fork()0){if(2i)pidgetpid();break;}}if(5i){sleep(5);printf(--------in parent , before waitpid, pid %d\n, pid);wpid(pid,NULL,0);printf(Im parent, wait a child finish : %d \n, wpid);}else{sleep(i);printf(Im %dth child, pid %d\n, i1, getpid());}return 0;
} 效果 错误分析 上面的代码看似非常对我们用pid来获取第三个子进程的id然后让父进程使用waitpid来回收。但是再仔细看我们是在子进程把第三个子进程的id赋值给变量pid,但是由于父子进程间遵循的是读时共享写时复制所以对于父进程中变量pid还是没有变还是0. 正确演示
源代码
#includeunistd.h
#includestring.h
#includestdlib.h
#includesys/wait.hint main()
{pid_t pid,wpid,tpid;int i;for(i0;i5;i){pidfork();if(0pid)break;if(2i)tpidpid;}if(5i){sleep(5);wpidwaitpid(tpid,NULL,0);printf(tpid%d\n,tpid);if(wpid-1){perror(waitpid error);exit(1);}printf(i am parent,wait child id is %d\n,wpid);}else{sleep(i);printf(I am %dth child,my pid is %d\n,i1,getpid());}return 0;
}效果
waitpid回收多个子进程
首先我们要无论是wait还是waitpid每一次调用都只能回收一个子进程 源代码
#includestdio.h
#includeunistd.h
#includesys/wait.hint main()
{int i;pid_t pid,wpid;for(i0;i5;i){pidfork();if(!pid)break;}if(5i){while((wpidwait(NULL))!-1){printf(wait child pid is %d\n,wpid);}}else{sleep(i);printf(i am %dth child,my pid is %d\n,i1,getpid());}return 0;
}效果
利用宏函数判断子进程返回状态
源代码
#includestdio.h
#includeunistd.h
#includesys/wait.hint main()
{pid_t pid,wpid;int state;pidfork();if(pid0){printf(i am child,my pid is %d\n,getpid());sleep(15);printf(i am going to die\n);}else{wpidwait(state);if(WIFEXITED(state))printf(i am parent,my child was terminal normally, childs pid is %d\n,wpid);else if(WIFSIGNALED(state))printf(my child was terminaled with signal %d,childs pid is %d\n,WTERMSIG(state),wpid);}return 0;
}效果 自然终止 被信号终止 写在最后
个人亲身经验我们学习的一系列Linux命令一定要自己亲手去敲。不要只是看别人敲代码不要只是停留在眼睛看脑袋以为自己懂了等你实际上手去敲会发现许许多多的这样那样的问题。正可谓“键盘敲烂月薪过万” 如果你觉得我写的题解还不错的请各位王子公主移步到我的其他题解看看 数据结构与算法部分还在更新中 C STL总结 - 基于算法竞赛强力推荐动态规划——01背包问题动态规划——完全背包问题动态规划——多重背包问题动态规划——分组背包问题动态规划——最长上升子序列LIS)二叉树的中序遍历三种方法最长回文子串最短路算法——DijkstraC实现最短路算法———Bellman_Ford算法C实现最短路算法———SPFA算法C实现最小生成树算法———prim算法C实现最小生成树算法———Kruskal算法C实现染色法判断二分图C实现 Linux部分还在更新中 Linux学习之初识LinuxLinux学习之命令行基础操作Linux学习之基础命令适合小白Linux学习之权限管理和用户管理Linux学习之制作静态库和动态库Linux学习之makefileLinux学习之系统编程1关于读写系统函数 ✨总结
“种一颗树最好的是十年前,其次就是现在” 所以, “让我们一起努力吧,去奔赴更高更远的山海” 如果有错误❌,欢迎指正哟
如果觉得收获满满,可以动动小手,点点赞,支持一下哟