以下是我目前的一段代码:
pipe(pipes);
int count = 0, t = 0;
int forks[numForks];
for(j = 1; j<=numForks; j++){
if((pid=fork()) == 0){
count = findKey(in, key, buf, j, count);
close(pipes[0]);
write(pipes[1],&count, sizeof(count));
exit(0);
}else{
close(pipes[1]);
read(pipes[0], &t, sizeof(t));
}
}
count = t;
printf("count = %i\n", count);
我创造了n个孩子。在每个子节点中,他们扫描文本文件的不同部分并返回它找到关键字的次数。孩子都只阅读文本文件的某个部分。有时候孩子可能在它自己的部分找不到关键字所以它显然会返回0.在我正在使用的测试用例中,count的最终值应为1但最后的值为0因为我不认为我正在使用管道正确保存每个值。我知道其中一个孩子确实找到了关键字,因为如果我在if语句中的函数调用之后放了一个print语句,那么在某个时候,count是1。
基本上我想把所有的count值加起来。
答案 0 :(得分:2)
父进程
{
close(pipes[1]);
read(pipes[0], &t, sizeof(t));
}
numForks
次。因此,只有第一个孩子获得一个开放的写入描述符pipes[1]
,并且每个read
都会覆盖t
,只留下最后一个值。
答案 1 :(得分:1)
您的父进程会覆盖循环中前一个子进程的返回值。
试试这个:
pipe(pipes);
int count = 0, t = 0;
int forks[numForks];
for(j = 1; j<=numForks; j++){
if((pid=fork()) == 0){
count = findKey(in, key, buf, j, count);
close(pipes[0]);
write(pipes[1],&count, sizeof(count));
exit(0);
}else{
close(pipes[1]);
read(pipes[0], &t, sizeof(t));
count += t;
}
}
printf("count = %i\n", count);
答案 2 :(得分:1)
您需要在其他答案和我的评论中概述的两个修补程序:
此时,孩子们同步执行,一次只执行一个孩子,因为在循环运行下一个孩子之前等待孩子的响应。您应该在
count += t;
之后使用read()
。您还应该检查更多系统调用。此外,第二个和后续子节点无法写入父节点,因为父节点已关闭管道的写入端。您必须为每个子项创建(并关闭)管道,或者您必须将写入结束打开直到完成。
这导致了这样的代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
enum { numForks = 5 };
static int findKey(void)
{
return getpid() % numForks;
}
int main(void)
{
int j;
int pipes[2];
pipe(pipes);
int count = 0, t = 0;
for (j = 1; j <= numForks; j++)
{
pid_t pid;
if ((pid = fork()) == 0)
{
count = findKey();
close(pipes[0]);
write(pipes[1], &count, sizeof(count));
exit(0);
}
}
close(pipes[1]);
while (read(pipes[0], &t, sizeof(t)) == sizeof(t))
{
printf("Got %d\n", t);
count += t;
}
printf("count = %i\n", count);
return 0;
}
示例运行:
Got 0
Got 1
Got 2
Got 3
Got 4
count = 10
显然,这是使用虚拟findKey()
函数。另请注意最基本的调试技术:在读取数据时打印数据。它也会异步运行子进程。他们在这里做的不多。代码仍然不会检查除read()
之外的任何系统调用,这是懒惰的。