You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;
}

关键修改点说明

  1. 调用ftruncate设置共享内存的大小,这是MacOS下必须的步骤,否则无法进行后续映射操作。
  2. 使用mmap将共享内存区域映射到进程的地址空间,通过内存指针shm_ptr来完成读写(用memcpy代替write/read)。
  3. 程序结束时调用munmap解除映射,shm_unlink删除共享内存对象,避免资源泄漏。

内容的提问来源于stack exchange,提问作者Aidan Steele

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 14:00:47