C语言如何批量写入多组值到FIFO管道避免读取端提前读取
解决方案
方案1:使用writev系统调用实现原子批量写入(优先推荐)
这是最适配你场景的方案,不需要手动申请堆内存、拷贝数据,完全规避堆损坏风险:
writev支持直接传入多个分散的内存地址和对应长度,内核会在内核态把所有数据一次性写入管道- 只要你3个结构体的总大小不超过系统定义的
PIPE_BUF(Linux下默认是4096字节,POSIX要求至少为512字节),写入操作是原子性的,内核不会在写入过程中调度切换,对端只会读到完整的全部数据
示例代码:
#include <sys/uio.h> struct iovec iov[3]; iov[0].iov_base = struct_1; iov[0].iov_len = sizeof(struct part_1); iov[1].iov_base = struct_2; iov[1].iov_len = sizeof(struct part_2); iov[2].iov_base = struct_3; iov[2].iov_len = sizeof(struct part_3); ssize_t written = writev(out_fd, iov, 3); // 后续判断written是否等于总长度做异常处理即可
方案2:数据帧格式约定(适配数据总大小超过PIPE_BUF的场景)
如果你的三个结构体总大小超过PIPE_BUF,无法保证单次写入原子性,可以修改读写两端的通信协议:
- 写入端在发送实际数据前,先写入一个固定长度的头部,标记本次完整数据的总长度
- 读取端先读取头部拿到总长度,再循环读取直到凑够对应长度的字节后再做业务处理,不会因为读到部分数据就执行逻辑
这个方案和写入端是否分批写无关,完全避免半包处理异常。
方案3:进程间同步机制
如果不方便修改通信协议,可以在读写两端加进程间同步锁:
- 写入端获取锁之后再执行三次write操作,全部写完后释放锁
- 读取端只有获取到锁之后才执行读取操作,读完立刻释放锁
可选的同步工具包括POSIX信号量、文件锁等。
内容的提问来源于stack exchange,提问作者Achmed
相关产品推荐
相关产品推荐

