[英]Why can't I write to or read from pipes?
我已经看到了很多类似的问题,但是所有这些问题都针对特定的情况,因此没有帮助我找到解决方案。 对于我的情况,请提供以下反馈:
我正在尝试编写一个程序来从文本文件中获取字符数。 该程序通过派生四个映射器和26个reducer并为它们中的每个创建管道来工作。 父进程将输入分为四行,然后将其传递给每个映射器,该映射器计算其行中每个字符的数量。 然后,每个映射器将计数传递到适当的缩减器,后者对所有四个计数求和并打印结果。
以下是到目前为止的代码:
int main(int argc, char *argv[])
{
int i = 0;
FILE *input = fopen("input.txt", "r");
// Things for reading line-by-line: see getline reference on man7.org
char *line = NULL;
size_t len = 0;
// Where we'll store the messages
static char message[MSGSIZE];
for(i = 0; i < NUMREDUCERS; i++)
{
pipe(reducer_pipes[i]);
}
for(i = 0; i < NUMMAPS; i++)
{
// Step 1: Create pipes for communication using the system call pipe()
pipe(mapper_pipes[i]);
// Step 2: Fork a number of mappers (4).
if (fork() == 0)
{
// Don't want to close the write pipe yet
// Child process: one of the mappers
read(mapper_pipes[i][0], message, MSGSIZE); // Read from reading end
char *msg = "Error reading from pipe";
check_errors(msg);
// Get char count and write to pipe
int j = 0;
int ccount = 0;
for(j = 0; j < NUMREDUCERS; j++)
{
// Count up the number of chars
ccount = count_char(message, (char) (j + 97), MSGSIZE);
// Write to the appropriate reducer pipe
write(reducer_pipes[j][1], (char *) ccount, MSGSIZE);
msg = "error writing to reducer pipe";
check_errors(msg);
}
exit(EXIT_SUCCESS);
}
else
{
getline(&line, &len, input);
// Parent process
write(mapper_pipes[i][1], line, (int) len);
char *msg = "Error writing to pipe";
check_errors(msg);
}
}
return 0;
}
我遇到的问题是我无法写入减速器管道。 每当我尝试写入,读取或关闭它们时,我都会收到一个错误的地址错误。 他们以某种方式到期了吗? 我没有正确创建它们吗? 如果有人愿意提供意见,我将不胜感激。
快速编辑:我删除了所有“关闭”语句,因为它们都存在相同的问题。 但是,我尝试关闭应该关闭管道的位置,只是找到了相同的错误消息。
“地址errno == EFAULT
”( errno == EFAULT
)表示您已将无效指针传递给系统调用。 从本质上讲,它相当于一个段错误(我相信某些系统实际上在这种情况下会提高SIGSEGV
)。
看这行:
write(reducer_pipes[j][1], (char *) ccount, MSGSIZE);
这里的ccount
是int类型的。 将int转换为指针始终是可疑的。
在上一行中,您ccount
分配给count_char()
的返回值。 现在您没有向我们展示该函数的代码,但是我想它会返回一个字符数-最有可能是一个小整数。 假设它返回了17。您正在告诉write
写入位于地址17的MSGSIZE
字节。这肯定不是您想要的。
如果您想以二进制格式将该整数发送给reducer,您可能想说
write(reducer_pipes[j][1], &ccount, sizeof(ccount));
当然,您必须在减速器端具有匹配的代码。
其他人已经解决了代码中的许多其他问题,例如您仅通过查看errno
就无法可靠地检测错误(这大概就是check_errors
所做的事情)。 如果系统调用没有错误,则即使先前具有非零值,也不会errno
。 相反,您应该做的是检查write()
的返回值; 如果它是-1
那么将发生错误,只有这样,您才应该查看errno
(或致电perror
)以查看其含义。
基本上,每当您进行系统调用并且不检查返回值时,都会遇到错误。
您没有显示您的check_errors
函数是什么,但是我猜想它只是在显示错误消息而没有实际检查错误的情况下,假设您仅在发生错误后才调用它。 因此,您实际上可能并没有收到错误消息。
您实际上需要检查读写调用的返回值,以查看是否发生错误:
if ((len = read(mapper_pipes[i][0], message, MSGSIZE)) < 0) // Read from reading end
perror("Error reading from pipe");
请注意,如果没有错误,返回值还会告诉您接收到的消息的长度(您应该在查看该消息的后续代码中使用该值代替MSGSIZE
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.