Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 分叉和过程管理_C_Linux_Process_Fork - Fatal编程技术网

C 分叉和过程管理

C 分叉和过程管理,c,linux,process,fork,C,Linux,Process,Fork,系统信息:我在一台2个月大的笔记本电脑上运行64位Ubuntu 10.10 大家好,我有一个关于C中fork函数的问题。根据我使用Stevens/Rago、YoLinux和Opengroup的参考资料,我的理解是,当您fork一个进程时,父进程和子进程都会从下一个命令继续执行。由于fork将0返回给子级,将子级的进程id返回给父级,因此可以使用两个if语句来区分它们的行为,一个ifpid=0用于子级,另一个ifpid>0,假设您使用pid=fork进行fork 现在,我发生了最奇怪的事情。在我的

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

大家好,我有一个关于C中fork函数的问题。根据我使用Stevens/Rago、YoLinux和Opengroup的参考资料,我的理解是,当您fork一个进程时,父进程和子进程都会从下一个命令继续执行。由于fork将0返回给子级,将子级的进程id返回给父级,因此可以使用两个if语句来区分它们的行为,一个ifpid=0用于子级,另一个ifpid>0,假设您使用pid=fork进行fork

现在,我发生了最奇怪的事情。在我的主函数开始时,我正在向stdout打印一些已分配给变量的命令行参数。这是整个程序中的第一个非赋值语句,然而,有时当我在程序中稍后调用fork时,似乎会执行这个print语句

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

我的代码如下所示,并进行了适当的注释,命令行参数应该是文件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,然后运行文件3 2-p的ptree时,控制台被垃圾发送了32次,文件的格式看起来很正确,但对于我认为我的程序应该执行的操作来说有点太大了,显示了34个子进程,这时应该有2^3+2^2+2^1=14。我认为这与正在打印32的语句有关,因为这似乎可能会产生比预期更多的分叉


非常感谢您的帮助。

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

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

如果这不是一个骗局,那就需要弄清楚为什么不是。好吧,答案集中在我犯的一些错误上,这些错误显然与我的中心问题无关,为什么这32个的打印语句在我的分叉和循环之前被多次执行。所有的答案都集中在我的错误上,关于不使用atoi和复杂的文件输出,这两个问题都没有答案。我决定重新发布那里的人建议我做的更改,希望不会再次分散任何潜在的回答者对我的中心问题的注意力//递增算术计数器,pid=fork//福克斯计划!我是C graham的新手,我喜欢确保几乎所有的东西都有注释,这样当我阅读自己的代码时,我就可以准确地知道语句是什么和引用什么,即使不必看实际的代码。我相信你们的行业标准和诸如此类的标准在保持专业程序员的代码整洁方面是非常有用的,但让我们学生放松一下吧?如果这不是一个骗局,那就需要弄清楚为什么不是。好吧,答案集中在我犯的一些错误上,这些错误显然与我的中心问题无关,为什么这32个的print语句被多次执行,而它们在我的fork和循环之前。所有的答案都集中在我的错误上,关于不使用atoi和复杂的文件输出,这两个问题都没有答案。我决定重新发布那里的人建议我做的更改,希望不会再次分散任何潜在的回答者对我的中心问题的注意力//递增算术计数器,pid=fork//福克斯计划!我是C graham的新手,我喜欢确保几乎所有的东西都有注释,这样当我阅读自己的代码时,我就可以准确地知道语句是什么和引用什么,即使不必看实际的代码。我相信你们的行业标准和诸如此类的东西在保持专业程序员的代码整洁方面非常有用,但让我们学生放松一下吧?哇,非常感谢。我甚至在我的短信中找不到关于这种情况的参考
k、 虽然它很可能在那里,我的老师也从来没有提到过这样的事情。我相信我自己永远也不会明白这一点。干杯同样值得注意的是,当你使用fork时,缓冲区是自动复制的,这就是为什么你会得到重复的输出。是的,我想这就是William暗示的缓冲区是由孩子继承的。感谢您通过Douglas提供的输入。另外值得注意的是,默认情况下,标准输出是行缓冲的,这意味着如果您总是用a\n完成printf格式,您将不会看到问题。因为这很常见,这可能是教科书/老师没有提到这个问题的原因。说标准输出默认是行缓冲的说法不太正确。如果stdout与tty相关联,那么默认情况下它是行缓冲的。但是在大多数情况下,stdout与管道相关联,在这种情况下,默认情况下它是块缓冲的。当与常规文件关联时,默认情况下它也是块缓冲的。哇,非常感谢。我甚至在我的教科书中找不到关于这种情况的参考,尽管它很可能在那里,我的老师也从来没有提到过这样的事情。我相信我自己永远也不会明白这一点。干杯同样值得注意的是,当你使用fork时,缓冲区是自动复制的,这就是为什么你会得到重复的输出。是的,我想这就是William暗示的缓冲区是由孩子继承的。感谢您通过Douglas提供的输入。另外值得注意的是,默认情况下,标准输出是行缓冲的,这意味着如果您总是用a\n完成printf格式,您将不会看到问题。因为这很常见,这可能是教科书/老师没有提到这个问题的原因。说标准输出默认是行缓冲的说法不太正确。如果stdout与tty相关联,那么默认情况下它是行缓冲的。但是在大多数情况下,stdout与管道相关联,在这种情况下,默认情况下它是块缓冲的。当与常规文件关联时,默认情况下它也是块缓冲的。