执行mmap并关闭fd后文件仍持有flock锁的原因是什么?
核心原理说明
flock锁的绑定对象是open file description(打开文件描述),而非用户态的文件描述符fd,也不是文件inode本身,认知偏差核心是混淆了这几个实体的关系。
- mmap的额外引用持有对象就是
open file description,调用close(fd)仅释放了当前进程持有的fd句柄,只要MAP_SHARED类型的映射还存在,open file description的内核引用计数就不会降到0,对应的实体不会被销毁,绑定在其上的flock锁自然不会释放。 - 该行为和flock手册描述完全不冲突:手册中“所有文件描述符关闭即释放锁”的表述默认前提是不存在其他内核态引用持有该
open file description,mmap映射就是典型的内核态持有场景,不属于手册描述的常规场景。
平台差异与规范符合性
- 当前主流类Unix系统(Linux、FreeBSD、macOS等)的行为均和测试结果一致:mmap映射存续期间,对应
open file description不会销毁,flock锁持续有效。 - 仅部分已淘汰的老旧System V衍生系统存在不同行为,无实际兼容价值。
- 现有主流实现完全符合POSIX规范:规范明确要求mmap会增加对应
open file description的引用计数,flock锁绑定到open file description直到其销毁,“close(fd)即放锁”的认知属于对手册的片面解读。
验证方案
可以调整测试代码,将munmap调用移到close(fd)之后、pause()之前执行,重新运行测试即可看到第二个进程可以正常拿到锁,刚好验证上述逻辑。
// 调整后的代码片段示例 // This block if (true) { close(fd); fd = -1; } // 新增munmap调用,主动释放mmap引用 if (m != NULL) { munmap(m, M_SIZE); m = NULL; } fprintf(stderr, "Lock holding ...\n"); pause();
内容的提问来源于stack exchange,提问作者David Timber
相关产品推荐
相关产品推荐

