首先,我知道有很多关于rand()函数的问题,但我认为这是不同的。
实际上,当我没有与sleep()函数结合使用时,rand()函数总能正常工作。我尝试过这个。但是,当我将rand()函数与sleep()结合使用时,就像这样“睡眠(rand()%5)”,有时它会产生所有子进程的随机时间,正如我预期的那样,但有时适用于前4-5个孩子,之后,它为所有剩余子进程生成0。所以其他子进程不会睡觉。有时候,所有子流程的产品总是为0。
BTW,我在Ubuntu 64bit上编码。
关于我的代码: 我想从父进程中分叉8个子进程并逐个打印他们的pid号。但我应该在创建一个孩子后使用睡眠功能。睡觉时间应该是随机的。我使用time()函数作为种子并尝试使用rand函数,但它对睡眠函数不起作用。
这是我的代码:
#include <stdio.h>
#include <sys/sem.h>
#include <unistd.h>
#include <wait.h>
#include <stdlib.h>
#include <time.h>
void childs();
void parent();
int id;
int i;
int pidID[9];
int fd[2];
char buff[100];
int main(int argc, char *argv[]){
pid_t child;
for(i = 0; i < 8; i++){
pipe(fd);
child = fork();
wait(NULL);
if(child){
parent();
continue;
}else if(child == 0){
childs();
break;
}else{
perror("State\n");
exit(1);
}
}
if(child ==0){
printf("I am a child pid: %d, ppid: %d pidno: %d\n", getpid(), getppid(),pidID[i+1]);
}else{
printf("I am a parent pid: %d, ppid: %d pidno: %d\n", getpid(), getppid(),pidID[0]);
}
}
void childs(){
id = getpid();
pidID[i + 1] = id;
char swap[50];
sprintf(swap, "%d" ,id);
write(fd[1], swap, 10);
srand(time(NULL));
int randomTime = rand() %5;
printf("Random time: %d\n",randomTime);
sleep(randomTime);
}
void parent(){
pidID[0] = getpid();
read(fd[0], buff , 10);
printf("Buff: %s\n", buff);
}
答案 0 :(得分:2)
当您在每个子进程中time(NULL)
sleep
时,在同一秒内启动的所有子进程将以相同的值播种。
当然,如果涉及wait
和sleep
,如果孩子们rand() % 5
一秒钟,那么他们会以新的价值播种,所以事情大部分都会解决如果你总是在睡觉。
但是time
产生0到4之间的值;第一次给定rand()
种子会导致第一个time
输出为五的倍数,你睡眠0秒,孩子几乎立即退出,并且循环分叉一个新的孩子,全部在最多只有几毫秒的空间。并且它将继续执行此操作一秒(或更多),直到rand
重新设置将int randomTime = rand() %5;
的第一个输出更改为不是五的倍数的值。
如果你想解决这个问题,最简单的(如果仍然是愚蠢的)方法就是改变:
int randomTime = rand() %5 + 1; // Range 1-5, or use rand() % 4 + 1 for 1-4
为:
time
所以你永远不会有不到一秒钟的睡眠时间,并且你永远不会进入不断重新播种的病理情况,同时反复产生相同的零秒睡眠。
或者,如果必须有零秒睡眠,则使用更细粒度的struct timespec tm;
clock_gettime(CLOCK_MONOTONIC, &tm);
// xor-ing with tv_nsec >> 31 to ensure even low precision clocks vary
// the low 32 bits
srand((unsigned)(tm.tv_sec ^ tm.tv_nsec ^ (tm.tv_nsec >> 31)));
函数来获得更快速变化的种子。例如,在POSIX系统上,您可以改为使用clock_gettime
,它应该变化得更快:
rand() % 5
并且您可以继续使用srand
,因为tv_nsec
之间的时间应足够长,以便更改{{1}}中的一些值并获得不同的种子值。