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

Multiple child creation with fork() in Linux

本文关键字:创建 Linux fork      更新时间:2023-10-16

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

///////////////////////// 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]... %dn", 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()的行为不会根据您的意愿而改变。

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

你能给我举个例子吗?

这是我在1991年写的完整的主程序。我只更新了它,使其使用main()的原型,并包含了Pipe的typedef和id:的定义

static char id[] = "nnnSQLMONITOR 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()进程继续从其标准输入读取消息,将其记录到文件中,并将消息写入to_sqlexec管道写入端的子级的标准输入;然后,它将从from_sqlexec管道读取端的子代读取回响应,并将该消息也记录到然后将其写入标准输出。因此,它将位于两个过程的中间,记录从一个过程到另一个过程的一切。进程之间的通信协议是同步的,这大大简化了生活。另一方面,计算一个过程的数据何时完成是相当困难的。该代码早于select()poll()的广泛可用性;如今,它将不需要对消息进行那么多分析。

不过,需要注意的关键是,在fork()之后的两个过程中,这两个管道是相同的;实际上,唯一不同的变量是pid,它捕获fork()的返回值。其他一切都和fork()之前一模一样。

当您分叉时,您的子进程是父进程的副本,包括堆。因此,您有一个单独的对象副本或使用new分配的内存。我不知道你所说的重新voked是什么意思,但如果你在父进程中使用new()分配了一个对象,那么你将在两个独立的进程中的两个独立堆上拥有两个独立对象。一个是父进程中的原始堆,另一个是子进程中复制堆上的副本。

这将有助于更好地理解:堆上类中的Linux分叉

似乎不知道fork()的作用。这让人觉得奇怪的是,你确信这是正确的功能。

阅读:

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

http://en.wikipedia.org/wiki/Fork_(操作系统)

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

我认为,如果分叉,所有对象和变量都将与父进程完全相同。我不理解"但我看到的是,他们为每个孩子重新宣誓",这里重新宣誓了什么?