windows用createnamedpipe创建内核级命名管道,需handle+readfile/writefile操作,路径为.pipexxx;linux用mkfifo创建posix fifo文件节点,通过open阻塞同步,不支持o_rdwr。

Windows下用CreateNamedPipe创建服务端管道
命名管道在Windows里是内核对象,得用WinAPI那一套。服务端必须先调用 CreateNamedPipe,不能直接用fopen或open——那是文件,不是命名管道。
-
CreateNamedPipe返回的是HANDLE,后续读写得用ReadFile/WriteFile,不是fread/fwrite - 管道名格式固定为
\\.\pipe\xxx,开头四个反斜杠不能少,少一个就返回INVALID_HANDLE_VALUE - 注意
dwOpenMode参数:服务端通常设PIPE_ACCESS_DUPLEX,客户端连上来才能双向通信;如果只设PIPE_ACCESS_INBOUND,客户端一发数据就断连 - 阻塞模式下,
CreateNamedPipe会等客户端调用CreateFile连接后才返回;想非阻塞得配PIPE_NOWAIT,但得自己轮询ConnectNamedPipe
Linux下用mkfifo创建FIFO文件节点
Linux没“命名管道”这个独立概念,只有POSIX FIFO,本质是带特殊权限的文件节点,路径行为和普通文件一致,但读写语义不同。
- 先用
mkfifo命令或mkfifo()系统调用创建节点,比如mkfifo /tmp/my_pipe;不创建就直接open会失败 - 服务端必须先
open(..., O_RDONLY)(或O_WRONLY),且该调用会阻塞,直到有另一端以相反模式打开——这点和Windows的CreateNamedPipe等待逻辑类似,但触发时机不同 - FIFO不支持
O_RDWR模式,哪怕你只是想测试;Linux内核禁止这种打开方式,open直接返回 -1,errno是EINVAL - 一旦任一端关闭,另一端继续读会得到0字节(EOF),写则触发
SIGPIPE或返回 -1(errno=EBADF),得提前处理
跨平台收发数据时的缓冲与同步问题
两边都用字节流接口,但底层实现差异会导致行为不一致,尤其在小数据、多客户端或快速断连场景下。
- Windows管道默认有4KB内核缓冲区,Linux FIFO缓冲区大小由系统决定(通常是64KB),但实际可用量受两端打开顺序和阻塞状态影响极大
- Windows上多次
WriteFile可能被合并成一次到达,Linux下write小于PIPE_BUF(通常4096)是原子的,大于则可能拆包——别假设“一次write对应一次read” - 客户端连接后,Windows需显式调用
ConnectNamedPipe(服务端)和CreateFile(客户端);Linux只需按序open,但顺序错会导致死锁:比如服务端先open(O_WRONLY),客户端再open(O_RDONLY),服务端就卡住 - 务必设置超时:Windows用
SetNamedPipeHandleState配PIPE_READMODE_MESSAGE+PIPE_WAIT控制读行为;Linux用alarm()或select()防止read永久阻塞
错误码和调试关键点
管道出问题往往静默失败,靠返回值和errno/GetLastError()定位最直接。
立即学习“C++免费学习笔记(深入)”;
- Windows常见错误:
ERROR_PIPE_BUSY(客户端连太快,服务端还没调ConnectNamedPipe)、ERROR_NO_DATA(对方已断开但你还想ReadFile)、ERROR_BROKEN_PIPE(对方close了写端) - Linux常见错误:
ENXIO(服务端还没open就读)、EAGAIN(非阻塞模式下无数据可读)、EPIPE(写端已关闭还写) - 调试时优先检查:管道名/路径是否存在、权限是否足够(Linux下
chmod影响open)、两端打开模式是否匹配(读/写方向、阻塞/非阻塞)、是否遗漏CloseHandle或close导致句柄泄漏 - 别依赖
std::ofstream或FILE*封装——它们内部缓冲机制会打乱管道的实时性,直接用底层句柄或fd操作更可控
跨平台管道最难的不是语法,而是对“连接建立时机”和“数据边界消失”的适应。Windows等客户端上门,Linux靠打开顺序隐式同步,两边对“断连”的反应也完全不同。写完别急着测功能,先用最简case跑通两端生命周期管理——建、连、读、写、关,漏一步就卡死。










