c 中的 forking、waitpid 问题
由于某种原因,这段代码立即执行父母命令,终止我的信号量并搞乱我对其他程序的流量控制。谁能告诉我为什么 waitpid() 不起作用?
//Create child processes
pid = fork();
if(pid < 0){
fprintf(stderr, "Fork Failed.\n");
exit(1);
return;
}else if(pid==0){
if(execl("/home/tropix/hw11-2","/home/tropix/hw11-2",semarg,pipe_to_p3,pipe_to_p4,(char*)0)){
fprintf(stderr, "File Exexecution of hw11-2 failed.\n");
exit(1);
}
} else {
pid = fork();
if(pid < 0){
fprintf(stderr, "Fork Failed.\n");
exit(1);
return;
} else if(pid==0){
if(execl("/home/tropix/hw11-3","/home/tropix/hw11-3",shmarg,semarg,pipe_from_p2,pipe_to_p5_1, (char*)0)){
fprintf(stderr, "File Execution of hw11-3 failed.\n");
exit(1);
}
} else {
pid = fork();
if(pid < 0){
fprintf(stderr, "Fork Failed.\n");
exit(1);
return;
} else if (pid == 0){
if(execl("/home/tropix/hw11-4","/home/tropix/hw11-4",shmarg,semarg,pipe_from_p2_2,pipe_to_p5_2, (char*)0)){
fprintf(stderr, "File Execution of hw11-4 failed.\n");
exit(1);
}
} else {
pid = fork();
if(pid < 0){
fprintf(stderr, "Fork Failed.\n");
exit(1);
return;
} else if (pid == 0){
if(execl("/home/tropix/hw11-5","/home/tropix/hw11-5",semarg,pipe_from_p3,pipe_from_p4,(char*)0)){
fprintf(stderr, "File Execution of hw11-5 failed.\n");
exit(1);
}
} else if (pid > 0) {
}
}
}
//Closing Pipes
close(pipe1[1]);
close(pipe2[1]);
close(pipe3[1]);
close(pipe4[1]);
close(pipe1[0]);
close(pipe2[0]);
close(pipe3[0]);
close(pipe4[0]);
//Wait for child process completetion
waitpid(pid,NULL,0);
printf("Child Processes Complete.\n");
//Terminate Semaphores
semctl(sem_id,0,IPC_RMID);
//Terminate Shared Memory Segement
shmctl(shmid, IPC_RMID, NULL);
}
}
谢谢!
编辑:好的,我用:替换了 waitpid
while (pid = waitpid(-1, NULL, 0)) {
if (errno == ECHILD) {
break;
}
}
,这让我完成了部分工作。它不会立即执行家长控制,但现在似乎永远不会执行。至于你谈到的管道问题,程序1(这个)应该终止所有IPC元素,包括管道。如果有更好的方法,我很想听听。
谢谢@乔纳森
For some reason this code executes the parental commands immediately, terminating my semaphores and screwing up my flow control of other programs. Can anyone tell me why the waitpid() isnt working?
//Create child processes
pid = fork();
if(pid < 0){
fprintf(stderr, "Fork Failed.\n");
exit(1);
return;
}else if(pid==0){
if(execl("/home/tropix/hw11-2","/home/tropix/hw11-2",semarg,pipe_to_p3,pipe_to_p4,(char*)0)){
fprintf(stderr, "File Exexecution of hw11-2 failed.\n");
exit(1);
}
} else {
pid = fork();
if(pid < 0){
fprintf(stderr, "Fork Failed.\n");
exit(1);
return;
} else if(pid==0){
if(execl("/home/tropix/hw11-3","/home/tropix/hw11-3",shmarg,semarg,pipe_from_p2,pipe_to_p5_1, (char*)0)){
fprintf(stderr, "File Execution of hw11-3 failed.\n");
exit(1);
}
} else {
pid = fork();
if(pid < 0){
fprintf(stderr, "Fork Failed.\n");
exit(1);
return;
} else if (pid == 0){
if(execl("/home/tropix/hw11-4","/home/tropix/hw11-4",shmarg,semarg,pipe_from_p2_2,pipe_to_p5_2, (char*)0)){
fprintf(stderr, "File Execution of hw11-4 failed.\n");
exit(1);
}
} else {
pid = fork();
if(pid < 0){
fprintf(stderr, "Fork Failed.\n");
exit(1);
return;
} else if (pid == 0){
if(execl("/home/tropix/hw11-5","/home/tropix/hw11-5",semarg,pipe_from_p3,pipe_from_p4,(char*)0)){
fprintf(stderr, "File Execution of hw11-5 failed.\n");
exit(1);
}
} else if (pid > 0) {
}
}
}
//Closing Pipes
close(pipe1[1]);
close(pipe2[1]);
close(pipe3[1]);
close(pipe4[1]);
close(pipe1[0]);
close(pipe2[0]);
close(pipe3[0]);
close(pipe4[0]);
//Wait for child process completetion
waitpid(pid,NULL,0);
printf("Child Processes Complete.\n");
//Terminate Semaphores
semctl(sem_id,0,IPC_RMID);
//Terminate Shared Memory Segement
shmctl(shmid, IPC_RMID, NULL);
}
}
Thanks!
EDIT: Ok, I replaced waitpid with:
while (pid = waitpid(-1, NULL, 0)) {
if (errno == ECHILD) {
break;
}
}
and that got me part of the way there. It isnt executing the parental controls immediately, but it seems to never execute now. As far as the pipe issue you talked about, program 1 (this one) is supposed to terminate all IPC elements, including the pipes. If there is a better way, I would love to hear it.
Thanks @Jonathan
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您只需等待一个进程完成,而不是等待所有进程完成。这可能是一个问题。使用
waitpid()
上的循环进行修复,直到返回“no more kids”。代码的结构还有一些不足之处——它是一个嵌套 if 的兔子窝;恶心!
我担心在执行其他命令之前您没有关闭足够的管道。如果命令不依赖于检测管道上的 EOF,那么您可能没问题;否则,你将要等待很长时间。
您需要一个如下功能:
这可以简化您的错误处理。如果您愿意,您还可以执行一些操作,例如自动添加即将终止的 PID 或触发退出的错误。
我们还可以创建一个函数来运行另一个命令:
有了这些命令,我们就可以将代码简化为这样...
嗯...其中一些具有
shmarg
,而有些则没有- 这种不一致是有意的还是偶然的?我们假设是故意的,所以我们需要两个版本的“run_command()”:然后:
如果这是我的代码,变量的名称会更统一 - 并且可能在数组中:
然后,最后,你就有了代码:
我非常怀疑
run_cmdX()
函数还需要关闭大量管道选择 - 至少管道的每个描述符不用于与其子进程通信。干净地组织起来比较困难——但可以小心地完成。我可能会在单个数组中创建管道:
然后创建一个函数:
然后可以调用它来关闭不需要的管道:
您只需安排每个
传递正确的掩码run_cmdN()
函数,以及要进行的正确调用。如果 Pipes 数组不是全局的,则也需要传递该数组。我还会研究如何对数据进行整齐编码,以便对 run_cmdN() 的调用尽可能规则和对称。克尼根和Plauger 的“编程风格的要素”(第 2 版,1978 年;很难找到,我怀疑)包含许多精彩的引言。直接相关的是(加粗强调,原文斜体):
这可以被视为 DRY(不要重复自己)编程原则的一部分。
err_exit()
函数调用封装了三行或四行代码 - 打印和退出加上大括号,具体取决于您首选的布局。run_command()
函数是 DRY 的一个主要例子。提议的pipe_closer()
是另一个。You only wait for one process to complete - not for all processes to complete. That is probably one problem. Fix with a loop on
waitpid()
until it returns 'no more kids'.The structure of the code leaves something to be desired - it is a rabbit's warren of nested if's; ick!
I worry that you are not closing enough pipes before the other commands are executed. You may be OK if the commands do not depend on detecting EOF on a pipe; otherwise, you are in for a long wait.
You need a function like:
This simplifies your error handling. You can also do things like automatically add the PID that is dying, or the error that triggered the exit, if you wish.
We can also create a function to run another command:
With those in place, we can look to reduce your code to this...
Hmmm...some of these have the
shmarg
and some don't - is that inconsistency intentional or accidental? We'll assume intentional, so we need two versions of 'run_command()':And then:
If it was my code, the names of the variables would be more uniform - and probably in arrays:
Then, finally, you have the code:
I am deeply suspicious that the
run_cmdX()
functions also need to close a large selection of the pipes - at least every descriptor of the pipes not intended for communication with their sub-process.Organizing that cleanly is trickier - but can be done with care. I'd probably create the pipes in a single array:
Then I'd create a function:
Then it can be called to close the unneeded pipes:
You just have to arrange for the right mask to be passed with each of the
run_cmdN()
functions, and the correct calls to be made. If thepipes
array is not global, that will need to be passed too. I'd also look at how to encode the data tidily so that the calls torun_cmdN()
are as regular and symmetric as possible.Kernighan & Plauger's "The Elements of Programming Style" (2nd Edn, 1978; hard to find, I suspect) contains many magnificent quotes. The immediately apposite one is (bold emphasis added, italics in original):
This can be viewed as part of the DRY (Don't Repeat Yourself) principle of programming. The
err_exit()
function call encapsulates three or four lines of code - a print and an exit plus the braces, depending on your preferred layout. Therun_command()
functions are a prime case of DRY. The proposedpipe_closer()
is yet another.