我正在使用这两个this回答的程序。这个答案使用命名管道而不是管道,我是否正确?
我写了main.c,它实际上是我实际项目的代码,最小化到这个特定问题(这就是为什么我有一个for循环的例子)。
#include <unistd.h>
#include <sys/wait.h>
#include <stddef.h>
#include <limits.h>
#include <stdio.h>
int main(void) {
pid_t pid;
int i;
for(i = 0; i < 2; ++i) {
pid = fork();
if (pid == -1) {
// error, failed to fork()
perror("failed to fork()");
return 1;
} else if (pid == 0) {
// child code
if(i < 1) {
// the writer.c
char* arg_list[] = { "w", NULL };
execv( "w", arg_list );
printf("exec FAILED\n");
} else {
// the reader.c
char* arg_list[] = { "r", NULL };
execv( "r", arg_list );
printf("exec FAILED\n");
}
}
}
// parent code
int status;
// wait for all children to terminate
while ((pid = wait(&status)) > 0) {
if (status == 1) {
printf("The child process terminated with an error!\n");
return -1;
}
}
printf("All children are done\n");
return 0;
}
问题在于有时,读者会收到垃圾(或者很可能没有)并且它会挂断。
示例输出:
Received: Hi
All children are done
samaras@samaras-A15:~/test$ ./m
Received: Hi
All children are done
samaras@samaras-A15:~/test$ ./m
Received: <----------------- This is garbage, that is not reproducible
^C
那么,我错过了什么?
无需在下面阅读。
我的猜测是(没有检查,所以如果我是正确的,我仍然需要澄清):
读者在作家面前跑,这就是为什么它有垃圾,但为什么它会挂起?
或
我需要编写一个包装函数read_all()
(还有一个用于写案例?),它收集管道吐出的所有数据,但为什么如果我更换&#34;嗨&#34;与&#34; H&#34;,我有相同的行为?
编辑:
如果我的第一个猜测就是这种情况,我会设置一个循环进行阅读,但是在读者首先启动的情况下它将永远执行。
在我看到垃圾的情况下,在使用strace -f
后,我得到了这个:
...
[pid 3326] read(-1, 0xbfddd80c, 1024) = -1 EBADF (Bad file descriptor)^C
Process 3324 resumed
Process 3325 detached
Process 3326 detached
答案 0 :(得分:1)
你的循环(或缺乏)与它无关。当您的阅读器打开(open()
)管道,以便在writer创建管道之前进行读取,然后读者等待的文件描述符无效(-1
)。因此,即使作者稍后写了一些内容,读者也会等待无效的fd(-1
)并且永远不会读取任何内容。平凡的,您可以通过以下方式解决它:
while( (fd = open(myfifo, O_RDONLY)) == -1);
在读卡器中等待管道可用。我其实想知道是否有比这更好的方法。我能想到的另一种方法是access()
上的循环,但它与此并没有太大的不同......