代码示例:模仿僵尸进程
运行输出:
#include<sys/types.h>#include<sys/wait.h>pid_t wait(int*status);返回值:成功返回被等待进程 pid ,失败返回 -1 。参数:输出型参数,获取子进程退出状态 , 不关心则可以设置成为 NULL
pid_ t waitpid(pid_t pid, int *status, int options);返回值:当正常返回的时候, waitpid 返回收集到的子进程的进程 ID ;如果设置了选项 WNOHANG, 而调用中 waitpid 发现没有已退出的子进程可收集 , 则返回 0 ;如果调用中出错 , 则返回 -1, 这时 errno 会被设置成相应的值以指示错误所在;参数:pid :Pid=-1, 等待任一个子进程。与 wait 等效。Pid>0. 等待其进程 ID 与 pid 相等的子进程。status:WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)WEXITSTATUS(status): 若 WIFEXITED 非零,提取子进程退出码。(查看进程的退出码)options:WNOHANG: 若 pid 指定的子进程没有结束,则 waitpid() 函数返回 0 ,不予以等待。若正常结束,则返回该子进程的ID 。
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/wait.h> #include <sys/types.h> int main() { pid_t id = fork(); if(id == 0) { //child process int cnt = 5; while(cnt--) { printf("I am child process! cnt: %d ,pid: %d, ppid: %d\n", cnt, getpid(), getppid()); sleep(1); } } else { //father process while(1) { printf("I am father process! pid: %d, ppid: %d\n", getpid(), getppid()); sleep(1); pid_t ret = wait(NULL); //阻塞等待 if(ret > 0) printf("wait child process success! ret :%d\n", ret); } } return 0; }
示例:
//pid_t ret = wait(NULL);
pid_t ret = waitpid(id, NULL, 0);//阻塞等待
输出:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/wait.h> #include <sys/types.h> int main() { pid_t id = fork(); if(id == 0) { //child process int cnt = 5; while(cnt--) { printf("I am child process! cnt: %d ,pid: %d, ppid: %d\n", cnt, getpid(), getppid()); sleep(1); } exit(99); } else { //father process //pid_t ret = wait(NULL); int status = 0; pid_t ret = waitpid(id, &status, 0);//阻塞等待 if(ret > 0) printf("waitpid child process success! ret :%d, status:%d\n", ret, status); // while(1) // { // printf("I am father process! pid: %d, ppid: %d\n", getpid(), getppid()); // sleep(7); // } } return 0; }
[wxq@VM-4-9-centos code_4_10]$ ./test I am child process! cnt: 4 ,pid: 4736, ppid: 4735 I am child process! cnt: 3 ,pid: 4736, ppid: 4735 I am child process! cnt: 2 ,pid: 4736, ppid: 4735 I am child process! cnt: 1 ,pid: 4736, ppid: 4735 I am child process! cnt: 0 ,pid: 4736, ppid: 4735 waitpid child process success! ret :4736, status:3840 [wxq@VM-4-9-centos code_4_10]$
为什么这里status的值是3840呢??而不是我们设置的99呢???
"&":有0就为0,同为0就为0,同为1就为1
0xFF : 0000 0000 0000 .... .... 1111 1111
0x7F: 0000 0000 0000 .... .... 0111 1111
if(ret > 0) printf("waitpid child process success! ret :%d, status:%d\n", ret, (status >> 8) & 0XFF);
[wxq@VM-4-9-centos code_4_10]$ vim process_wait.c [wxq@VM-4-9-centos code_4_10]$ make gcc -o test process_wait.c [wxq@VM-4-9-centos code_4_10]$ ./test I am child process! cnt: 4 ,pid: 9576, ppid: 9575 I am child process! cnt: 3 ,pid: 9576, ppid: 9575 I am child process! cnt: 2 ,pid: 9576, ppid: 9575 I am child process! cnt: 1 ,pid: 9576, ppid: 9575 I am child process! cnt: 0 ,pid: 9576, ppid: 9575 waitpid child process success! ret :9576, status:99
的确通过这个途径,我们可以得到退出码。当然,我们也可以通过status,得到子进程退出的信号标号:
printf("等待子进程退出成功:ret: %d\n,子进程的信号编号:%d\n 子进程的退出码:%d\n",
ret, status & 0x7F, (status >> 8) & 0xFF);
输出:信号编号为0,退出成功
[wxq@VM-4-9-centos code_4_10]$ ./test
I am child process! cnt: 4 ,pid: 14639, ppid: 14638
I am child process! cnt: 3 ,pid: 14639, ppid: 14638
I am child process! cnt: 2 ,pid: 14639, ppid: 14638
I am child process! cnt: 1 ,pid: 14639, ppid: 14638
I am child process! cnt: 0 ,pid: 14639, ppid: 14638
等待子进程退出成功:ret: 14639
,子进程的信号编号:0
子进程的退出码:99
[wxq@VM-4-9-centos code_4_10]$
WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)WEXITSTATUS(status): 若 WIFEXITED 非零,提取子进程退出码。(查看进程的退出码
//father process //pid_t ret = wait(NULL); int status = 0; pid_t ret = waitpid(id, &status, 0);//阻塞等待 // printf("等待子进程退出成功:ret: %d\n,子进程的信号编号:%d\n 子进程的退出码:%d\n", // ret, status & 0x7F, (status >> 8) & 0xFF); if(ret > 0) { if(WIFEXITED(status)) { printf("子进程正常退出,退出码:%d\n", WEXITSTATUS(status)); } else { printf("子进程异常退出:%d\n", WIFEXITED(status)); } }
[wxq@VM-4-9-centos code_4_10]$ vim process_wait.c [wxq@VM-4-9-centos code_4_10]$ make gcc -o test process_wait.c [wxq@VM-4-9-centos code_4_10]$ ./test I am child process! cnt: 4 ,pid: 20268, ppid: 20267 I am child process! cnt: 3 ,pid: 20268, ppid: 20267 I am child process! cnt: 2 ,pid: 20268, ppid: 20267 I am child process! cnt: 1 ,pid: 20268, ppid: 20267 I am child process! cnt: 0 ,pid: 20268, ppid: 20267 子进程正常退出,退出码:99 [wxq@VM-4-9-centos code_4_10]$
pid_t ret = waitpid(id,&status,0 ); //默认是在阻塞状态去等待子进程状态变化–退出
[wxq@VM-4-9-centos code_4_10]$ grep -ER 'WNOHANG' /usr/include/ /usr/include/sys/wait.h: If the WNOHANG bit is set in OPTIONS, and that child /usr/include/sys/wait.h: If the WNOHANG bit is set in OPTIONS, and that child /usr/include/bits/waitflags.h:#define WNOHANG 1 /* Don't block waiting. */ /usr/include/valgrind/vki/vki-linux.h:#define VKI_WNOHANG 0x00000001 /usr/include/linux/wait.h:#define WNOHANG 0x00000001 [wxq@VM-4-9-centos code_4_10]$
其实就是宏定义: #define WNOHANG 1
waitpid(id, &status, 1); 这里也可以传1,但是怕长时间忘记了1的含义,所以设置了这个宏,这里也叫做魔术数字。
- 进程阻塞的本质,是进程阻塞在系统函数的内部!
- 这也就意味着后面的代码不再向后继续执行
- 当条件满足的时候,父进程被唤醒,从哪里唤醒?
- 是waitpid重新调用,还是从if的后面,if
- (为什么?因为挂起父进程的时候,pc指针会存储父进程下一步命令的地址,换言之,pc指针会指向这里)
- 再继续向后执行父进程的代码
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/wait.h> #include <sys/types.h> int main() { pid_t id = fork(); if(id == 0) { //child process int cnt = 5; while(cnt--) { printf("I am child process! cnt: %d ,pid: %d, ppid: %d\n", cnt, getpid(), getppid()); sleep(1); } exit(99); } else { //father process int quit = 0; while(!quit) { int status = 0; pid_t result = waitpid(-1, &status, WNOHANG); //-1表示等待任意的子进程 WNOHANG:以非阻塞的方式等待 if(result > 0) { printf("等待子进程退出成功,退出码:%d\n", WEXITSTATUS(status)); quit = 1; } else if(result == 0 ) { printf("子进程仍在运行,暂时并未退出,父进程可以继续执行自己的相关代码\n"); } else { printf("waitpid error\n"); } sleep(1); printf("hello father process\n"); } //pid_t ret = wait(NULL); // int status = 0; // pid_t ret = waitpid(id, &status, 0);//阻塞等待 // // // printf("等待子进程退出成功:ret: %d\n,子进程的信号编号:%d\n 子进程的退出码:%d\n", // // ret, status & 0x7F, (status >> 8) & 0xFF); // // // if(ret > 0) // { // if(WIFEXITED(status)) // { // printf("子进程正常退出,退出码:%d\n", WEXITSTATUS(status)); // } // else // { // printf("子进程异常退出:%d\n", WIFEXITED(status)); // } // } // // // while(1) // { // printf("I am father process! pid: %d, ppid: %d\n", getpid(), getppid()); // sleep(7); // } } return 0; }
[wxq@VM-4-9-centos code_4_10]$ vim process_wait.c [wxq@VM-4-9-centos code_4_10]$ make gcc -o test process_wait.c [wxq@VM-4-9-centos code_4_10]$ ./test 子进程仍在运行,暂时并未退出,父进程可以继续执行自己的相关代码 I am child process! cnt: 4 ,pid: 10576, ppid: 10575 hello father process 子进程仍在运行,暂时并未退出,父进程可以继续执行自己的相关代码 I am child process! cnt: 3 ,pid: 10576, ppid: 10575 hello father process 子进程仍在运行,暂时并未退出,父进程可以继续执行自己的相关代码 I am child process! cnt: 2 ,pid: 10576, ppid: 10575 hello father process I am child process! cnt: 1 ,pid: 10576, ppid: 10575 子进程仍在运行,暂时并未退出,父进程可以继续执行自己的相关代码 hello father process I am child process! cnt: 0 ,pid: 10576, ppid: 10575 子进程仍在运行,暂时并未退出,父进程可以继续执行自己的相关代码 hello father process 子进程仍在运行,暂时并未退出,父进程可以继续执行自己的相关代码 hello father process 等待子进程退出成功,退出码:99 hello father process [wxq@VM-4-9-centos code_4_10]$
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- huatuo2.com 版权所有 湘ICP备2023021991号-2
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务