跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

C++怎么使用命名管道_C++进程间通信IPC【通信】

命名管道跨平台开发需注意:Windows用CreateNamedPipe需正确设置dwOpenMode和dwPipeMode,Linux用mkfifo需避免O_RDWR竞态;读写应合理分包并统一消息边界处理。 Windows 上用
CreateNamedPipe
创建服务端管道 命名管道在 Windows 是同步阻塞 I/O 模型,服务端必须先创建、等待连接,客户端才能连上。直接调用
CreateNamedPipe
是最可控的方式,比封装库更易调试。 常见错误是没设对
dwOpenMode
:比如用了
PIPE_ACCESS_DUPLEX
却没配
PIPE_TYPE_MESSAGE
,结果读写行为不一致;或者
nMaxInstances
设成 1,第二个客户端直接
ERROR_PIPE_BUSY
被拒。
lpName
必须是
\\.\pipe\xxx
格式,开头双反斜杠不能少,否则
CreateNamedPipe
返回
INVALID_HANDLE_VALUE
建议设
dwPipeMode = PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT
,避免字节流粘包问题
ConnectNamedPipe
在阻塞模式下会挂起线程,别在 UI 线程里直接调,容易卡死 Linux 上用
mkfifo
+
open
模拟命名管道 Linux 没有原生“命名管道服务端/客户端”概念,
mkfifo
创建的是一个特殊文件,靠
open
的阻塞语义来同步——一端
open(O_WRONLY)
会等另一端
open(O_RDONLY)
才返回。 典型坑是两端都用
O_RDWR
:Linux 允许,但行为不可靠,某些内核版本下
read
可能永远返回 0;还有人忘了
mkfifo
后要检查
errno == EEXIST
,重复创建导致失败。 立即学习 “ C++免费学习笔记(深入) ”;
mkfifo("/tmp/my_pipe", 0666)
后,权限可能被 umask 截断,建议后续用
chmod
补全 服务端应先
open(O_RDONLY | O_NONBLOCK)
尝试打开,再
open(O_WRONLY)
触发阻塞,避免竞态 不要用
fscanf
读命名管道——遇到 EOF(对方关闭)会直接失败,改用
read
判断返回值
WriteFile
和
read
的缓冲区大小不是越小越好 Windows 下
WriteFile
发送小块数据(比如每次 1 字节),会触发大量系统调用和上下文切换;Linux 下
read
用太小的缓冲区(如 1 字节),同样效率极低,还可能因管道缓冲区满而阻塞。 C知道 CSDN推出的一款AI技术问答工具 下载 命名管道本身有内建缓冲(Windows 默认 64KB,Linux
PIPE_BUF
通常是 4KB),但应用层仍需合理分包。消息边界不等于 TCP 那种“自动分帧”,得自己处理。 Windows 推荐单次
WriteFile
不超过 64KB,大于这个值会被拆包,且不保证原子性 Linux 下若用
PIPE_TYPE_MESSAGE
类似语义,得自己加长度头或分隔符,不然
read
可能只读到半条消息 跨平台代码别假设
sizeof(size_t)
一致,长度字段统一用
uint32_t
更安全 客户端连不上时先查
GetLastError()
或
errno
连不上不一定是代码逻辑错,更多是环境或权限问题。Windows 下
ERROR_FILE_NOT_FOUND
往往是管道名拼错或服务端根本没启动;
ERROR_ACCESS_DENIED
多半是 UAC 权限或服务端用
SECURITY_DESCRIPTOR
限制了访问。 Linux 下
errno == ENXIO
表示服务端已关闭或未
open
读端;
EAGAIN
是非阻塞模式下暂时无数据,不是错误。 Windows 客户端用
CreateFile
连接时,
dwDesiredAccess
必须和服务端
dwOpenMode
匹配,比如服务端是
GENERIC_READ
,客户端就不能只请求
GENERIC_WRITE
Linux 下
ls -l /tmp/my_pipe
看权限位,如果显示
prw-------
,其他用户进程根本打不开 调试时用
Process Explorer
(Win)或
lsof | grep pipe
(Linux)确认句柄是否真被占用 命名管道最难的不是写通,而是两边对“消息结束”的理解是否一致。别依赖底层自动切分,老老实实加长度头或换行符——这点比选 API 更关键。

相关文章