You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux I/O:写入(及读取)的原子性问题咨询

关于文件读写原子性的问题解答

你的write原子性认知是否正确?

你的核心认知是准确的:Linux内核中,单个write()调用写入常规文件时,只要数据大小不超过PIPE_BUF(通常为4KiB),就会被保证是原子操作——内核会将整个写入请求作为一个完整单元执行,不会与其他进程的write()操作产生内容交错。若写入数据超过PIPE_BUF,内核会将其拆分为多个不超过PIPE_BUF的原子块依次执行。

你遇到的乱码问题,根源不在write()的原子性,而是libc的用户态缓冲机制:

  • 当通过bash的>将stdout重定向到文件时,libc对stdout的默认缓冲模式是全缓冲(行缓冲仅针对终端输出场景)。
  • 这意味着printf不会在每次调用后立即触发write(),而是会把输出内容暂存在用户态缓冲区中,直到缓冲区填满、进程退出或手动调用fflush()时,才会一次性调用write()将缓冲区内容写入文件。
  • 两个并发进程的缓冲区内容会被各自的write()批量写入,这些写入的块可能包含多行数据,或者两个进程的缓冲区内容在文件中重叠覆盖,最终导致文件出现乱码,而非你预期的行级交错。

如果要实现每行的原子写入,可以在每次printf后调用fflush(stdout),或者通过setvbuf(stdout, NULL, _IOLBF, 0)将stdout设置为行缓冲模式,这样每行输出都会触发一个独立的write(),从而保证行级原子性。

并发读取的原子性情况

  • 常规文件:read()调用没有类似写入的原子性保证。多个进程并发读取同一文件时,各自的read()会独立移动文件指针,读取当前位置的数据,不会互相阻塞或保证数据块的完整性。比如进程A读取了前100字节,进程B会接着读取后续的100字节,不会出现数据损坏,但也不会像写入那样有原子块的约束。
  • 管道/FIFO:当读取的数据大小不超过PIPE_BUF时,read()是原子的,不会与其他进程的读取操作交错;若读取大小超过PIPE_BUF,则原子性无法保证。

内容的提问来源于stack exchange,提问作者ABu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 17:56:06