来自stdin的read()

Rav*_*pta 16 c unix linux io

考虑以下代码行:

while((n = read(STDIN_FILENO, buff, BUFSIZ)) > 0)
Run Code Online (Sandbox Code Playgroud)

根据我的理解,read/write函数是非缓冲I/O的一部分.那么这意味着read()每次调用stdio时函数只能读取一个字符吗?或者换句话说,n的值将是

    -1  in case of error
n =  0  in case of EOF
     1  otherwise
Run Code Online (Sandbox Code Playgroud)

如果不是这种情况,上述read()功能何时会返回?为什么?

注意:我也在考虑read()等到它成功读取BUFSIZstdin中的字符数.但是,在一个案例中可以读取的字符数小于BUFSIZ?将永远等待或直到EOF到达(Ctrl + D在unix或Ctrl + ZWindows上)?

另外,让我们说BUFSIZ = 100stdin = ACtrl+D(即EOF紧跟一个字符后).现在while loop迭代的次数是多少次?

Kyl*_*nes 20

read()的行为方式取决于正在读取的内容.对于常规文件,如果要求N个字符,如果可用,则获得N个字符,如果文件末尾介入,则小于N个字符.

如果read()正在以规范/烹饪模式从终端读取,则tty驱动程序一次提供一行数据.因此,如果你告诉read()获得3个字符或300个,读取将挂起,直到tty驱动程序看到换行符或终端定义的EOF键,然后read()将返回行中的字符数或者您请求的字符数,以较小者为准.

如果read()从非规范/原始模式的终端读取,则读取将立即访问按键.如果你要求read()获得3个字符,它可能会返回0到3个字符,具体取决于输入时序和终端的配置方式.

read()在信号面前表现不同,返回时小于请求的字符数,如果信号在任何字符到达之前中断读取,则errno设置为EINTR为-1.

如果已为非阻塞I/O配置了描述符,则read()的行为会有所不同.如果没有立即可用的输入,read()将返回-1,并将errno设置为EAGAIN或EWOULDBLOCK.这适用于套接字.

所以你可以看到,当你调用read()时,你应该准备好迎接惊喜.您不会总是得到您请求的字符数,并且您可能会收到像EINTR这样的非致命错误,这意味着您应该重试read().


Jon*_*ler 6

你的代码如下:

while((n = read(0, buff, BUFSIZ) != 0))
Run Code Online (Sandbox Code Playgroud)

这是有缺陷的 - 括号意味着它被解释为:

while ((n = (read(0, buff, BUFSIZ) != 0)) != 0)
Run Code Online (Sandbox Code Playgroud)

其中布尔条件在赋值之前进行评估,因此n只会获得值 0(条件不为真)和 1(条件为真)。

你应该写:

while ((n = read(0, buff, BUFSIZ)) > 0)
Run Code Online (Sandbox Code Playgroud)

这会在 EOF 或读取错误时停止,并n让您知道遇到了哪种情况。


显然,上面的代码是问题中的拼写错误。

无缓冲 I/O 将读取最多您读取的字符数(但不能更多)。由于 EOF 或错误,它可能会读取较少。它也可能读取较少,因为调用时可用的内容较少。考虑一个终端;通常,它只会读到行尾,因为没有比这更可用的了。考虑一根管道;如果馈送过程生成了 128 个未读字节,那么如果 BUFSIZ 为 4096,则您只能从读取中获得 128 个字节。非阻塞文件描述符可能会因为没有可用的内容而返回;套接字可能返回更少的字节,因为还没有更多可用信息;磁盘读取可能返回较少的字节,因为执行读取时文件中剩余的字节数少于请求的字节数。

不过,一般来说,read()如果您请求许多字节,则不会只返回一个字节。


Dav*_*ave 3

正如read()联机帮助页所述:

返回值

成功时,返回读取的字节数(零表示文件结尾),并且文件位置将前进该数字。如果该数字小于请求的字节数,则不是错误;例如,这可能会发生,因为现在实际可用的字节数较少(可能是因为我们接近文件结尾,或者因为我们正在从管道或终端读取),或者因为 read() 被信号。出错时,返回 -1,并适当设置 errno。在这种情况下,未指定文件位置(如果有)是否更改。

因此,每个read()将读取指定字节数;但读起来可能会少一些。“非缓冲”意味着如果指定read(fd, bar, 1),read将只读取一个字节。缓冲 IO 会尝试读取 的量BUFSIZ,即使您只需要一个字符。这听起来可能很浪费,但它避免了进行系统调用的开销,这使得速度更快。