考虑下面的代码行:
while((n = read(STDIN_FILENO,buff,BUFSIZ)) > 0)
根据我的理解, read/writefunction是非缓冲I / O的一部分。 那么这是否意味着read()函数将从stdio每次只读取一个字符? 换句话说,n的值将会是
-1 in case of error n = 0 in case of EOF 1 otherwise
如果不是这种情况,上面的read()函数什么时候会返回,为什么?
注意:我也在考虑read()将等待,直到它成功地从标准input读取BUFSIZ字符数。 但是,在可读取的大小写字符数量less于BUFSIZ的情况下会发生什么? 将读取永久等待或直到EOF到达( Ctrl + D在unix或Ctrl + Z在Windows上)?
无法读取C中的UNICODE文本文件
如何在Windows中移动文件而不更改目标父文件夹的修改时间(Win32)?
什么原因导致WriteFile返回ERROR_ACCESS_DENIED?
如何find经常做io的过程?
另外,让我们说BUFSIZ = 100和stdin = ACtrl+D (即EOF紧跟在单个字符之后)。 现在while loop会迭代多less次?
pipe道batch file输出到Python脚本
将Windows CDROM驱动器视为阻止文件?
“系统调用参数打开(模式)包含未初始化的字节(S)”在打开系统调用
read()的行为方式取决于正在读取的内容。 对于普通文件,如果要求输入N个字符,如果可用,则会得到N个字符,如果文件结束,则会得到N个字符。
如果read()正在以规范/熟化模式从终端读取,则tty驱动程序一次提供一行数据。 所以,如果你告诉read()得到3个字符或者300,那么read会挂起,直到tty驱动程序看到一个换行符或者终端的定义的EOF键,然后read()将返回该行的字符数或者您请求的字符数量,以较小者为准。
如果read()正在以非规范/原始模式从终端读取,则read将立即访问按键。 如果您要求read()获取3个字符,则可能会返回0到3个字符的任意位置,具体取决于输入时间以及终端的配置方式。
如果在任何字符到达之前信号中断读取,则read()在面对信号时会有不同的表现,返回的字符数小于请求的字符数,或者当errno设置为EINTR时返回-1。
如果描述符已配置为非阻塞I / O,则read()的行为将有所不同。 如果没有输入立即可用,则read()将返回-1,并将errno设置为EAGAIN或EWOULDBLOCK。 这适用于套接字。
正如你所看到的,当你调用read()时,你应该准备好了。 您不会总是得到您请求的字符数,并且您可能会遇到像EINTR这样的非致命错误,这意味着您应该重试read()。
你的代码如下:
while((n = read(0,BUFSIZ) != 0))
这是有缺陷的 – 括号表示它被解释为:
while ((n = (read(0,BUFSIZ) != 0)) != 0)
布尔条件在赋值之前被求值,所以n只会得到值0(条件不成立)和1(条件成立)。
你应该写:
while ((n = read(0,BUFSIZ)) > 0)
这在EOF或读取错误上停止, n让你知道你遇到了哪种情况。
无缓冲I / O将读取您读取的字符数(但不是更多)。 由于EOF或错误,它可能会读取较少。 由于通话时间较短,因此可能会读取较少。 考虑一个终端; 通常情况下,这只会读到行的末尾,因为没有更多的可用。 考虑一个管道; 如果馈送进程已经产生了128个未读字节,那么如果BUFSIZ是4096,则只能从读取中获得128个字节。 无阻塞的文件描述符可能会返回,因为什么都不可用; 套接字可能会返回更少的字节,因为没有更多的信息可用; 磁盘读取可能会返回更少的字节,因为执行读取时文件中剩余的字节数少于请求的字节数。
但是,一般来说,如果请求多个字节, read()将不会返回一个字节。
正如read()页所述:
返回值
成功时返回读取的字节数(零表示文件结束),文件位置按此编号提前。 如果这个数字小于请求的字节数就不是错误; 这可能发生,例如因为现在实际上可用的字节更少(可能是因为我们接近文件结束,或者因为我们正在从管道读取或从终端读取),或者因为read()被中断信号。 出错时,返回-1,并适当地设置errno。 在这种情况下,没有指定文件位置(如果有的话)是否改变。
所以,每个read()将读取最多的指定字节数; 但可能会少一些。 “非缓冲”意味着如果指定read(fd,bar,1) ,读将只读取一个字节。 缓冲IO尝试读入BUFSIZ量子,即使你只需要一个字符。 这听起来很浪费,但它避免了系统调用的开销,这使得它更快。
读取尝试获取所有请求的字符。
如果EOF在所有请求的字符可以返回之前发生,它返回它得到之后得到的下一个读取返回-1,让你知道你的文件结束。
当它试图读取时会发生什么,并且什么都没有涉及阻塞的东西。 您可以调用open来读取阻塞或非阻塞的文件。 “阻塞”意味着等到有东西要回来。
这就是您在等待输入的shell中看到的内容。 它坐在那里。 直到你回来。
非阻塞意味着如果没有数据,读取将不返回任何数据字节。 根据很多其他的因素,你会得到一个完全正确的答案,阅读将把errno设置成像EWOULDBLOCK这样的东西,它可以让你知道为什么你的读取返回了零字节。 这不一定是一个致命的错误。
当我们说read是无缓冲的,这意味着在数据从底层的打开文件描述(这是一个潜在的共享资源)中取出之后,在进程级别上不会发生缓冲。 如果stdin是一个终端,那么至少有两个额外的缓冲区在使用:
终端缓冲区,它可能会保持1-4k的数据,直到。
内核的熟化/规范模式缓冲区用于终端上的行输入/编辑,它允许用户通过按Enter键在行上执行原始编辑(退格,后退,删除行等),直到它被提交(到上述缓冲区) 。
read将提交已经提交的任何内容,直到传递给它的最大读取长度,但是它不能从行编辑缓冲区中取出任何东西。 如果你想禁用这个额外的缓冲层,你需要查找如何禁用使用tcsetattr等终端熟/标准模式。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。