进程控制---进程等待(下)
2026/4/27 23:48:22 网站建设 项目流程

目录

进程等待的方法

wait方法

waitpid方法

WEXITSTATUS

WIFEXITED

options

非阻塞调用

那么如何让父进程做自己的事情呢?


继进程等待(上),我们来继续进行下的学习

进程等待的方法

wait方法

#include<sys/types.h>

#include<sys/wait.h>

pid_t wait(int* status);

返回值:

成功返回被等待进程pid,失败返回-1。

参数:

输出型参数,获取子进程退出状态,不关心则可以设置成为NULL

waitpid方法

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:默认为0,表示阻塞等待

WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进程的ID。

WEXITSTATUS

printf("wait success,rid:%d,exit code:%d,exit signal:%d\n",rid,WEXITSTATUS(status),status&0x7F);

[user1@iZ5waahoxw3q2bZ 26-4-25.2]$ cat proc.c #include<stdio.h> #include<errno.h> #include<string.h> #include<stdlib.h> #include<unistd.h> #include<sys/types.h> #include<sys/wait.h> int main() { pid_t id = fork(); if(id == 0) { //子进程 int cnt = 3; while(cnt) { sleep(3); printf("我是一个子进程,pid:%d,ppid:%d\n",getpid(),getppid()); sleep(1); cnt--; } exit(10); } //父进程 //pid_t rid = wait(NULL); //pid_t rid = waitpid(-1,NULL,0); int status = 0; pid_t rid = waitpid(id,&status,0); if(rid > 0) { //printf("wait success,rid:%d,exit code:%d\n",rid,(status>>8)&0xFF);//rid //printf("wait success,rid:%d,exit code:%d,exit signal:%d\n",rid,(status>>8)&0xFF,status&0x7F); printf("wait success,rid:%d,exit code:%d,exit signal:%d\n",rid,WEXITSTATUS(status),status&0x7F); } else { printf("wait failed:%d:%s\n",errno,strerror(errno)); } return 0; }
WIFEXITED
[user1@iZ5waahoxw3q2bZ 26-4-25.2]$ cat proc.c #include<stdio.h> #include<errno.h> #include<string.h> #include<stdlib.h> #include<unistd.h> #include<sys/types.h> #include<sys/wait.h> int main() { pid_t id = fork(); if(id == 0) { //子进程 int cnt = 3; while(cnt) { sleep(3); printf("我是一个子进程,pid:%d,ppid:%d\n",getpid(),getppid()); sleep(1); cnt--; //int *p =0; //*p = 100; int a = 10; a /= 0; } exit(10); } //父进程 //pid_t rid = wait(NULL); //pid_t rid = waitpid(-1,NULL,0); int status = 0; pid_t rid = waitpid(id,&status,0); if(rid > 0) { //printf("wait success,rid:%d,exit code:%d\n",rid,(status>>8)&0xFF);//rid //printf("wait success,rid:%d,exit code:%d,exit signal:%d\n",rid,(status>>8)&0xFF,status&0x7F); if(WIFEXITED(status)) printf("wait success,rid:%d,exit code:%d,exit signal:%d\n",rid,WEXITSTATUS(status),status&0x7F); else printf("子进程退出异常!\n"); } else { printf("wait failed:%d:%s\n",errno,strerror(errno)); } return 0; }
[user1@iZ5waahoxw3q2bZ 26-4-25.2]$ make gcc -o proc proc.c proc.c: In function ‘main’: proc.c:25:15: warning: division by zero [-Wdiv-by-zero] a /= 0; ^ [user1@iZ5waahoxw3q2bZ 26-4-25.2]$ ./proc 我是一个子进程,pid:3948,ppid:3947 子进程退出异常!
options
pid_t waitpid(pid_t pid, int *status, int options);
The value of options is an OR of zero or more of the following constants:

其中options设为WNOHANG

return immediately if no child has exited. 夯住

如果子进程没有结束那就立即返回。

一般默认子进程不退就会阻塞在那,但是如果用WNOHANG

pid_t waitpid(pid_t pid, int *wstatus, int options); | 非阻塞调用 返回值>0:等待结束 =0:调用结束,但是子没有退出 <0:等待失败

张三--用户,你或父进程

打电话--就是一次函数调用

李四--操作系统或子进程

打一次电话就挂,李四没下来--非阻塞

然后多打几次---非阻塞轮询--循环完成

