在Linux中使用fork()创建多个子代

时间:2012-03-14 04:02:57

标签: c++ c linux operating-system fork

我想使用fork()创建多个孩子,但我遇到了问题。 LIKE:

///////////////////////// these are some class objects creation and calling
//  There are some functions calling from another class. about 5 functions I invoked.
// and some variables like.

    pid_t PID;
    int status = 0;
    char *x = new char[10];

///////////////////////// This for loop give me multiple children
// now one parent have multiple children in this case 10


    for( int i=0; i<10; i++ )
    {
        mNo++;
        rNo++;
        PID = fork();

        if( PID == FORK_ERROR )         // fork ERROR!
        {
            fprintf(stderr, "ERROR! In fork() [FORCE EXITING]... %d\n", errno);
            exit(EXIT_FAILURE);
        }
        else if( PID == CHILD )         // Do Child Stuff Here...
        {
            exit(status);
        }
        else            // Do parent Stuff Here...
        {

        }
    }
    PID = wait(&status);

////////////////////////////////////////////

这是我实施的代码,但存在一些问题。

我想问一下,当我在内存中创建一个子节点时,它会创建重复的内存。我宣布的对象也是;他们是通过调用fork()重新调用的,那么这是否意味着每个孩子都有内存中的对象在课堂上被重新调用?

我希望如果我fork,并且之前的函数调用和变量对于每个子节点应该是相同的但不是非幂等函数。我希望你明白。我知道这是一个非常简单的问题,但我正在研究的项目非常关键,它必须用fork()实现,而不是在管道或线程中实现。

此外,我在重复我的问题,如果我fork(),对象和变量会发生什么。在调用fork之前,它们是刚刚重新分配还是为每个孩子重新调用它们?但我所看到的是,他们为每个孩子重新培养,这是我不想要的。那我该怎么办?

4 个答案:

答案 0 :(得分:2)

当你fork时,你的孩子是父进程的副本,包括堆。因此,您有一个单独的对象副本或使用new分配的内存。我不确定你的意思是重新调用,但是如果你在父代中使用new()分配了一个对象,那么你将在2个独立的进程中在2个独立的堆上有2个独立的对象。 一个是父进程中的原始进程,另一个是子进程中复制堆上的副本。

这有助于更好地理解:Linux fork within class on heap

答案 1 :(得分:2)

fork()的行为不会改变以符合您的意愿。

当进程分叉时,同一程序有两个几乎相同的副本。差异列在POSIX手册页(上面的链接)中。记忆是一样的。例如,C ++中的对象不会被重构。例如,在每个过程中,所有单身人士仍然是单身人士。

  

你能举个例子吗?

这是我在1991年写过的完整主程序。我只更新了它以使用main()的原型,并且我已经包含了Pipe的typedef和{的定义{1}}:

id

static char id[] = "\n\n\nSQLMONITOR version 3.5 \n"; typedef int Pipe[2]; int main(int argc, char **argv) { int pid; Pipe to_sqlexec; Pipe from_sqlexec; setarg0(argv[0]); write(STDERR, id, sizeof(id)-1); if (pipe(to_sqlexec) < 0 || pipe(from_sqlexec) < 0) error("unable to create pipes"); else if ((pid = fork()) < 0) error("unable to fork"); else if (pid == 0) be_childish(argv, to_sqlexec, from_sqlexec); else be_parental(to_sqlexec, from_sqlexec); return(0); } 函数继续执行一些管道工作(在执行另一个程序之前复制和关闭管道的适当部分。be_childish()进程继续从其标准输入读取消息,记录它们到一个文件,并将消息写入其be_parental()管道写入端的子项的标准输入;然后它将读取{{1}的读取端上的子项的响应管道,并记录该消息,然后将其写入其标准输出。因此,它将位于两个进程的中间,记录从一个到另一个的所有内容。进程之间的通信协议是同步的,大大简化了生活。另一方面,当一个过程的数据完成时,很难解决。代码早于to_sqlexecfrom_sqlexec的广泛可用性;现在,它不需要对消息进行尽可能多的分析。

但值得注意的是,select()之后的两个流程中的两个管道是相同的;实际上,唯一不同的变量是poll(),它从fork()中捕获返回值。其他一切与pid之前完全一样。

答案 2 :(得分:1)

好像你不知道fork()的作用。这让你觉得它是正确的功能似乎很奇怪。

了解它:

http://linux.die.net/man/2/fork

http://en.wikipedia.org/wiki/Fork_(operating_system)

乍一看,子进程似乎得到了父进程内存的副本。

答案 3 :(得分:1)

如果你fork,我认为,所有的对象和变量都与父进程完全相同。我不明白“但我看到他们为每个孩子重新燃起了什么”这里重新引用了什么?