考虑下面这行代码:
while((n = read(STDIN_FILENO, buff, BUFSIZ)) > 0)
根据我的理解,read/write
函数是非缓冲I/O的一部分。那么,这是否意味着read()
函数将在每次调用时只从stdio读取一个字符?或者换句话说,n的值将是
-1 in case of error
n = 0 in case of EOF
1 otherwise
如果不是,那么上述read()
函数将在什么时候返回?为什么?
注意:我还认为read()
将等待,直到它成功地从标准输入中读取BUFSIZ
数量的字符。但是,如果可供读取的字符数少于BUFSIZ
,会发生什么情况呢?read是永远等待还是等到EOF到来( unix上的Ctrl + D
或windows上的Ctrl + Z
)?
另外,假设是BUFSIZ = 100
和stdin = ACtrl+D
(即紧跟在单个字符后面的EOF )。现在,while loop
将迭代多少次?
发布于 2012-01-23 17:16:50
read()的行为方式取决于所读取的内容。对于常规文件,如果请求N个字符,则得到N个字符(如果可用),如果文件末尾介入,则得到少于N个字符。
如果read()在规范/熟食模式下从终端读取数据,tty驱动程序会一次提供一行数据。因此,如果您告诉read()获取3个字符或300个字符,那么read将挂起,直到tty驱动程序看到换行符或终端定义的EOF键,然后read()将返回该行中的字符数或您请求的字符数,取较小的值。
如果read()在非规范/原始模式下从终端读取,那么read将立即访问按键。如果您要求read()获取3个字符,它可能会返回0到3个字符,这取决于输入时间和终端的配置方式。
在遇到信号时,read()的行为会有所不同,返回的字符数少于请求的字符数,或者如果在任何字符到达之前信号中断了读取,则返回-1并将errno设置为EINTR。
如果描述符已配置为非阻塞I/O,则read()的行为将有所不同。如果没有立即可用的输入,read()将返回-1并将errno设置为EAGAIN或EWOULDBLOCK。这适用于套接字。
因此,正如您所看到的,当您调用read()时,应该准备好迎接惊喜。您不会总是得到所请求的字符数,并且可能会得到像EINTR这样的非致命错误,这意味着您应该重试read()。
发布于 2012-01-23 17:19:06
您的代码为:
while((n = read(0, buff, BUFSIZ) != 0))
这是有缺陷的-括号意味着它被解释为:
while ((n = (read(0, buff, BUFSIZ) != 0)) != 0)
其中,布尔条件在赋值之前求值,因此n
将仅获得值0(条件不为真)和1(条件为真)。
你应该这样写:
while ((n = read(0, buff, BUFSIZ)) > 0)
这会在出现EOF或读取错误时停止,n
会让您知道遇到了哪种情况。
显然,上面的代码是问题中的一个打字错误。
无缓冲I/O读取的字符数将达到您读取的字符数(但不会更多)。它可能会因为EOF或错误而读取较少。它也可能读取较少的内容,因为在调用时有较少的内容可用。以终端为例;通常,它只能读到行尾,因为没有比行尾更多的数据可用。考虑一个管道;如果供给进程生成了128个未读字节,那么如果BUFSIZ是4096,那么从读取中只能获得128个字节。非阻塞文件描述符可能会因为没有可用的东西而返回;套接字可能会返回更少的字节,因为还没有更多的信息可用;磁盘读取可能会返回更少的字节,因为在执行读取时,文件中剩余的字节数少于请求的字节数。
不过,通常情况下,如果您请求很多字节,read()
不会只返回一个字节。
发布于 2012-01-23 17:06:53
正如read()
手册页所述:
返回值
如果成功,将返回读取的字节数(0表示文件结束),文件位置将按此数字前进。如果这个数字小于请求的字节数,这不是错误;例如,这可能是因为现在实际可用的字节更少了(可能是因为我们接近文件末尾,或者因为我们正在从管道或终端读取数据),或者因为read()被信号中断。出错时,返回-1,并适当设置errno。在这种情况下,未指定文件位置(如果有)是否更改。
因此,每个read()
将读取指定的字节数;但它读取的字节数可能会更少。"Non-buffered“表示如果指定read(fd, bar, 1)
,read将只读取一个字节。缓冲IO尝试读取BUFSIZ
的数量,即使您只需要一个字符。这听起来可能很浪费,但它避免了进行系统调用的开销,这使得它很快。
https://stackoverflow.com/questions/8975521
复制相似问题