首页 > 系统相关 >进程控制之wait函数

进程控制之wait函数

时间:2023-02-03 11:25:14浏览次数:32  
标签:status 函数 pid printf 进程 include wait

一、绪论

一个进程在终止时会关闭所有文件描述符,释放在用户空间分配的内存,但它的PCB还保留着,内核在其中保存了一些信息:如果

是正常终止则保存着退出状态,如果是异常终止则保存着导致该进程终止的信号是哪个。这个进程的父进程可以调用waitwaitpi

d获取这些信息,然后彻底清除掉这个进程。

二、wait()

1. 功能:父进程调用wait函数可以回收子进程终止信息。该函数有三个功能:

① 阻塞等待子进程退出

② 回收子进程残留资源

③ 获取子进程结束状态(退出原因)。

wait一旦被调用,就会一直阻塞在这里,直到有一个子进程退出出现为止。

2. 函数原型:

pid_t wait(int *status); 

成功:清理掉的子进程ID;失败:-1 (没有子进程)

使用wait函数传出参数status来保存进程的退出状态 (正常终止→退出值;异常终止→终止信号)。借助宏函数来进一步判断进程终止的具体原因。

宏函数可分为如下三组:

1). WIFEXITED(status) 为非0 → 进程正常结束

    WEXITSTATUS(status) 如上宏为真,使用此宏 → 获取进程退出状态 (exit的参数)

2). WIFSIGNALED(status) 为非0 → 进程异常终止

    WTERMSIG(status) 如上宏为真,使用此宏 → 取得使进程终止的那个信号的编号。

*3). WIFSTOPPED(status) 为非0 → 进程处于暂停状态

    WSTOPSIG(status) 如上宏为真,使用此宏 → 取得使进程暂停的那个信号的编号。

    WIFCONTINUED(status) 为真 → 进程暂停后已经继续运行

3. 例程

复制代码
 1 #include <unistd.h>
 2 #include <stdlib.h>
 3 #include <stdio.h>
 4 #include <sys/wait.h>
 5 
 6 int main(void)
 7 {
 8     pid_t pid, wpid;
 9     int status; //定义传出参数
10 
11     pid = fork();
12     if(pid == -1){
13         perror("fork error");
14         exit(1);
15     } else if(pid == 0){    //子进程
16         printf("I'm process child, pid = %d\n", getpid());
17 #if 0
18         execl("./abnor", "abnor", NULL);
19         perror("execl error");
20         exit(1);
21 #endif
22         sleep(1);                
23         exit(20);
24     } else {
25         //wpid = wait(NULL);     //无传出参数,无需判断
26         wpid = wait(&status);    //status为传出参数,wpid返回的进程ID
27         if(WIFEXITED(status)){    //正常退出 非0
28             printf("I'm parent, The child process%d exit normally\n", wpid);
30             printf("return value:%d\n", WEXITSTATUS(status));//获取退出值31 
32         } else if (WIFSIGNALED(status)) {    //异常退出
33             printf("The child process exit abnormally, killed by signal %d\n", WTERMSIG(status));//获取终止信号编号                                   
36         } else {
37             printf("other...\n");
38         }
39     }
40     return 0;
41 }
复制代码

编译与执行结果:

异常退出:

二、waitpid()

1. 功能与wait相同,但可指定pid进程清理,可以不阻塞。

pid_t waitpid(pid_t pid, int *status, in options);

成功:返回清理掉的子进程ID;失败:-1(无子进程)

特殊参数和返回情况,参数pid:

  > 0 回收指定ID的子进程

  -1 回收任意子进程(相当于wait)

  0 回收和当前调用waitpid一个组的所有子进程

  < -1 回收指定进程组内的任意子进程

注意:

  1)参3为WNOHANG(非阻塞),且子进程正在运行,则返回0。

  2)一次wait或waitpid调用只能清理一个子进程,清理多个子进程应使用循环

2. 例程一

