非阻塞文件的结尾

问题描述

在非阻塞模式下如何检测文件结尾?     

解决方法

至少在POSIX(包括Linux)上,显而易见的答案是不存在非阻塞常规文件。常规文件始终会阻塞,而O_NONBLOCK会被静默忽略。 同样,poll()/ select()等。会始终告诉您,指向常规文件的fd已准备好进行I / O,无论数据是在页面缓存中还是在磁盘上(大多数与读取有关)都准备就绪。 编辑而且,由于O_NONBLOCK是常规文件的禁忌,因此常规文件上的read()永远不会将errno设置为EAGAIN,这与对该问题的另一个答案相反。 EDIT2参考: 从POSIX(p)select()规范中:\“与常规文件关联的文件描述符应始终为true,以准备读取,准备写入和出现错误情况。” 从POSIX poll()规范中:\“常规文件应始终将TRUE轮询以进行读写。 上面的内容足以暗示,虽然可能没有严格禁止,但非阻塞常规文件没有任何意义,因为除了忙碌等待之外,没有其他方法可以轮询它们。 除上述以外,至少还有一些间接证据 根据POSIX open()规范:定义了引用管道,块特殊文件和字符特殊文件的文件描述符的行为。 \“否则,未指定O_NONBLOCK的行为。” 一些相关链接: http://tinyclouds.org/iocp-links.html http://www.remlab.net/op/nonblock.shtml http://davmac.org/davpage/linux/async-io.html 而且,即使在stackoverflow上: 非阻塞IO可以使常规文件读取受益吗? 正如R.的答案所指出的那样,由于页面缓存的工作原理,对于常规文件的非阻塞不是很容易定义。例如。如果通过某种机制发现已经准备好在页面缓存中读取数据,然后在读取数据之前,内核由于内存压力而决定将该页面从缓存中踢出,该怎么办?对于套接字和管道,它是不同的,因为正确性要求不要像这样丢弃数据。 另外,如何选择/轮询可搜索的文件描述符?您将需要一些新的API,这些API支持指定您感兴趣的文件中的哪个字节范围。该API的内核实现将与VM系统绑定,因为它将需要阻止您的页面。对被踢出感兴趣。这意味着这些页面将计入进程锁定页面的限制(请参阅ulimit -l)以防止DOS。而且,这些页面什么时候才能解锁?等等。     ,这是一个非常好的问题。非阻塞套接字从“ 0”返回一个空字符串,而不是抛出“ 1”以指示没有可用数据。不过对于文件来说,似乎没有任何可用于Python的直接指示符。 我能想到的唯一一种检测EOF的机制是在接收到空字符串后将文件的当前位置与文件的整体大小进行比较:
def read_nonblock( fd ):
    t = os.read(fd,4096)
    if t == \'\':
        if os.fstat(fd).st_size == os.lseek(fd,os.SEEK_CUR):
            raise Exception(\"EOF reached\")
    return t
当然,这假定非阻塞模式下的常规文件实际上将立即返回,而不是等待从磁盘读取数据。我不确定在Windows或Linux上是否如此。值得测试,但是即使在非阻塞模式下读取常规文件也只会在遇到实际EOF时返回空字符串,我不会感到惊讶。     ,在c ++(YMMV)中很好用的一个好技巧是,如果返回的数据量小于缓冲区的大小(即缓冲区未满),则可以安全地假定事务已完成。那么文件的最后部分就有1 / buffersize的可能性完全填满了缓冲区,因此对于较大的缓冲区,您可以合理地确定事务将以未填充的缓冲区结束,因此如果您测试数据量返回缓冲区大小,并且它们不相等,您知道发生了错误或事务已完成。不知道这是否将转换为python,但这是我发现EOF的方法     ,即使选择EOF,也不会选择告诉您有什么要阅读的内容吗?如果它告诉您有什么要阅读的东西,而您又没有得到任何东西,那么它一定是EOF。我相信插座就是这种情况。     ,对于文件,将文件描述符设置为非阻塞将无济于事-所有IO都会阻塞。 如果您确实需要非阻塞文件IO,则需要查看ѭ3和朋友,它们是用于文件访问的异步IO工具。这些是非常不可移植的,并且有时工作起来有些混乱-因此,大多数项目实际上已经决定对IO使用单独的进程(或线程),并在那里仅使用阻塞IO。 再说一遍,也许您对以某种方式“选择”文件感兴趣:当文件增长时,您会收到通知。您可能已经意识到
select
poll
等不起作用。大多数软件都是通过每秒轮询一次文件来完成此操作的,例如\“ tail -f \”通过轮询来做到这一点很神奇。但是,您也可以让内核在文件写入时通知您-
inotify
和朋友发生这种情况。有一些方便的库可以为您完成所有这些工作,因此您不必自己弄乱细节。即,对于python,分别为
inotifyx
pyinotify
。     

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...