aio_write()和O_NONBLOCK write()的区别

5
什么是aio_write()和O_NONBLOCK write()之间的区别? 同时,我使用write()函数通过文件描述符使用O_NONBLOCK函数写入文本文件,并通过在函数前后放置计时器来比较其性能与aio_write()。 似乎当字符串长度增加时,write()函数写入文件需要更长的时间,但aio_write()仍然保持大致相同的时间。 为什么会这样?NONBLOCK和asynchronous有什么区别吗? 谢谢。
1个回答

14
使用O_NONBLOCK的write()函数将接受(即复制到内核缓冲区)你传递给它的所有、一部分或没有数据(如果接受了一些字节,write()的返回值将指示它接受了多少字节...如果没有接受,则write()将返回-1,并将errno设置为EWOULDBLOCK)。write()接受的字节数取决于其内核缓冲区当前可用的空间大小。在write()返回后,你需要记住它接受了多少字节,并调用select()(或poll()或其他机制),以便在缓冲区中有更多空间可用时进行通知。当有更多空间可用(即在未来某个时间)时,你可以再次调用write()向缓冲区传递更多字节。
另一方面,aio_write()函数将“拥有”你传递给它的数据,并在稍后通知你已完成写出数据。使用aio_write(),你不必担心调用仅接受部分数据缓冲区;它要么接受整个缓冲区,要么报错。在这方面,异步I/O会使应用程序的I/O逻辑变得更简单;但我认为异步I/O也有其自身的一套复杂因素,因此并不总是优势。(我自己没有使用过aio_*()函数,因此无法提供详细信息)
至于为什么write()函数似乎不随所写数据长度的增加而花费更多时间...这是因为非阻塞的write()函数只将你传递给它的(零个、一部分或全部)数据复制到缓冲区,然后立即返回;它实际上并不等待数据进入磁盘。从应用程序的缓冲区复制(相对较小的)字节序列到内核缓冲区总是很快的,并且每次write()复制的字节数永远不会大于内核缓冲区当前可用的空间量,因此每次write()复制的字节数都是有限/较小的。

1
总结一下:如果内核缓冲区有足够的空间,则没有任何区别。 如果没有,O_NONBLOCK 将失败,aio_write 将稍后在线程外执行。 - Ben Voigt
2
那是个不错的总结,除了 O_NONBLOCK 不一定会失败… 它可能只是接受一部分你提供的数据然后留下其余部分。 - Jeremy Friesner
aio_write使用的缓冲区数据是否也由内核缓冲?根据POSIX似乎不是这样。请参阅https://pubs.opengroup.org/onlinepubs/9699919799/搜索未缓冲。 - Han XIAO

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接