fork() 创建的进程不并行执行
fork() created process don't execute in parallel
我在共享内存中得到了一个包含 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开始。
当您不使用 srandom
函数为随机数生成器播种时,您将始终获得相同的 "random" 数字序列。通常你播种它做 srandom(time(NULL))
调用。
检查这个简单的程序:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
printf("%d\n", rand());
return 0;
}
在我的电脑上它总是输出1804289383
。
此外,当您在 child 进程中调用 rand
时,它 总是 继承 parent 的 random-number-generating-machine 状态,因此您的 children 将 always 生成 相同的 随机数。你应该在分叉之前生成这个随机数。在下面的代码中所有 children return 相同的随机值:
#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;
}
最后一点是,创建一些进程 one-after-another 并不意味着它们将按顺序获得处理器的时间。完全可以,当你 fork
你的第一个 child 时,处理器的上下文将 return 到 parent,谁将执行另一个 fork
,然后处理器的上下文将分配给第二个 child,而不是第一个。
有效代码:
#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;
}
你的代码是错误的,不要按照你的想法去做。
在fork()
成功的情况下,调用者自增i
,然后while最后的测试为false,所以原流程终止。当新进程执行它的代码 "start 0"、"terminates 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
我在共享内存中得到了一个包含 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开始。
当您不使用 srandom
函数为随机数生成器播种时,您将始终获得相同的 "random" 数字序列。通常你播种它做 srandom(time(NULL))
调用。
检查这个简单的程序:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
printf("%d\n", rand());
return 0;
}
在我的电脑上它总是输出1804289383
。
此外,当您在 child 进程中调用 rand
时,它 总是 继承 parent 的 random-number-generating-machine 状态,因此您的 children 将 always 生成 相同的 随机数。你应该在分叉之前生成这个随机数。在下面的代码中所有 children return 相同的随机值:
#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;
}
最后一点是,创建一些进程 one-after-another 并不意味着它们将按顺序获得处理器的时间。完全可以,当你 fork
你的第一个 child 时,处理器的上下文将 return 到 parent,谁将执行另一个 fork
,然后处理器的上下文将分配给第二个 child,而不是第一个。
有效代码:
#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;
}
你的代码是错误的,不要按照你的想法去做。
在fork()
成功的情况下,调用者自增i
,然后while最后的测试为false,所以原流程终止。当新进程执行它的代码 "start 0"、"terminates 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