macOS Ventura下两次调用ftruncate操作共享内存返回无效参数
macOS Ventura 13.3.1共享内存二次ftruncate失败问题
问题代码
#include <iostream> #include <unistd.h> #include <string.h> #include <sys/mman.h> #include <sys/types.h> #include <fcntl.h> int main() { int memory_object_size = 72; const char* m_shm_name = "/original_mutexx"; shm_unlink(m_shm_name); int firstfd = shm_open(m_shm_name, O_CREAT | O_RDWR, S_IRWXU); // > 0 int res = ftruncate(firstfd, memory_object_size ); if(res != 0) { printf("first object size :%d\n", memory_object_size); printf("first ftruncate error :%s\n", strerror(errno)); } // does nothing // close(firstfd); // works if // shm_unlink(m_shm_name); int secondfd = shm_open(m_shm_name, O_RDWR, S_IRWXU); // > 0 res = ftruncate(secondfd, memory_object_size); if(res != 0) { printf("second object size: %d\n", memory_object_size); printf("second ftruncate error: %s\n", strerror(errno)); } return 1; }
执行输出
second object size: 72 second ftruncate error: Invalid argument
解答
是否属于预期行为?
是,这是macOS共享内存实现的预期行为,属于跨平台机制差异导致的结果。
原因分析
- macOS基于BSD的共享内存实现对
ftruncate有严格约束:当共享内存对象仍被其他打开的文件描述符引用时,无法通过新打开的描述符修改其大小——哪怕是设置为相同值或尝试增大。你的代码中firstfd未关闭,对象仍被持有,因此secondfd调用ftruncate触发EINVAL(无效参数)错误。 - Linux的共享内存机制在这一点上限制更宽松,允许多个打开的描述符存在时修改对象大小,这是两者的核心差异。
解决办法
- 关闭第一个文件描述符后再打开第二个:取消代码中
close(firstfd);的注释 - 直接复用已打开的
firstfd进行大小调整,无需重新打开共享内存 - 若必须重新打开,先通过
shm_unlink销毁原对象(注意此操作会清除已有数据,仅适用于重建场景)
内容的提问来源于stack exchange,提问作者Paltoquet
相关产品推荐
相关产品推荐

