C中写入(2)的返回值是0是错误吗?

Rob*_*nes 13 c linux posix tcp

在系统调用的手册页中写(2) -

ssize_t write(int fd, const void *buf, size_t count);

它说如下:

回报价值

成功时,返回写入的字节数(零表示没有写入).出错时,返回-1,并errno进行适当设置.如果count为零且文件描述符引用常规文件,则可能返回0,或者可以检测到错误.对于特殊文件,结果不可移植.

我会将此解释为意味着返回0只意味着没有任何内容被写入,无论出于何种原因.

但是,当处理作为TCP套接字的文件描述符时,UNP中的Stevens将返回值0视为致命错误(这由另一个调用exit(1)短计数的函数包装):

ssize_t /* Write "n" bytes to a descriptor. */
writen(int fd, const void *vptr, size_t n)
{
    size_t      nleft;
    ssize_t     nwritten;
    const char  *ptr;

    ptr = vptr;
    nleft = n;
    while (nleft > 0) {
        if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
            if (nwritten < 0 && errno == EINTR)
                nwritten = 0;       /* and call write() again */
            else
                return(-1);         /* error */
        }

        nleft -= nwritten;
        ptr   += nwritten;
    }
    return(n);
}
Run Code Online (Sandbox Code Playgroud)

如果errno指示写入的调用被接收信号的进程中断,则他仅将0视为合法返回值.

为什么?

Per*_*ytt 7

史蒂文斯可能这样做是为了捕获表现不同的旧的write()实现.例如,单Unix规范说(http://www.opengroup.org/onlinepubs/000095399/functions/write.html)

如果此体积的IEEE Std 1003.1-2001要求返回-1并将errno设置为[EAGAIN],则大多数历史实现返回零

  • 我用那句话抬起了段落,我认为你是对的.我认为原因是这个特定的函数只能用于阻塞套接字,它应该永远不会返回0表示调用会阻塞.另外,将0字节写入文件描述符将返回0,但这对于套接字也是不可取的,因为这不会导致将EOF写入描述符,因为只有对`shutdown`或`close`的调用才能执行此操作.一个插座.因此,在此上下文中,0始终表示意外/非法行为. (2认同)

mar*_*k4o 6

这将确保代码不会无限期地旋转,即使文件描述符不是 TCP 套接字或意外的非阻塞标志生效也是如此。在某些系统上,如果无法在不阻塞的情况下写入数据,某些传统的非阻塞模式(例如O_NDELAY)会导致write()返回 0(无需设置errno),至少对于某些类型的文件描述符而言。(POSIX 标准O_NONBLOCK在这种情况下使用错误返回。)某些系统上的某些非阻塞模式适用于底层对象(例如套接字、fifo)而不是文件描述符,因此甚至可以由另一个启用具有同一对象的打开文件描述符的进程。在这种情况下,代码通过简单地将其视为错误来保护自身免于旋转,因为它不适用于非阻塞模式。