MacOS Monterey下shm_open打开的文件描述符无法写入求助
shm_open打开的文件描述符在MacOS上无法执行write操作的问题
以下代码在Linux上可通过shm_open获取的文件描述符正常执行读写,但在MacOS Monterey 12.5上运行时会触发write()失败,错误信息为Device not configured (6):
#include <stdio.h> #include <stdlib.h> #include <sys/mman.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <string.h> int main(int argc, const char * argv[]) { int fd = shm_open("/example", O_CREAT|O_RDWR, S_IRUSR|S_IWUSR); if (fd < 0) { printf("shm_open() failed %s (%d)\n", strerror(errno), errno); return 1; } const char *buf = "hello world"; unsigned long len = strlen(buf); ssize_t ret = write(fd, buf, len); if (ret < 0) { printf("write() failed %s (%d)\n", strerror(errno), errno); return 1; } ret = lseek(fd, 0, SEEK_SET); if (ret < 0) { printf("lseek() failed %s (%d)\n", strerror(errno), errno); return 1; } char *newbuf = calloc(len + 1, 1); ret = read(fd, newbuf, len); if (ret < 0) { printf("read() failed %s (%d)\n", strerror(errno), errno); return 1; } printf("read: %s\n", newbuf); return 0; }
运行结果对比
- Linux下正常输出:
$ cc main.c $ ./a.out read: hello world
- MacOS下报错:
$ cc main.c $ ./a.out write() failed Device not configured (6)
问题原因
MacOS的POSIX共享内存实现和Linux存在差异:Linux允许直接对shm_open返回的文件描述符执行write/read,但MacOS不支持这种操作。MacOS要求必须先通过ftruncate设置共享内存区域的大小,再将其映射到进程地址空间,通过内存指针来完成读写操作。
修正后的代码
#include <stdio.h> #include <stdlib.h> #include <sys/mman.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <string.h> int main(int argc, const char * argv[]) { int fd = shm_open("/example", O_CREAT|O_RDWR, S_IRUSR|S_IWUSR); if (fd < 0) { printf("shm_open() failed %s (%d)\n", strerror(errno), errno); return 1; } const char *buf = "hello world"; unsigned long len = strlen(buf); // 关键:先设置共享内存的大小 if (ftruncate(fd, len) < 0) { printf("ftruncate() failed %s (%d)\n", strerror(errno), errno); close(fd); shm_unlink("/example"); return 1; } // 将共享内存映射到进程地址空间 char *shm_ptr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (shm_ptr == MAP_FAILED) { printf("mmap() failed %s (%d)\n", strerror(errno), errno); close(fd); shm_unlink("/example"); return 1; } // 通过内存指针写入数据 memcpy(shm_ptr, buf, len); // 通过内存指针读取数据 char *newbuf = calloc(len + 1, 1); memcpy(newbuf, shm_ptr, len); printf("read: %s\n", newbuf); // 清理资源 munmap(shm_ptr, len); close(fd); shm_unlink("/example"); // 不再需要时删除共享内存对象 free(newbuf); return 0; }
关键修改点说明
- 调用
ftruncate设置共享内存的大小,这是MacOS下必须的步骤,否则无法进行后续映射操作。 - 使用
mmap将共享内存区域映射到进程的地址空间,通过内存指针shm_ptr来完成读写(用memcpy代替write/read)。 - 程序结束时调用
munmap解除映射,shm_unlink删除共享内存对象,避免资源泄漏。
内容的提问来源于stack exchange,提问作者Aidan Steele
相关产品推荐
相关产品推荐

