通过管道读取和写入数据

时间:2011-09-07 13:08:11

标签: c fork pipe

我使用fork()创建了两个进程。子进程正在连续生成和写入可变数量的数据(数组char)到管道。父进程从管道读取并将接收的数据打印到stdout。

代码非常简单:

switch (fork()) {
  case -1: 
    exit (1);
    break;
  case 0:
    close(fd[0]);
    generate_data(fd[1]);
    break;
  default:
    close(fd[1]);
    while(1) {
        n = read(fd[0], readbuffer, sizeof(readbuffer));
        readbuffer[n] = 0;
        if (n > 0)
            printf ("read: %s\n", readbuffer);            
        else
            exit(1);
    }   
   break;
}   

其中generate_data(int)遍历列表,将每个元素(字符串)写入作为参数给出的文件描述符(在这种情况下为管道的写端):

void generate_data(int fd) 
{
   node_t node* = list;
   while (node != NULL) {
     write(fd, node->data, strlen(node->data)+1);
     node = node->next();
   }

}

这里的问题是输出总是不可预测的:当另一个进程处理最后一个read时,子进程将数据写入管道,所以当它再次调用read时,其余的数据不是那里了。

根据man 2 pipe,这不应该发生:

  

写入管道写端的数据由缓冲   内核,直到从管道的读取端读取。

列出10个元素,一些输出示例:

示例1:

read: element_4
read: element_8
read: element_9

示例2:

read: element_7
read: element_8
read: element_9
read: element_10

示例3:

read: element_2
read: element_8

任何人都知道这里发生了什么?

2 个答案:

答案 0 :(得分:3)

你调用read并捕获返回值,但是你在很大程度上忽略了它;它告诉你readbuffer中有多少有效字节,但是你正在将readbuffer视为包含一个以零结尾的字符串,但这并不一定。实际上,如果您的数据写入过程通过管道发送read字节,则单个0可能会为您提供多个零终止字符串;使用printf意味着你忽略了第二个和后续的那些。至少,您需要使用fwrite将特定的,正确的字节数写入stdout,尽管我怀疑您实际需要做的是先用换行符替换这些零。修改generate_data以发送换行而不是零可能是一个更好的主意。

答案 1 :(得分:0)