分岔和流程管理

时间:2010-12-16 12:09:00

标签: c linux process fork

系统信息:我在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”的语句有某种关系,因为这似乎可能产生比预期更多的分叉。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:6)

当您调用printf时,数据会在内部存储在缓冲区中。 fork时,该缓冲区由子进程继承。在某些时候,(当您再次调用printf或关闭文件时),刷新缓冲区并将数据写入基础文件描述符。为了防止缓冲区中的数据被子进程继承,您可以在调用fork之前通过fflush刷新FILE *。