在 C 中等待兄弟进程
Wait for sibling process in C
当我在使用 C 并尝试了解有关进程、分叉和等待的更多信息时,我遇到了一个问题,我无法等待同级进程完成,直到我可以继续。
那么,问题来了:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <stdlib.h>
int processoDisplayLyric;
int processoDisplayGraph;
int processoTimer;
int main(){
int numeroMusicaAtual = 0;
int continueWorking = 0;
int fathersPID = getpid();
while(continueWorking == 0) {
//Create graph process
processoDisplayGraph = fork();
if(processoDisplayGraph == 0){
int work = 0;
while(work == 0){
pause();
}
}
if(processoDisplayGraph != 0){
//Create lyric process.
processoDisplayLyric = fork();
if(processoDisplayLyric == 0){
int work = 0;
while(work == 0){
pause();
}
}
}
if(processoDisplayLyric != 0 && processoDisplayGraph != 0){
//Create timer process.
processoTimer = fork();
if(processoTimer == 0){
printf("I was created and i just want to wait for my brothers.\n");
}
}
if(getpid() != fathersPID){
wait(processoDisplayLyric);
wait(processoDisplayGraph);
}else{
//It's the father.
int child_status;
for (int i = 0; i < 2; i++) {
pid_t wpid = waitpid(processoDisplayLyric, &child_status, 0);
if (WIFEXITED(child_status))
printf("Saw %d done with %d\n", wpid, WEXITSTATUS(child_status));
else
printf("Child %d terminated abnormally\n", wpid);
}
}
numeroMusicaAtual++;
}
}
问题是:创建了 processDisplayLyric、processDisplayGraph 和 processTimer,但是,Timer 不会等待其他两个完成(永远不应该发生的事情!!!)。
在标准 POSIX 下,只有 parent 进程可以等待其(立即)children 结束。
兄弟进程不能等待其他兄弟进程死亡。
Child 个进程无法等待 parent 个进程死亡。
grandparent进程不能等grandchildren死掉。
有一些方法可以检测 parent 进程是否已死(getppid()
的结果是 1
,或者如果您记录了原始 PPID,则表明它失败)。您可以查明是否可以发出已知 PID 的信号——如果它不存在,则不能。在某些使用其他 API 的平台上可能有一些替代方案。但是对于兄弟姐妹或 parents(或任何其他相关过程),没有与 wait()
的一般类比——只能等待 children。
请注意,Linux 的最新版本(自内核 3.4 起)具有 prctl()
系统调用。 PR_SET_CHILD_SUBREAPER
选项允许系统进程(通常为 PID 1)以外的进程在其进程层次结构中收集 dead children 的状态信息。那仍然没有收集兄弟进程;它只能收集 children、grandchildren、great-grandchildren 等。
当我在使用 C 并尝试了解有关进程、分叉和等待的更多信息时,我遇到了一个问题,我无法等待同级进程完成,直到我可以继续。
那么,问题来了:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <stdlib.h>
int processoDisplayLyric;
int processoDisplayGraph;
int processoTimer;
int main(){
int numeroMusicaAtual = 0;
int continueWorking = 0;
int fathersPID = getpid();
while(continueWorking == 0) {
//Create graph process
processoDisplayGraph = fork();
if(processoDisplayGraph == 0){
int work = 0;
while(work == 0){
pause();
}
}
if(processoDisplayGraph != 0){
//Create lyric process.
processoDisplayLyric = fork();
if(processoDisplayLyric == 0){
int work = 0;
while(work == 0){
pause();
}
}
}
if(processoDisplayLyric != 0 && processoDisplayGraph != 0){
//Create timer process.
processoTimer = fork();
if(processoTimer == 0){
printf("I was created and i just want to wait for my brothers.\n");
}
}
if(getpid() != fathersPID){
wait(processoDisplayLyric);
wait(processoDisplayGraph);
}else{
//It's the father.
int child_status;
for (int i = 0; i < 2; i++) {
pid_t wpid = waitpid(processoDisplayLyric, &child_status, 0);
if (WIFEXITED(child_status))
printf("Saw %d done with %d\n", wpid, WEXITSTATUS(child_status));
else
printf("Child %d terminated abnormally\n", wpid);
}
}
numeroMusicaAtual++;
}
}
问题是:创建了 processDisplayLyric、processDisplayGraph 和 processTimer,但是,Timer 不会等待其他两个完成(永远不应该发生的事情!!!)。
在标准 POSIX 下,只有 parent 进程可以等待其(立即)children 结束。
兄弟进程不能等待其他兄弟进程死亡。
Child 个进程无法等待 parent 个进程死亡。
grandparent进程不能等grandchildren死掉。
有一些方法可以检测 parent 进程是否已死(getppid()
的结果是 1
,或者如果您记录了原始 PPID,则表明它失败)。您可以查明是否可以发出已知 PID 的信号——如果它不存在,则不能。在某些使用其他 API 的平台上可能有一些替代方案。但是对于兄弟姐妹或 parents(或任何其他相关过程),没有与 wait()
的一般类比——只能等待 children。
请注意,Linux 的最新版本(自内核 3.4 起)具有 prctl()
系统调用。 PR_SET_CHILD_SUBREAPER
选项允许系统进程(通常为 PID 1)以外的进程在其进程层次结构中收集 dead children 的状态信息。那仍然没有收集兄弟进程;它只能收集 children、grandchildren、great-grandchildren 等。