复制代码
 1 #include <sys/types.h>
 2 #include <sys/wait.h>
 3 #include <unistd.h>
 4 #include <stdio.h>
 5 #include <stdlib.h>
 6 int main(void)
 7 {
 8     pid_t pid;
 9     int i;
10     int stat_val;
11 
12     pid = fork();
13 
14     if (pid < 0) {
15         perror("fork failed");
16         exit(1);
17     }
18     if (pid == 0) {
19         for (i = 3; i > 0; i--) {
20             printf("This is the child\n");
21             sleep(1);
22         }
23         exit(34);
24     } else {
25         waitpid(pid, &stat_val, 0);     //0阻塞
26         if (WIFEXITED(stat_val))  ////stat_val为传出参数
27             printf("Child exited with code %d\n", WEXITSTATUS(stat_val));
28         else if (WIFSIGNALED(stat_val))
29             printf("Child terminated abnormally, signal %d\n", WTERMSIG(stat_val));
30     }
31     return 0;
32 }
复制代码

编译与执行结果:

例程二(循环清理多个子进程)

复制代码
 1 #include <stdio.h>
 2 #include <unistd.h>
 3 #include <stdlib.h>
 4 #include <sys/wait.h>
 5 
 6 int main(int argc, char *argv[])
 7 {
 8     int n = 5, i;                
 9     pid_t p;
10 
11     for(i = 0; i < n; i++)     {
12            p = fork();
13        if(p == 0) break;            
14        }
15     if(n == i){  // parent
16         sleep(n);
17         printf("I am parent, pid = %d\n", getpid());
18             for (i = 0; i < n; i++) {
19                 p = waitpid(0, NULL, WNOHANG);
20                 printf("wait  pid = %d\n", p);
21                }
22     } else {
23         sleep(i);
24         printf("I'm %dth child, pid = %d\n", i+1, getpid());
25     }
26     return 0;
27 }
复制代码

编译与执行结果:

 

标签:status,函数,pid,printf,进程,include,wait
From: https://www.cnblogs.com/kn-zheng/p/17088512.html

相关文章

  • 进程控制之僵尸进程和孤儿进程
    一、孤儿进程1.孤儿进程: 父进程先于子进程结束,则子进程成为孤儿进程。子进程成为孤儿进程之后,init进程则会成为其新的父进程,称为init进程领养孤儿进程。2.例程:1......
  • 进程控制之exec函数族
     一、引言进程通过exec函数根据指定的文件名或目录名执行另一个可执行文件,当进程调用exec函数时,该进程的数据段、代码段和堆栈段完全被新程序替换,从新程序的启动例程开始......
  • 进程间通信之fifo
    一、引言FIFO常被称为有名管道,不同于管道(pipe)。pipe仅适用于“有血缘关系”的IPC。但FIFO还可以应用于不相关的进程的IPC。实际上,FIFO是Linux基础文件类型中的一......
  • c++中调用QML中的函数和设置QML中的属性的问题
    1.这里主要是介绍,如何在c++中调用QML中的函数和设置QML中的属性的问题  2.具体代码    //UICtest.qmlimportQt4.7Rectangle{   id:mainWid......
  • kotlin的拓展函数和原理
    kotlin的拓展函数和原理问题背景kotlin的使用过程中有个拓展函数的概念,这个概念在java中是没有的,那么问题来了,kotlin中拓展函数是什么呢?拓展函数的概念:不改变原有类的情......
  • inline内联函数详解
    这几天看题解一直遇到inline所以学习总结一下1、C++inline内联函数(1)引入inline关键字的原因:在c/c++中,为了解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题,特别的引入......
  • c分配内存底层函数 realloc
    realloc(void*__ptr,size_t__size):更改已经配置的内存空间,即更改由malloc()函数分配的内存空间的大小。如果将分配的内存减少,realloc仅仅是改变索引的信息。如果是将......
  • oracle 自定义函数splitstr
     函数主体createorreplacetypetype_splitastableofvarchar2(4000) createorreplacefunctionsplitstr(p_stringvarchar2,......
  • #yyds干货盘点# 歌谣学前端之箭头函数1
    前言我是歌谣我有个兄弟巅峰的时候排名c站总榜19叫前端小歌谣曾经我花了三年的时间创作了他现在我要用五年的时间超越他今天又是接近兄弟的一天人生难免坎坷大不了从......
  • PHP精度计算函数
    bcadd—将两个高精度数字相加bccomp—比较两个高精度数字,返回-1,0,1bcdiv—将两个高精度数字相除bcmod—求高精度数字余数bcmul—将两个高精度数字相乘bc......