系统信息:我在2个月大的笔记本电脑上运行64位Ubuntu 10.10。
大家好,我对C中的fork()函数有疑问。从我正在使用的资源(Stevens / Rago,YoLinux和Opengroup)中,我理解当你分叉一个进程时,两者都是父和子从下一个命令继续执行。由于fork()将0返回给子节点,并将子节点的进程id返回给父节点,因此可以使用两个if语句来分散它们的行为,一个if(pid = 0)表示子节点和if(pid> 0),假设你用pid = fork()分叉。
现在,我发生了最奇怪的事情。在我的main函数的开头,我打印到stdout已经分配给变量的几个命令行参数。这是整个程序中的第一个非赋值语句,但有时当我稍后在程序中调用fork时,会执行此print语句。
我的程序的目标是创建一个“进程树”,每个进程有两个子进程,深度为3,从而创建初始可执行文件的14个子进程。每个进程在fork之前和之后打印其父进程ID及其进程ID。
我的代码如下并且被正确评论,命令行参数应该是“ofile 3 2 -p”(我还没有实现-p / -c标志“:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[])
{
if(argc != 5)//checks for correct amount of arguments
{
return 0;
}
FILE * ofile;//file to write to
pid_t pid = 1;//holds child process id
int depth = atoi(argv[2]);//depth of the process tree
int arity = atoi(argv[3]);//number of children each process should have
printf("%d%d", depth, arity);
ofile = fopen(argv[1], "w+");//opens specified file for writing
int a = 0;//counter for arity
int d = 0;//counter for depth
while(a < arity && d < depth)//makes sure depth and arity are within limits, if the children reach too high(low?) of a depth, loop fails to execute
//and if the process has forked arity times, then the loop fails to execute
{
fprintf(ofile, "before fork: parent's pid: %d, current pid: %d\n", getppid(), getpid());//prints parent and self id to buffer
pid = fork(); //forks program
if(pid == 0)//executes for child
{
fprintf(ofile, "after fork (child):parent's pid: %d, current pid: %d\n", getppid(), getpid());//prints parent's id and self id to buffer
a=-1;//resets arity to 0 (after current iteration of loop is finished), so new process makes correct number of children
d++;//increases depth counter for child and all of its children
}
if(pid > 0)//executes for parent process
{
waitpid(pid, NULL, 0);//waits on child to execute to print status
fprintf(ofile, "after fork (parent):parent's pid: %d, current pid: %d\n", getppid(), getpid());//prints parent's id and self id to buffer
}
a++;//increments arity counter
}
fclose(ofile);
}
当我运行“gcc main.c -o ptree”然后“ptree ofile 3 2 -p”时,控制台会被“32”垃圾邮件发送几次,文件“ofile”的格式看似合适,但是对于我认为我的程序应该做的事情有点太大了,显示了34个子进程,当应该有2 ^ 3 + 2 ^ 2 + 2 ^ 1 = 14时。我认为这与打印“32”的语句有某种关系,因为这似乎可能产生比预期更多的分叉。
非常感谢任何帮助。
答案 0 :(得分:6)
当您调用printf时,数据会在内部存储在缓冲区中。 fork时,该缓冲区由子进程继承。在某些时候,(当您再次调用printf或关闭文件时),刷新缓冲区并将数据写入基础文件描述符。为了防止缓冲区中的数据被子进程继承,您可以在调用fork之前通过fflush刷新FILE *。