文章涉及以下问题:
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后,就不再阻塞父进程,父进程就继续执行,进而结束,然后没执行完的子进程继续执行,直到结束:(多运行几次)
发现是这样的。
等所有子进程返回后父进程再结束
#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;
因此结果为:
父进程等待某个子进程结束后再结束
用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;
}
结果:
waitpid的第三个参数具体啥用我也不是很清楚
不过经过测试,用
int t = waitpid(child, NULL, WUNTRACED);
就行,t
指出了结束的子进程的 pid
,child
为要结束的进程的 pid