父进程等待子进程结束后再结束

文章涉及以下问题:

1.父进程创建了多个子进程,等待全部子进程均结束后再结束

2.父进程创建了多个子进程,等待一个子进程结束后就结束

wait()与waitpid()

父进程的 wait(),waitpid()与子进程的 exit(0)一一对应,一个wait,waitpid等一个exit

其中,

wait()

pid_t wait(int *status);

返回值:pid_t等价于int

状态 返回值
成功 成功结束运行的子进程的进程号
失败 -1

参数

  • 参数status如果不是一个空指针,则终止进程的终止状态就存放在statloc所指向的单元。
  • 参数status如果是一个空指针,则表示父进程不关心子进程的终止状态

waitpaid()

参数

PID值 结果
pid>0 只等待进程ID等于pid的子进程,不管其它已经有多少子进程运行结束退出了,只要指定的子进程还没有结束,waitpid就会一直等下去。
pid=-1 等待任何一个子进程退出,没有任何限制,此时waitpid和wait的作用一模一样。
pid=0 等待同一个进程组中的任何子进程,如果子进程已经加入了别的进程组,waitpid不会对它做任何理睬。
pid<-1 等待一个指定进程组中的任何子进程,这个进程组的ID等于pid的绝对值。
status 结果
NULL 表示父进程不关心子进程的终止状态
某个指针或者地址 终止进程的终止状态就存放在status所指向的单元
OPTION col2
WNOHANG 若由pid指定的子进程未发生状态改变(没有结束),则waitpid()不阻塞,立即返回0
WUNTRACED 返回终止子进程信息和因信号停止的子进程信息
WCONTINUED 返回收到SIGCONT信号而恢复执行的已停止子进程状态信息

返回值

成功:返回成功结束的子进程的进程号

失败:返回-1

WNOHANG:没有子进程退出返回0

有一个子进程返回,父进程就结束

观察以下两个代码:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

int main() {
    int num_processes = 3;  // 设置子进程的数量

    for (int i = 0; i < num_processes; i++) {
        pid_t pid = fork();

        if (pid == 0) {
            // 子进程的代码
            printf("子进程 %d 开始\n", getpid());
            sleep(2);  // 模拟子进程的工作
            printf("子进程 %d 结束\n", getpid());
            exit(0);  // 子进程退出了,不再继续执行for
        }
    }

    // 父进程等待所有子进程结束
    // for (int i = 0; i < num_processes; i++) {
    //     wait(NULL);
    // }
    wait(NULL);
    printf("所有子进程都已经结束,父进程也结束\n");
    return 0;
}

在这段代码中,父进程用一个for创建了3个子进程,然后只用了一个wait,因此当这个wait接受到一个exit后,就不再阻塞父进程,父进程就继续执行,进而结束,然后没执行完的子进程继续执行,直到结束:(多运行几次)

img

img

发现是这样的。

等所有子进程返回后父进程再结束

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

int main() {
    int num_processes = 3;  // 设置子进程的数量

    for (int i = 0; i < num_processes; i++) {
        pid_t pid = fork();

        if (pid == 0) {
            // 子进程的代码
            printf("子进程 %d 开始\n", getpid());
            sleep(2);  // 模拟子进程的工作
            printf("子进程 %d 结束\n", getpid());
            exit(0);
        }
    }

    // 父进程等待所有子进程结束
    for (int i = 0; i < num_processes; i++) {
        wait(NULL);
    }
    // wait(NULL);
    printf("所有子进程都已经结束,父进程也结束\n");
    return 0;
}

三个exit对应三个wait;

因此结果为:

img

父进程等待某个子进程结束后再结束

用waitpid()

那么怎么得到某个指定的子进程的pid呢?

fork函数啊!!

fork对于父进程来说,返回创建的子进程的pid

因此我们可以如下实现:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

int main() {
    int num_processes = 3;  // 设置子进程的数量
    int child = -1;
    for (int i = 0; i < num_processes; i++)
    {
        pid_t pid = fork();
        if (pid != 0){
            if(i == 1){  // 等第二个子进程退出后再父进程退出
                child = pid;
                printf("第二个子进程:%d\n", pid);
            }
        }

        if (pid == 0) {
            // 子进程的代码
            printf("子进程 %d 开始\n", getpid());
            sleep(2);  // 模拟子进程的工作
            printf("子进程 %d 结束\n", getpid());
            exit(0);
        }
    }

    int t = waitpid(child, NULL, WUNTRACED);

    printf("第二个子进程:%d 已经结束,父进程也结束\n", t);
    return 0;
}

结果:

img

waitpid的第三个参数具体啥用我也不是很清楚

不过经过测试,用

int t = waitpid(child, NULL, WUNTRACED);

就行,t指出了结束的子进程的 pidchild为要结束的进程的 pid

posted @ 2023-08-22 22:09  诗子黎  阅读(117)  评论(0编辑  收藏  举报