如何使用fork()创建指定数量的子进程

4
我需要创建一定数量的并发子进程。我希望每个子进程都能修改一个全局变量,这样主父进程就可以打印它的最后修改版本。当我运行下面的程序时,“k”的最终值将为5,因此全局变量不会改变。如果我删除“exit(0)”部分,则全局变量会更改,但是这次创建的子进程数量会更多。
使用fork(),如何创建X个子进程,这些子进程可以修改主父进程中的数据(全局变量,局部变量等)?
int k = 5; // global variable   

int main(){

  int i=0;
  int status;

  for(i = 0; i<5; i++){
    if(fork() == 0){ 
        printf("child %d %d\n", i, ++k);
        sleep(5);
        printf("done %d\n",i);
        exit(0);
    }
  }

  return 0;
}

1
你自己回答了问题 - 使用for循环。 - Merlyn Morgan-Graham
是的,但k的值将会是5而不是10。这就是问题所在。 - user246392
创建子进程来修改全局变量,这不是'fork'的工作方式,我猜你更想创建线程。 - Kevin
1
那么你的问题不是“如何使用fork()创建一定数量的子进程”,而实际上是“如何允许子进程使用fork()修改父进程状态”。这听起来准确吗? - Merlyn Morgan-Graham
两个都可以!但我更关心后者。我真正需要做的是多次调用execvp()。如果我不能传递在主程序中全局定义的数组,那么我猜我需要在for循环头之后确定其内容,并在每个if块中将数组传递给execvp()。 - user246392
5个回答

2
以这种方式做是不可行的。Fork会创建一个新的进程,它将把内存页面复制(或者写时复制)到新进程中。这意味着每个子进程都会得到自己的“k”拷贝,并且每个“k”拷贝只会被增加一次。
要使所有进程将“相同”的k变量传回,请执行某种形式的进程间通信。
良好的进程间通信的示例:
1.父进程创建一个共享内存段,其中存储了k的值。子进程等待父进程创建的互斥锁来获取共享内存段的独占控制权。当子进程获得独占锁时,让子进程读取k的值并将k + 1的值存储在其中。
2.在父进程和子进程之间创建一个针对每个进程的管道。父进程从管道中读取消息,以指示需要增加k的值。然后,由父进程代表子进程递增k的值。
不良的进程间通信的示例:
任何不能确保K更改是原子性的解决方案(这意味着两个竞争的子进程可能同时将K递增到相同的值)。这样的缺乏关注会导致K的值似乎比子进程的数量少递增多次,因为设置的值可能看起来像(2, 3, 3, 4, 5)。这意味着文件I/O大部分是无用的,除非您在它周围创建一个框架,以确保在独占访问文件时进行原子操作。

2

1

子进程默认情况下不能更改父进程的地址空间。为此,您需要使用共享内存以及互斥机制来防止竞态条件。


1

进程按定义不能直接修改其他进程的资源(如全局变量等)。您需要使用线程而不是进程来实现此目的。请查看pthread_create(3)或clone(2)。


0
一个子进程会获得父进程地址空间的副本。换句话说,每个子进程都有自己的全局变量副本。
为了让所有子进程和父进程共享同一个变量,你需要将变量放入共享内存映射中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接