系统信息:我在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"
看似正确格式,但也是因为我认为我的计划应该做的很多。
非常感谢任何帮助。
答案 0 :(得分:6)
我不确定为什么会为孩子执行fputs
到stdout
,并且没有可用于验证/测试的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代码作为depth
和arity
,因此您的代码正在尝试生成{{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()
)将数字格式化为正确的字符串,当然要确保缓冲区足够大以容纳整数的字符串表示。
此外,您似乎正在向文件发送文本,但它以二进制模式打开,这似乎是错误的。