C 使用fork()生成随机数

C 使用fork()生成随机数,c,random,process,fork,sleep,C,Random,Process,Fork,Sleep,我的程序应该有n个子进程,这些子进程每秒生成一个介于1和9之间的随机数,我的问题是我应该验证这个子进程是否在同一时间生成相同的数 例如,如果我有5个孩子,他们可以生成 5 4 8 2 1 但它们不能产生 55431 有人能给我建议吗 int main (int argc,char** argv) { int i,pid,x,l; l=atoi(argv[1]); for(i=0;i<l;i++) { pid=fork();

我的程序应该有n个子进程,这些子进程每秒生成一个介于1和9之间的随机数,我的问题是我应该验证这个子进程是否在同一时间生成相同的数

例如,如果我有5个孩子,他们可以生成 5 4 8 2 1 但它们不能产生 55431

有人能给我建议吗

int main (int argc,char** argv)
{
    int i,pid,x,l;

    l=atoi(argv[1]);

    for(i=0;i<l;i++)
    {
        pid=fork();
        switch(pid)
        {
        case -1:
            printf("error\n");
        case 0: {
            srand(time(NULL));
            x=rand()%9+1;
            printf("Im child%d\n",x);sleep(1);
        }
        default:
            printf("Im parent %d\n",getpid());
        }
    }
}

您的子进程需要将它们选择的随机数传递给父进程。您可以使用管道在父进程和每个子进程之间建立双向通信

我坚持双向,因为如果孩子画错了号码,家长必须再次询问

这里是我不久前编写的一些样板代码,用于在父进程和子进程之间建立这样的双向通信。发生的情况是,父对象写入一个恰好是子对象“stdin”的文件,而子对象写入其stdout,该stdout也由父对象读取。技术上是C++,但易于适应C.P/P> 我不明白在子进程中生成随机数的可能用例是什么。也许您应该使用线程而不是进程

#include "process.h"
#include <assert.h>
#include <unistd.h>
#include <signal.h>
#include <cstring>
#include <iostream>

void Process::run(const char *cmd) throw (Err)
/*
 * Spawn a child process, and executes cmd. On success:
 * - pid is the process id
 * - in, out are FILE* to read/write from/to the process' stdout/stdin
 * */
{
    pid = 0;
    int readpipe[2], writepipe[2];
#define PARENT_READ     readpipe[0]
#define CHILD_WRITE     readpipe[1]
#define CHILD_READ      writepipe[0]
#define PARENT_WRITE    writepipe[1]

    try {
        if (pipe(readpipe) < 0 || pipe(writepipe) < 0)
            throw Err();

        pid = fork();

        if (pid == 0) {
            // in the child process
            close(PARENT_WRITE);
            close(PARENT_READ);

            if (dup2(CHILD_READ, STDIN_FILENO) == -1)
                throw Err();
            close(CHILD_READ);

            if (dup2(CHILD_WRITE, STDOUT_FILENO) == -1)
                throw Err();
            close(CHILD_WRITE);

            if (execlp(cmd, cmd, NULL) == -1)
                throw Err();
        } else if (pid > 0) {
            // in the parent process
            close(CHILD_READ);
            close(CHILD_WRITE);

            if ( !(in = fdopen(PARENT_READ, "r"))
                    || !(out = fdopen(PARENT_WRITE, "w")) )
                throw IOErr();
        } else
            // fork failed
            throw Err();
    } catch (Err &e) {
        cleanup();
        throw;
    }
}

void Process::cleanup()
{
    // close file descriptors
    if (in) fclose(in);
    if (out) fclose(out);

    // kill child process
    if (pid > 0) kill(pid, SIGKILL);
}

Process::~Process()
{
    cleanup();
}

void Process::write_line(const char *s) const throw(IOErr)
{
    fputs(s, out);
    fflush(out);    // don't forget to flush! (that's what she says)

    if (ferror(out))
        throw IOErr();
}

void Process::read_line(char *s, int n) const throw(IOErr)
{
    if (!fgets(s, n, in))
        throw IOErr();
}

这是一个很酷的问题,因为它同时说明了随机数生成实际上不是随机的,以及单独线程的使用和限制

我只想记下几件事

1由于2个原因,您不能要求每个子进程拾取的随机数必须与其他进程协调。1他们将不再选择随机数字,他们将选择另一个进程尚未选择的数字;那是随机的?2如果所有子进程都必须与父进程协调,那么整个进程将比只有一个进程慢——换句话说,这是无用的,但这可能是练习的重点。也就是说,允许整体算法不是快速高效的,而是通过包含进程调度因子来增加随机性。如果没有,那么继续阅读

2每个流程是否可以全速运行,或者每个流程是否必须等待当前迭代完成所有其他流程?或者父进程可以简单地记录每个子进程在时隙n的拾取吗

3子进程不能超过9个,因为可以保证至少有2个进程选择相同的数字

那么,每个孩子是否可以使用相同的种子为伪随机数生成器设定种子,然后将其编号添加到mod 9中?它是随机的,因为它是一个伪随机数加上一个常数。唯一的缺点是它不是随机的,其他的孩子,但假设你不喜欢,然后我们回到观察1,它比较慢,仍然不是随机的,其他的孩子,因为它是协调的。它同样是随机的,因为rnd实际上是确定性的,它只是看起来是随机的

更新一些伪代码:

In the parent process
   select a seed number S

   for index = 0 .. numChildren - 1 do
      fork child
      childNum = index
      communicate(S,childNum) to child

   while true
      receive(childRND,childNum,childIteration) from child
      iterationResults[childIteration,childNum] = childRND
      iterationResults[childIteration].numResults++
      if(iterationResults[childIteration].numResults == numChildren) then
         print iterationResults[childIteration]
         delete iterationResults[childIteration]
子伪代码:

In each child process
   Seed the random number generator with S
   for iteration = 1 ... do
      X = RND(1,9)
      Y = RND(1,10000)
      Pick the Yth number N that is relatively prime to 9 (or just pick the Yth prime)
      childRND = (X + (Y*childNum mod 9)) mod 9 + 1
      send(childRND,childNum,iteration) to parent
注:

由于所有子项都使用相同的种子S为RNG播种,因此每个子项的X和Y始终是相同的数字

因为Y相对于9是素数,所以N=0..8的N*Y mod 9将创建数字0..8的排列。由于我们选择了一个随机Y,排列也将是随机的,因此X+Y*childNum mod 9 mod 9+1将在每次新的迭代中进行置乱,但是每个子项都保证返回一个不同于其他子项的数字


是的,这仍然是确定的,但报告的结果会显得更加随机。

因此您需要生成随机数,但您需要对其进行协调以避免重复,但您是在单独的过程中生成随机数的,这些过程似乎是专为防止您需要的那种协调而设计的?你想解决的实际问题是什么?如果每隔一秒钟就解决一次,那么1..9中的数字将很快被计算出来。如果一个孩子有@JohnZwinck,他们似乎不产生相同的数字,因为rand取决于时间,但是当我运行程序时,它们总是产生相同的编号,而不是以任何方式依赖时间。因为我使用SalDimeTimeTM。不知怎么说,我认为C++代码不会帮助OP更接近于解决他/她的问题的真实本质。我是C++的新手,但我会尝试采纳一个想法。