POSIX阻塞I/O的write()是否需等待DMA设备完成数据写入?
阻塞模式下POSIX
write() 调用的阻塞行为 首先明确:POSIX标准并没有严格规定write()要等待DMA完成磁盘数据传输,还是仅把数据提交给DMA就返回——它只要求write()成功返回后,数据已经被安全地交由内核处理(要么进入内核缓存,要么已写入设备),具体行为由操作系统和IO场景决定。
普通文件(默认页缓存模式)的常见行为
对于绝大多数普通磁盘文件,操作系统默认会用**页缓存(page cache)**来优化IO性能:
- 当你调用
write()时,内核首先把用户空间缓冲区的数据拷贝到内核页缓存,更新文件元数据后就会返回——这时候数据还在内存里,后续由内核后台线程异步刷到磁盘。这种情况下,write()的耗时主要来自内存拷贝,大缓冲区会因为拷贝数据更多而耗时增加,但并不是等待DMA完成磁盘写入。 - 但如果遇到以下情况,
write()会阻塞直到数据真正写入磁盘:- 系统可用内存不足,内核需要先把旧的缓存页刷到磁盘来腾出空间给新数据
- 打开文件时指定了
O_SYNC或O_DSYNC标志,强制write()等待数据写入磁盘后返回 - 写入后调用了
fsync(),这时候会阻塞到磁盘写入完成
直接IO(O_DIRECT)场景的行为
如果打开文件时使用了O_DIRECT标志绕过页缓存,write()的行为就完全不同:
- 此时数据会直接从用户缓冲区提交给DMA控制器,
write()会阻塞直到DMA完成整个数据块的磁盘写入操作。这种情况下,缓冲区越大,DMA传输的时间就越长,write()的耗时自然会显著增加——这和你的测试结果完全匹配。
对你测试结果的解释
你观察到write()耗时随缓冲区增大显著增加,大概率是以下两种情况之一:
- 你的测试触发了内核的同步刷写逻辑(比如内存不足),导致
write()需要等待旧缓存页写入磁盘 - 你无意中使用了直接IO模式,或者测试的是特殊设备(比如块设备文件),此时
write()会阻塞到DMA完成磁盘传输
验证方法
要确认具体原因,可以做几个小测试:
- 打开文件时加上
O_DIRECT,对比耗时变化,如果耗时进一步增加且线性关系更明显,说明之前可能已经是类似直接IO的场景 - 用
free命令查看系统内存使用情况,看大缓冲区写入时是否出现可用内存骤降(触发缓存刷写) - 用
iostat监控磁盘IO,看write()的耗时是否和磁盘繁忙时间完全对应
内容的提问来源于stack exchange,提问作者Marco
相关产品推荐
相关产品推荐

