fork()的功能

时间:2010-12-16 10:25:46

标签: c linux process fork

系统信息:我在2个月大的笔记本电脑上运行64位Ubuntu 10.10。

大家好,我对C中的fork()函数有疑问。从我正在使用的资源(Stevens / Rago,YoLinux和Opengroup)中,我理解当你分叉一个进程时,父和子都从下一个命令继续执行。由于fork()0返回给子项,并且子项的进程ID返回给父项,因此您可以使用两个if语句来分散它们的行为,一个if(pid == 0)用于子项{{1}假设你用if(pid > 0)分叉。

现在,我发生了最奇怪的事情。在我的main函数的开头,我打印到pid = fork()几个已分配给变量的命令行参数。这是整个程序中的第一个非赋值语句,但是,似乎每次我在程序中稍后调用stdout时,都会执行这些打印语句。

我的程序的目标是创建一个“进程树”,每个进程有两个子进程,深度为3,从而创建初始可执行文件的15个子进程。每个进程在fork之前和之后打印它的父进程ID及其进程ID。

我的代码如下并且已正确注释,命令行参数应为fork(我还没有实现"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"看似正确格式,但也是因为我认为我的计划应该做的很多。

非常感谢任何帮助。

3 个答案:

答案 0 :(得分:6)

我不确定为什么会为孩子执行fputsstdout,并且没有可用于验证/测试的Unix框。

然而,以下跳出来了:

int depth = *argv[2];//depth of the process tree
int arity = *argv[3];//number of children each process should have

您正在将argv[2]argv[3]中的第一个字符的ASCII代码作为deptharity,因此您的代码正在尝试生成{{1} }进程而不是50^51

你想要的是:

2^3

解决此问题后,int depth = atoi(argv[2]);//depth of the process tree int arity = atoi(argv[3]);//number of children each process should have 及其双胞胎也需要更正。

编辑虽然现在这不是问题,但是你将bleh[0] = depth sprintf obuf中某些内容的长度缩短到了很近的水平。 。让部分消息更长一点Kaboom!至少您要将snprintf或更好的fprintf直接用于文件。

编辑我刚刚意识到作为操作系统功能的fork很可能不知道C I / O功能完成的内部缓冲。这可以解释为什么你得到重复(父和子都得到fork上的缓冲数据的副本)。在循环之前尝试fflush(stdout)。在每fflush(ofile)之前fork

答案 1 :(得分:3)

您的代码中有2个错误:

1)

  int depth = *argv[2];//depth of the process tree
  int arity = *argv[3];//number of children each process should have

使用此代码,您将获得字符串argv [2]和argv [3]的第一个字符。 正确的代码必须是这样的:

int depth = atoi(argv[2]);
int arity = atoi(argv[3]);

2)

bleh[0] = depth;
fputs(bleh, stdout);
bleh[0] = arity;
fputs(bleh, stdout);

你可以做类似bleh[0] = (char) depth;的事情,但是你只保留你的整数的第一个字节而不是你想做的,我想,如果你想要打印整个整数,只需使用:< / p>

printf("%d\n%d", depth, arity);

我只是尝试使用这些修改代码,它似乎运行良好:)

Anhuin

答案 2 :(得分:0)

您无法在功能开始时使用该代码打印数字。它可能通过将非字符串传递给fputs()来调用未定义的行为。您应该使用sprintf()(或更好,snprintf())将数字格式化为正确的字符串,当然要确保缓冲区足够大以容纳整数的字符串表示。

此外,您似乎正在向文件发送文本,但它以二进制模式打开,这似乎是错误的。