欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 培训 > [操作系统] 进程等待

[操作系统] 进程等待

2026/2/1 14:12:07 来源:https://blog.csdn.net/SDFsoul/article/details/145568740  浏览:    关键词:[操作系统] 进程等待

进程等待(Process Waiting)是操作系统中父进程用于管理和同步子进程的重要机制。根据你的图片内容,我们可以分几个部分来讲解进程等待的相关知识。


为什么需要进程等待?

当一个进程创建了子进程后,子进程会独立运行。如果父进程不进行等待,它可能会比子进程更早终止,导致子进程变成僵尸进程(Zombie Process),即进程已经终止但父进程没有回收它的资源,造成内存泄漏。

另外,进程⼀旦变成僵⼫状态,那就⼑枪不⼊,“杀⼈不眨眼”的kill -9 也⽆能为⼒,因为谁也没有办法杀死⼀个已经死去的进程。

我们需要知道⽗进程派给⼦进程的任务完成的如何。如,子进程是否完成,结果是否正确。

因此,父进程通过进程等待的⽅式,回收⼦进程资源,获取⼦进程退出信息


进程等待的方式

进程等待主要有两种方式:

  1. pid_t **wait**(int *status);** 函数**
  2. pid_t **waitpid**(pid_t pid, int *status, int options);** 函数**

wait 函数

#include <sys/types.h>
#include <sys/wait.h>pid_t wait(int *status);
  • wait 会阻塞父进程,直到任意一个子进程退出。
  • 返回退出的子进程的 PID。
  • status 指向一个整数变量,用于存储子进程的退出状态。

示例代码

int status;
pid_t pid = wait(&status);

这行代码会让父进程暂停执行,直到有一个子进程结束,并将其退出状态存储到 status 变量。


waitpid 函数

pid_t waitpid(pid_t pid, int *status, int options);
  • waitpid 提供比 wait 更灵活的进程等待方式。
  • pid 参数决定了要等待哪个子进程:
    • pid > 0:等待指定的子进程。
    • pid == -1:等待任意子进程(等价于 wait)。
    • pid == 0:等待与当前进程同组的任何子进程。
    • pid < -1:等待特定进程组的子进程。
  • options 参数:
    • 0:默认阻塞等待子进程退出。
    • WNOHANG:非阻塞模式,如果没有子进程退出,则立即返回 0
    • WUNTRACED:等待子进程停止(如 Ctrl+Z)。
    • WCONTINUED:等待已经继续执行的子进程(如 SIGCONT 信号)。

示例代码

int status;
pid_t pid = waitpid(-1, &status, 0);

此代码与 wait 类似,等待任意子进程结束。


如何获取子进程的退出状态?

waitwaitpid参数中的int *status是输出型参数,当做位图来看待,通过传入变量地址然后经过函数处理后得到对应结果,传入NULL则表示不关心子进程退出状态信息,否则操作系统会通过该参数将子进程的退出信息返回给父进程。

int有四字节,32比特位, waitpid 返回的 status 值只使用了 低 16 位(2 字节) 来存储进程的退出状态或终止信号信息。

具体的信息存储如图所示。

  1. 正常终止:如果进程是 **exit(n)** 退出的,
    • 高 8 位存储 exit(n) 返回的值 n
    • 低 7 位全 0,表示不是被信号终止的。
  2. 如果进程是被信号终止的
    • 低 7 位存储终止信号编号(如 SIGKILL=9)。
    • 第 7 位(bit 7)表示是否生成 core dump。(后续讲解)
    • 高 8 位无意义。

也就是说:

  • 正常退出:status = (exit_code << 8)
  • 信号终止:status = signal_number | (core_dump_flag << 7)

代码示例:

#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main()
{pid_t pid;if ( (pid=fork()) == -1 )perror("fork"),exit(1);if ( pid == 0 ){sleep(20);exit(10);} else {int st;int ret = wait(&st);if ( ret > 0 && ( st & 0X7F ) == 0 ){ // 正常退出printf("child exit code:%d\n", (st>>8)&0XFF);} else if( ret > 0 ) { // 异常退出printf("sig code : %d\n", st&0X7F );}}
}

测试结果:

# ./a.out #等20秒退出 
child exit code:10 
# ./a.out #在其他终端kill掉 
sig code : 9

信息的宏解析

子进程退出时,status 变量会存储一些信息,可以使用以下宏解析:

  • WIFEXITED(status):如果子进程正常退出,返回非零值。
    • WEXITSTATUS(status):获取子进程的退出码。
  • WIFSIGNALED(status):如果子进程是被信号终止的,返回非零值。
    • WTERMSIG(status):获取终止子进程的信号编号。
  • WIFSTOPPED(status):如果子进程因 SIGSTOP 进入暂停状态,返回非零值。
    • WSTOPSIG(status):获取导致暂停的信号编号。

示例代码

if (WIFEXITED(status)) 
{printf("Child exited with status %d\n", WEXITSTATUS(status));
} 
else if (WIFSIGNALED(status)) 
{printf("Child terminated by signal %d\n", WTERMSIG(status));
}

非阻塞等待

waitpid()参数中WNOHANG 选项可用于非阻塞模式,即如果没有子进程退出,则 waitpid 立即返回 0,不会阻塞父进程。

示例代码

while (1) 
{int status;pid_t pid = waitpid(-1, &status, WNOHANG);if (pid > 0) {printf("Child %d exited\n", pid);} else if (pid == 0) {printf("No child exited yet\n");}sleep(1); // 避免 CPU 过载
}

进程等待的示意图

  1. 父进程调用 wait/waitpid 等待子进程结束
  2. 子进程执行任务后终止
  3. 父进程回收子进程资源,避免僵尸进程


进程等待的应用场景

  • 防止僵尸进程:确保子进程结束后,父进程回收其资源。
  • 管理多个子进程waitpid 可以指定等待特定的子进程,适用于多子进程管理。
  • 避免阻塞主进程:使用 WNOHANG 选项,使主进程可以继续执行其他任务。

总结

  • wait 适用于简单场景,等待任意子进程结束。
  • waitpid 提供更精细的控制,支持非阻塞模式。
  • WIFEXITED 等宏可以解析子进程的退出状态。
  • WNOHANG 选项可以实现非阻塞等待,防止父进程卡死。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词