fork() 导致为每个进程打印列标题
我正在编写一个简单的 C 程序,使用 fork() 创建进程的二叉树。我能够获得所需的所有输出(进程的 pid、其父进程及其两个子进程)。不幸的是,每个分叉进程都想要打印出列标题。如何确保标题的 printf 仅执行一次?
# include <stdio.h>
# include <stdlib.h>
# include <sys/types.h>
# include <unistd.h>
# include <sys/wait.h>
int main(int argc, char *argv[]){
//Declarations
int i;
int child_1_pid, child_2_pid;
int num_levels = atoi(argv[1]);
//Output banners
//execlp("/bin/echo", "echo", "Level\tProcs\tParent\tChild1\tChild2\nNo.\tID\tID\tID\tID", (char *) NULL);
//if(getpid() > 0)
printf("Level\tProcs\tParent\tChild1\tChild2\nNo.\tID\tID\tID\tID");
//Creates binary tree of processes
for(i = 0; i < num_levels; i++){
if((child_1_pid = fork()) && (child_2_pid = fork())){
printf("\n%d\t%d\t%d\t%d\t%d", i, getpid(), getppid(), child_1_pid, child_2_pid);
sleep(2); //prevents parent from terminating before child can get ppid (parent's pid)
break; //why?
}
}//end for
printf("\n"); //EXPLAIN ME!!
exit(0);
}//end main
还有更多代码(确实是错误检查),但我真正的问题是输出横幅部分下的 printf 执行多次,给出如下输出(但正确对齐):
关卡过程父级子级1子级2 编号 ID ID ID ID ID 编号 ID ID ID ID ID 编号 ID ID ID ID ID 编号 ID ID ID ID ID 编号 ID ID ID ID ID 编号 ID ID ID ID ID 编号 ID ID ID ID ID 0 30796 24743 30797 30798 1 30797 30796 30799 30800 1 30798 30796 30801 30802
我尝试了一些想法(包括在横幅部分下注释掉的想法),但似乎没有任何效果,而且大多数“修复”都会使问题变得更糟!
I'm writing a simple C program using fork() to create a binary tree of processes. I am able to get all the output I need (pid's of process, its parent, and its two children). Unfortunately, each forked process wants to print out the column headers. How do I make sure that the printf for the headers is executed only once?
# include <stdio.h>
# include <stdlib.h>
# include <sys/types.h>
# include <unistd.h>
# include <sys/wait.h>
int main(int argc, char *argv[]){
//Declarations
int i;
int child_1_pid, child_2_pid;
int num_levels = atoi(argv[1]);
//Output banners
//execlp("/bin/echo", "echo", "Level\tProcs\tParent\tChild1\tChild2\nNo.\tID\tID\tID\tID", (char *) NULL);
//if(getpid() > 0)
printf("Level\tProcs\tParent\tChild1\tChild2\nNo.\tID\tID\tID\tID");
//Creates binary tree of processes
for(i = 0; i < num_levels; i++){
if((child_1_pid = fork()) && (child_2_pid = fork())){
printf("\n%d\t%d\t%d\t%d\t%d", i, getpid(), getppid(), child_1_pid, child_2_pid);
sleep(2); //prevents parent from terminating before child can get ppid (parent's pid)
break; //why?
}
}//end for
printf("\n"); //EXPLAIN ME!!
exit(0);
}//end main
There's some more code (error checking really), but my real problem is that the printf under the output banners section executes multiple times, giving output like this (but correctly aligned):
Level Procs Parent Child1 Child2 No. ID ID ID ID No. ID ID ID ID No. ID ID ID ID No. ID ID ID ID No. ID ID ID ID No. ID ID ID ID No. ID ID ID ID 0 30796 24743 30797 30798 1 30797 30796 30799 30800 1 30798 30796 30801 30802
I've tried a few ideas (including those commented out under the banner section), but nothing seems to work and most "fixes" make the problem even worse!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
首先,for 循环中的
if
的行为并不如您所愿。请记住,fork 后,它在父进程中返回子进程 PID,在子进程中返回 0。因此,在循环内部,第一个 fork 为父级中的 child_1_pid 赋值,并继续执行第二个子句。子级不会输入if
而是继续下一个 for 循环迭代。第二个子句也发生同样的情况。因此,只有主进程才能进入if
的主体,而子进程不能进入。我想知道为什么输出表明不是这样。因此,要获得“二叉树”,您实际上应该具有以下内容:
横幅的奇怪输出与流的刷新有关。通常,fprintf 仅在换行符 (
\n
) 上刷新,IIRC。因此,在分叉之后,缓冲区中仍然有尚未刷新的内容,并且每个子进程都运行printf("\n");
,从而刷新缓冲区内容。解决方案是在第一个 printf 的末尾添加“\n”,或者在
for
循环之前调用fflush(stdout);
。First, the
if
in the for-loop does not behave as you want it to. Remember that after the fork, it returns the child PID in the parent process and 0 in the child. So inside the loop, the first fork assigns a value to child_1_pid in the parent and continues to the second clause. The child does not enter theif
but continues to the next for-loop iteration. The very same happens with the second clause. So only the main process should ever be able to enter the body of theif
, but no child process. I wonder why the output suggests otherwise.So to get your "binary tree", you should actually have this:
The strange output of the banners has to do with flushing of streams. Normally, fprintf only flushed on newline (
\n
), IIRC. So there's still stuff in the buffer after the fork that has not been flushed yet, and each child runsprintf("\n");
and thus flushes out the buffer content.The solution is to either add a "\n" to the end of the very first printf, or call
fflush(stdout);
before thefor
loop.尽管我对这些东西有点生疏,但还是有一些可以尝试的东西。在打印横幅的行中:
可能
\n
之后的所有内容都留在输出缓冲区中,因此当每个子项被分叉时它仍然存在。尝试在printf
的末尾添加另一个\n
,并从printf
的开头删除\n
> 在循环内。Here's something to try, although I'm a little rusty with this stuff. In the line where you print out your banners:
It may be that everything after the
\n
is being left in the ouput buffer, so it's still there when each child is forked. Try adding another\n
at the end of thatprintf
, and removing the\n
from the beginning of theprintf
inside the loop.替换
: 替换
: 替换
:
删除:
Replace:
With:
Replace:
With:
Remove:
在这里阅读 2.5.1:
http://pubs.opengroup.org/onlinepubs/9699919799 /functions/V2_chap02.html
这意味着,在调用 fork 之前 您应该在
fork
之后对打算在两个进程中使用的任何流调用fflush
。Read 2.5.1 here:
http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html
What this means is that, before calling
fork
you should callfflush
on any streams that you intend to use in both processes after thefork
.