我在共享内存中有一个整数矩阵,有n个列,所以我创建了n个进程,每个进程都是一个列的总和。问题是它们不是并行执行的。有代码(这实际上不是总和,是测试):
int pid2[n];
i=0;
do{
pid2[i] = fork();
if(pid2[i]==-1) printf("fork() fail!\n");
else if(pid2[i]==0){
printf("Start process %d \n", i);
sleep((rand() % 50)/10);
printf("Process %d terminated" ,i);
}
else i++;
}
while(i<n&&pid2[i]>0);
我得到的是它在此顺序过程中运行3,2,1并始终以相同的顺序结束。但是睡眠是随机的,所以到达时间也应该是随机的!另外,我不明白为什么它从过程3开始。
答案 0 :(得分:2)
你的代码错了,不按照你的想法行事。
在fork()
成功的情况下,调用者递增i
,然后对while的最终测试为false,因此原始进程终止。当新进程执行其代码“start 0”,“终止0”,然后跳转到测试,该测试为真,然后再次fork,等等。所以你的进程总是以相同的顺序一个接一个地生成。
以下是更正的代码(随机播种):
int pid2[n];
i=0;
do{
pid2[i] = fork();
if(pid2[i]==-1) printf("fork() fail!\n");
else if(pid2[i]==0){
printf("Start process %d \n", i);
sleep((rand() % 50)/10);
printf("Process %d terminated" ,i);
exit(0); // ends the child
}
else i++;
}
while(i<n&&pid2[i-1]>0); // test is last pid is correct
答案 1 :(得分:1)
如果您没有使用srandom
函数播种随机数生成器,您将始终获得相同的序列&#34;随机&#34;数字。通常你会通过srandom(time(NULL))
电话来播种它。
检查这个简单的程序:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
printf("%d\n", rand());
return 0;
}
在我的计算机上,始终输出1804289383
。
此外,当您在子流程中致电rand
时,始终会继承父级的随机数生成机器状态,因此您的孩子将始终生成相同的随机数。你应该在分叉之前生成这个随机数。在以下代码中,所有子项都返回相同的随机值:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#define CHILDREN 3
int main(void) {
int i;
for (i = 0; i < CHILDREN; ++i) {
if (fork() == 0) {
printf("rand is %d in child %d\n", rand(), i);
return 0;
}
wait(NULL);
}
return 0;
}
最后一点是,一个接一个地创建一些流程并不代表他们会按顺序获得处理器的时间。当您fork
第一个孩子时,处理程序的上下文将返回给父母,他们将执行另一个fork
,然后处理者的上下文将完全正常分配给第二个孩子,而不是第一个孩子。
有效的代码:
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#define CHILDREN 3
int main(void) {
int pid, i, children = 0;
srand(time(NULL));
double sleeptime;
for (i = 0; i < CHILDREN; ++i) {
sleeptime = (rand() % 50) / 10.0;
pid = fork();
if (pid == -1) {
perror("fork failed");
} else if (pid == 0) {
printf("Child %d crated\n", i);
fflush(stdout);
sleep(sleeptime);
printf("Child %d terminated\n", i);
fflush(stdout);
return 0;
} else {
++children;
}
}
// wait for all childredn
for (i = 0; i < children; ++i) {
wait(NULL);
}
return 0;
}