打电话不挂直到李四操作完才返回--阻塞调用

Non Block

非阻塞调用:可以让等待方,做自己的事情!---通常效率会更高一点

非阻塞调用

[user1@iZ5waahoxw3q2bZ 26-4-26]$ cat proc.c #include<stdio.h> #include<errno.h> #include<string.h> #include<stdlib.h> #include<unistd.h> #include<sys/types.h> #include<sys/wait.h> int main() { pid_t id = fork(); if(id == 0) { //子进程 int cnt = 3; while(1) { sleep(3); printf("我是一个子进程,pid:%d,ppid:%d\n",getpid(),getppid()); sleep(1); cnt--; //int *p =0; //*p = 100; //int a = 10; //a /= 0; } exit(10); } //父进程 while(1) { int status = 0; pid_t rid = waitpid(id,&status,WNOHANG); if(rid >0)//成功,获取信息 { printf("wait success,rid:%d,exit code:%d,exit signal:%d\n",rid,(status>>8)&0xFF,status&0x7F);//rid break; } else if(rid ==0) { printf("本轮调用结束,子进程没有退出\n"); sleep(1); } else { printf("等待失败\n"); break; } } return 0; }
[user1@iZ5waahoxw3q2bZ ~]$ kill -9 4068
[user1@iZ5waahoxw3q2bZ 26-4-26]$ ./proc 本轮调用结束,子进程没有退出 本轮调用结束,子进程没有退出 本轮调用结束,子进程没有退出 我是一个子进程,pid:4068,ppid:4067 本轮调用结束,子进程没有退出 本轮调用结束,子进程没有退出 本轮调用结束,子进程没有退出 本轮调用结束,子进程没有退出 我是一个子进程,pid:4068,ppid:4067 本轮调用结束,子进程没有退出 wait success,rid:4068,exit code:0,exit signal:9

非阻塞调用:可以让等待方,做自己的事情!

那么如何让父进程做自己的事情呢?

[user1@iZ5waahoxw3q2bZ 26-4-26]$ cat proc.c #include<stdio.h> #include<errno.h> #include<string.h> #include<stdlib.h> #include<unistd.h> #include<sys/types.h> #include<sys/wait.h> //函数指针类型 typedef void (*func_t)(); #define NUM 5 func_t handlers[NUM+1]; //如下是任务 void DownLoad() { printf("我是一个下载的任务...\n"); } void Flush() { printf("我是一个刷新的任务...\n"); } void Log() { printf("我是一个记录日志的任务...\n"); } //注册 void registerHandler(func_t h[],func_t f) { int i=0; for(;i<NUM;i++) { if(h[i]==NULL)break; } if(i==NUM) return; h[i]=f; h[i+1]=NULL; } int main() { registerHandler(handlers,DownLoad); registerHandler(handlers,Flush); registerHandler(handlers,Log); pid_t id = fork(); if(id == 0) { //子进程 int cnt = 3; while(1) { sleep(3); printf("我是一个子进程,pid:%d,ppid:%d\n",getpid(),getppid()); sleep(1); cnt--; //int *p =0; //*p = 100; //int a = 10; //a /= 0; } exit(10); } //父进程 while(1) { int status = 0; pid_t rid = waitpid(id,&status,WNOHANG); if(rid >0)//成功,获取信息 { printf("wait success,rid:%d,exit code:%d,exit signal:%d\n",rid,(status>>8)&0xFF,status&0x7F);//rid break; } else if(rid ==0) { //函数指针进行回调 int i=0; for(;handlers[i];i++) { handlers[i](); } printf("本轮调用结束,子进程没有退出\n"); sleep(1); } else { printf("等待失败\n"); break; } } return 0; }
[user1@iZ5waahoxw3q2bZ 26-4-26]$ make gcc -o proc proc.c [user1@iZ5waahoxw3q2bZ 26-4-26]$ ./proc 我是一个下载的任务... 我是一个刷新的任务... 我是一个记录日志的任务... 本轮调用结束,子进程没有退出 我是一个下载的任务... 我是一个刷新的任务... 我是一个记录日志的任务... 本轮调用结束,子进程没有退出 我是一个下载的任务... 我是一个刷新的任务... 我是一个记录日志的任务... 本轮调用结束,子进程没有退出 我是一个子进程,pid:4109,ppid:4108

感谢你的观看,期待我们下次再见!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询