从管道中读取:如何处理c中的返回值?

时间:2016-02-15 12:15:42

标签: c pipe return-value

我正在编写一个程序来读取管道,我想知道处理返回值的正确方法是什么。根据阅读手册页,

  

成功时,返回读取的字节数(零表示文件结束),文件位置按此编号前进。如果此数字小于请求的字节数,则不是错误;这可能发生在例如因为现在实际可用的字节数较少(可能是因为我们接近文件结尾,或者因为我们正在从管道或终端读取),或者因为read()被中断了信号。

我担心它只能读取一半数据的情况。另外,当返回值为零时,处理这种情况的正确方法是什么?

这是我的示例代码。

struct day
{
        int date;
        int month;
};

while(1)
{
        ret = select(maxfd+1, &read_fd, NULL, &exc_fd,NULL);
        if(ret < 0)
        {
                perror("select");
                continue;
        }
        if(FD_ISSET(pipefd[0], &read_fd))
        {
                struct day new_data;
                if((ret = read(pipefd[0], &new_data, sizeof(struct day)))!= sizeof(struct day))
                {
                        if(ret < 0)
                        {
                                perror("read from pipe");
                                continue;
                        }
                        else if(ret == 0)
                        {
                                /*how to handle?*/
                        }
                        else
                        /* truncated read. How to handle?*/
                }
        }
        ...
}

我相信read()无法读取比指定大小更多的数据。如果我错了,请纠正我。

请帮我处理读取的返回值。

2 个答案:

答案 0 :(得分:1)

当您read请求给定数量的数据时,但没有任何东西可以保证您可以根据请求读取尽可能多的可用数据。例如,您可能会遇到文件结尾,或者编写器部分没有在管道中写入太多数据。因此read会返回有效读取的内容,即返回的读取字节数(零表示文件结束)

如果read返回一个严格正数,那就很清楚。

如果read返回0,则表示文件结束。对于常规文件,这意味着您当前位于文件的末尾。对于管道,这意味着管道为空,不会写入任何单个字节。对于管道而言,这意味着您已经读取了所有数据并且另一端没有更多的写入器(因此不会写入更多的字节),因此您可以关闭现在无用的管道。

如果read返回-1,则表示发生了错误,您必须咨询errno变量以确定问题的原因。

因此,一般模式可能类似于:

n = read(descriptor,buffer,size);
if (n==0) { // EOF
  close(descriptor);
} else if (n==-1) { // error
  switch(errno) { // consult documentations for possible errors
    case EAGAIN: // blahblah
  }
} else { // available data
  // exploit data from buffer[0] to buffer[n-1] (included)
}

答案 1 :(得分:0)

如果read返回0,那么您的进程已读取将来自该文件描述符的所有数据。把它从read_fd中拿出来,如果是maxfd重置maxfd到最新的最大值。根据您的流程的不同,您可能还需要进行其他清理工作。如果您进行了简短的阅读,那么要么处理您收到的数据,要么将其丢弃或存储,直到您获得所有数据并进行处理。

很难对一般问题给出更具体的答案。