共享内存映射图像数据时,prot_write与map_shared必须同时启用,否则写入不生效;需用双缓冲+原子标志位防撕裂,opencv应直接绑定共享内存指针避免拷贝,/dev/shm空间不足需扩容或预分配。

共享内存映射图像数据时,mmap 的 PROT_WRITE 和 MAP_SHARED 必须同时启用
只设 PROT_READ 或用 MAP_PRIVATE,写入不会同步到另一进程,图像永远是初始值或零。典型现象是发送端改了像素,接收端读出来还是黑图或旧帧。
实操建议:
- 发送端和接收端都用
open()打开同一/dev/shm/xxx文件,再分别调mmap(..., PROT_READ | PROT_WRITE, MAP_SHARED, ...) - 不要用
shm_open()后忘记ftruncate()—— 图像缓冲区大小(如1920*1080*3)必须提前设定,否则mmap失败或映射区域为 0 - 推荐固定格式:RGB24(无 padding)、BGR8(OpenCV 默认),避免跨平台字节序或对齐问题
如何避免图像撕裂?用双缓冲 + 原子标志位控制帧切换
直接往共享内存写一整帧,接收端可能读到“半新半旧”的图像——比如上半部分是第 N 帧,下半部分是第 N+1 帧。这不是并发 bug,而是缺乏同步机制。
实操建议:
- 共享内存头部预留 16 字节:前 4 字节存当前有效帧号(
int32_t),后 4 字节存写入完成标志(int32_t,0=未就绪,1=就绪) - 发送端写完一帧后,先写帧号,再原子写标志位(用
__atomic_store_n(&flag, 1, __ATOMIC_RELEASE)) - 接收端轮询标志位,看到 1 后立即读帧号,若与上次不同才 memcpy 图像数据;读完立刻置标志为 0(
__atomic_store_n(&flag, 0, __ATOMIC_RELAXED))
OpenCV cv::Mat 如何直接绑定共享内存地址?别调 copyTo()
常见错误是把共享内存 memcpy 到本地 cv::Mat,这等于白用共享内存——多一次大块内存拷贝,延迟翻倍。
实操建议:
- 构造
cv::Mat时直接传入共享内存指针:cv::Mat(height, width, CV_8UC3, shm_ptr + header_size) - 确保
shm_ptr是uint8_t*类型,且内存对齐满足 OpenCV 要求(通常 16 字节对齐,mmap默认满足) - 禁止在该
cv::Mat上调用create()或assign(),否则会释放并重新分配内存,脱离共享区域
Linux 下 /dev/shm 空间不足导致 shm_open: No space left on device
默认 /dev/shm 只有 4MB,一张 1080p RGB 图就要约 6MB,连双缓冲都放不下。
实操建议:
- 临时扩容:
sudo mount -o remount,size=512M /dev/shm - 永久生效:在
/etc/fstab中修改对应行,例如shm /dev/shm tmpfs defaults,size=512M 0 0 - 更稳妥的做法是用
posix_fallocate()在shm_open()后预分配空间,避免运行时write()失败
usleep(16667) 控制 60 FPS),并在接收端检查帧号跳变来识别丢帧。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











