Windows命名管道需设PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED实现异步收发,Linux FIFO无内置双向支持,应改用socketpair(AF_UNIX, SOCK_STREAM)替代。

Windows 上用 CreateNamedPipe 建管道服务端
命名管道在 Windows 是内建 IPC 机制,服务端必须先创建管道实例,等待客户端连接。关键点不是“怎么连”,而是“怎么持续收发”——CreateNamedPipe 返回的句柄默认是同步阻塞的,如果没配好标志位,ConnectNamedPipe 可能直接返回失败而不是挂起等待。
实操建议:
- 必须设
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED才能异步读写;若只用同步模式,ConnectNamedPipe调用后要立刻ReadFile/WriteFile,否则客户端可能因超时断开 -
nMaxInstances设为PIPE_UNLIMITED_INSTANCES看似方便,但实际会受系统限制(通常最多 254),更稳妥的是设具体数字,比如 10 - 安全描述符不能传
NULL,否则默认只允许 SYSTEM 访问;用SECURITY_DESCRIPTOR+InitializeSecurityDescriptor配最低权限(如仅允许当前用户)
客户端用 CreateFile 连接时常见错误
很多人卡在 CreateFile 返回 INVALID_HANDLE_VALUE,错误码却是 ERROR_PIPE_BUSY 或 ERROR_FILE_NOT_FOUND——这不是代码写错了,而是服务端还没调用 ConnectNamedPipe,或管道名拼错(注意前缀必须是 \\.\pipe\,少一个反斜杠就失败)。
实操建议:
- 连接前先用
WaitNamedPipe等待服务端就绪,避免轮询或盲目重试;超时设 5000ms 比较合理 - 打开模式必须是
GENERIC_READ | GENERIC_WRITE,哪怕只读也要写权限,否则ERROR_ACCESS_DENIED - 如果服务端用
FILE_FLAG_FIRST_PIPE_INSTANCE,客户端首次连接成功后,后续CreateFile会失败,得让服务端主动创建新实例
读写数据必须处理 ERROR_MORE_DATA 和缓冲区边界
ReadFile 在消息模式(PIPE_TYPE_MESSAGE)下,一次调用要么读完整条消息,要么返回 ERROR_MORE_DATA 表示消息太长——但这个错误只在同步模式下触发;异步模式下它根本不会返回该错误,而是直接截断。
实操建议:
- 服务端创建时设
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE,客户端也得匹配,否则消息边界丢失 - 读取前务必用
PeekNamedPipe查看可用字节数,避免分配过小缓冲区导致ERROR_INSUFFICIENT_BUFFER - 写入超过 65535 字节的消息会被截断,且不报错;拆成多段写并加自定义长度头更可靠
Linux 不支持命名管道(FIFO)跨进程双向通信?
Linux 的 mkfifo 创建的是单向 FIFO,本质是特殊文件,没有 Windows 那种“实例管理”和“消息模式”。两个进程想全双工通信,得建两个 FIFO(一读一写),还得自己协调打开顺序,否则容易死锁。
实操建议:
- 不要试图用同一个 FIFO 同时
open(O_RDWR)实现双向——POSIX 标准不保证行为,glibc 可能阻塞,musl 直接失败 - 用
socketpair(AF_UNIX, SOCK_STREAM, 0, fd)替代,它天然双向、无缓冲区大小限制、支持select,比 FIFO 更接近 Windows 命名管道语义 - 如果必须用 FIFO,服务端先
open(..., O_RDONLY)阻塞等客户端,客户端再open(..., O_WRONLY)触发服务端返回,之后双方各开一个写 FIFO 专门发数据
真正麻烦的不是 API 调用,是状态同步:Windows 管道有明确的“连接/断开”事件,Linux FIFO 没有,一端崩溃另一端可能永远卡在 read 上。加心跳或用 signalfd 监控对端退出更稳妥。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











