首页 > 系统相关 >父进程等待子进程结束后再结束

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

时间:2023-08-22 22:11:29浏览次数:28  
标签:结束 int pid 进程 include 等待 wait

文章涉及以下问题:

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

标签:结束,int,pid,进程,include,等待,wait
From: https://www.cnblogs.com/hi-wind/p/17649835.html

相关文章

  • nodejs 使用exec ,execFile,spawn运行子进程区别,以及如何正确的的关闭子进程
    exec,execFile,spawn都是运行一个子进程,但是在不同的操作系统上用法和表现有很大差异。linux/unixexec运行子进程需要创建一个终端环境(命令行窗口),然后在其中运行命令,execFile则不需要,因此在linux/unix上,execFile的效率更高。windows在windows平台上,运行脚本程序(如批处理.bat)必须有......
  • 查看cpu或内存占用最多的进程
    通过ps命令查找,并对指定参数进行排序,然后取前10命令如下:ps-aux|sort-k3nr|head-10或者ps-aux|sort-k4nr|head-10ps命令用于报告当前系统的进程状态。可以搭配kill指令随时中断、删除不必要的程序。ps命令是最基本同时也是非常强大的进程查看命令,使用该命令可......
  • shell中的进程替换功能
    进程替换(ProcessSubstitution)是某些Unix-like系统中shell(特别是Bash和Zsh)提供的一种高级特性。它允许你使用进程的输出作为其他进程的输入,而不需要使用管道或临时文件。这主要是通过使用特殊的文件描述符来实现的。进程替换的常见语法如下:<()-将命令的输出作为输入提......
  • linux启动tomcat后,关闭ssh连接,tomcat进程停止
    在tomcat停止后会报错:org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesJdbcWeb应用程序[ROOT]注册了JDBC驱动程序[com.alibaba.druid.proxy.DruidDriver],但在Web应用程序停止时无法注销它。为防止内存泄漏,JDBC驱动程序已被强制取消注册。我以为是代码的问......
  • 【11.0】Linux之进程管理
    【一】介绍【1】什么是进程比如:开发写的代码我们称为程序,那么将开发的代码运行起来。我们称为进程。总结一句话就是:当我们运行一个程序,那么我们将运行的程序叫进程。PS1:当程序运行为进程后,系统会为该进程分配内存,以及进程运行的身份和权限。PS2:在进程运行的过程中,系......
  • OS(四):进程管理之进程的同步
    进程同步的主要任务是对多个相关进程在执行次序上进行协调,以使并发执行的诸进程之间能有效的共享资源、相互合作,使程序的执行具有可再现性。1、进程同步的基本概念1.1、进程间的制约关系OS中的进程存在两种形式的制约关系。一种是源于进程间的合作的直接相互制约......
  • 进程管理
    进程、线程、协程的区别:资源分配的基本单位资源调度的基本单位轻量级的线程切换页表、栈等程序计数器、栈、寄存器等栈和寄存器切换代价越来越小协程不用进入内核态,在用户态。它两陷入内核态的原因:进入内核态保存上下文信息。进程的通信方式管道:通信方式是效率低的......
  • OS(三):进程管理之进程的控制
    控制进程的程序段,进程控制一般是由OS的内核中的原语来实现的。原语是不可再分的原子操作(ActionOperation),执行过程中不会被打断。1、原语2.1、原语概念原语的概念:由若干条指令组成,完成特定的功能,是一种原子操作(ActionOperation)。2.2、原语特点原语的特点:原子......
  • OS(二):进程管理的基本概念
    进程是资源分配和独立运行的基本单位。引入进程的目的在于,使多道程序并发执行,提高系统的资源利用率和吞吐量;而引入线程,是为了减少程序在并发时的时空开销,提高系统的并发性,线程相对于进程,大大降低了创建、撤销和切换可执行实体的成本和难度。1、进程的定义与特征1.1、定......
  • 逆向 | 简单调试器检测&调试器进程检测、虚拟机进程检测、启动路径检测、计算机名检测
    逆向|简单调试器进程检测、虚拟机进程检测、启动路径检测、计算机名检测写在自己书里的代码,丢一份到blog。简单调试器检测:#include<stdio.h>#include<windows.h>//定义枚举值constintProcessDebugPort=0x7;constintProcessDebugObjectHandle=0x1e;constint......