pipe()必须在fork()前调用,以使子进程继承fd[0](读端)和fd[1](写端);父子进程需各自关闭不使用的端口,否则read()会因写端未彻底关闭而持续阻塞。

用 pipe() 做父子进程通信最简单
如果只是父子进程间传少量数据,pipe() 是开销最小、最不容易出错的选择。它返回一对文件描述符:fd[0] 读端,fd[1] 写端。调用后必须 fork(),子进程继承这两个 fd,再按需 close() 不用的一端。
常见错误是忘了关掉不用的 fd —— 比如子进程只读,却没关 fd[1],那父进程写完 close(fd[1]) 后,子进程 read() 还会一直阻塞,因为内核认为“写端可能还有别的进程开着”。
实操建议:
- 父进程写完立即
close(fd[1]),子进程读完立即close(fd[0]) - 读端关闭后,
read()返回 0;写端关闭后,read()不再阻塞 -
pipe()是字节流,无消息边界,应用层需自己处理分包(比如加长度头或换行符)
跨无关进程用 named pipe(FIFO)
mkfifo() 创建的命名管道允许不相关的进程通过路径名访问,本质仍是单向字节流,但不再依赖 fork 关系。
注意点比匿名 pipe 多:
- 必须先
mkfifo("/tmp/myfifo", 0666)创建,再分别open();若顺序反了,open(O_RDONLY)会阻塞直到有写端打开 -
open(O_WRONLY)在没有读端时会失败(返回 -1),得用open(O_WRONLY | O_NONBLOCK)避免卡住 - FIFO 文件权限受 umask 影响,
chmod()可后续调整,但创建时权限位会被截断 - 不要用
fseek()或lseek()—— FIFO 不支持随机访问
需要双向、低延迟就选 Unix domain socket
比 FIFO 更灵活:支持双向通信、SOCK_STREAM(可靠字节流)或 SOCK_DGRAM(无连接报文),且能传递文件描述符(用 SCM_RIGHTS 控制消息),这是 pipe 和 FIFO 做不到的。
典型坑:
- bind() 前必须
unlink()已存在的 socket 路径,否则bind()失败(Address already in use) - 路径长度受限(Linux 一般 108 字节),太长会触发
ENAMETOOLONG - 客户端 connect() 时服务端还没 listen(),会报
Connection refused;服务端应先 bind+listen,再启客户端 - sendmsg()/recvmsg() 传 fd 时,控制消息结构体要对齐,
CMSG_FIRSTHDR()和CMSG_NXTHDR()必须配合使用
shm_open() + mmap() 共享内存最快,但同步得自己管
共享内存是 IPC 中吞吐最高的方式,适合大数据量、高频交换场景(比如音视频帧传输)。shm_open() 创建 POSIX 共享内存对象,mmap() 映射到进程地址空间。
关键提醒:
-
shm_open()的 name 必须以/开头(如"/my_shm"),不能含其它/,否则失败 - 映射后内存内容不会自动清零,首次使用前建议
memset()或用MAP_SHARED | MAP_ANONYMOUS组合(仅限 Linux) - 没有内置同步机制 —— 你得配
pthread_mutex_t放在共享区内,或额外用sem_open()信号量 - 进程退出不自动销毁 shm 对象,必须显式
shm_unlink(),否则残留 /dev/shm/ 下
共享内存快是真的快,但错一个同步点就可能读到脏数据,调试起来比 socket 难得多 —— 尤其多线程同时访问时,连 std::atomic 都得确认是否 lock-free 且跨进程有效。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











