我的程序应该有n个孩子“进程”,那些孩子每秒生成1到9之间的随机数,我的问题是我应该验证孩子不会在同一时间生成相同的数字
例如,如果我有5个孩子,他们可以生成 5 4 8 2 1 但他们无法生成 “5 5”4 3 1
任何人都可以给我建议吗?
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());
}
}
}
答案 0 :(得分:0)
您的子进程需要将他们选择的随机数传递给父进程。您可以做的是使用管道在您的父进程和每个子进程之间建立(双向)通信。
我坚持双向,因为如果孩子输错了号码,家长必须再次询问。
这是我前一段时间写的一些boilder-plate代码,用于在父进程和子进程之间建立这种双向通信。发生的事情是父进程写入恰好是子进程的'stdin'的文件,并且子进程写入也由父进程读取的stdout。技术它是用C ++编写的,但很容易适应C。
我不明白在子进程中生成随机数的可能用例。也许您应该使用线程而不是进程?
#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 :(得分:0)
这是一个很酷的问题,因为它同时说明了随机数生成实际上不是随机的以及单独线程的使用和限制这一事实。
我只会注意一些事情。
1)您不能要求每个子进程选择的随机数必须与其他进程协调,原因有两个。 1)他们不会再选择随机数,他们会选择另一个进程尚未选择的数字;这是随机的吗? 2)如果所有子进程都必须与父进程协调,那么整个进程将比只有一个进程慢 - 换句话说没用,但也许这就是练习的重点。也就是说,允许整体算法不快速和有效,但通过包括“进程调度”因子来增加随机性。如果没有,那就继续阅读。
2)每个进程可以全速运行,还是每个进程必须等到所有其他进程完成当前迭代?或者,父进程是否可以在时隙n?
记录每个孩子的选择3)不能有超过9个子进程,因为您可以保证至少2会选择相同的数字。
那么,每个孩子可以使用相同的种子播种“伪随机数生成器”,然后将它们的数字添加到mod 9吗?它是随机的,因为它是一个伪随机数加一个常数。唯一的缺点是它不是随机的w.r.t.其他的孩子,但是让我们说你不喜欢那样,然后我们回到观察#1,它慢了,它仍然不是随机的w.r.t.其他孩子,因为它是协调的。然而,它并不是随机的,因为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 * Y mod 9,其中N = 0..8将产生数字0..8的排列。由于我们选择“随机”Y,所以排列也将是“随机的”,因此(X +(Y * childNum mod 9))mod 9 + 1将对每次新迭代进行加扰,但是每个子项都保证返回不同的数字比其他孩子。
是的,这仍然是确定性的,但报告的结果会显得更加随机。