使用fcntl锁进行共享mmap协调?
在使用 mmap()
来处理共享内存(比如在Linux或其他类UNIX系统中)时,能否使用 fcntl()
(或者 flock()
或 lockf()
函数)来协调对这块内存的访问呢?
对这个问题的回答似乎表明这样做是可行的。
我想的方案是把共享内存设计成一个进程/页面的映射,以减少锁的竞争。这样,每个进程可以同时处理自己的页面,只有在更新进程/页面映射时才需要获取锁。(从未被占用的页面读取数据时,需要检查一个序列号,复制所需的数据,然后验证这个块的序列号没有改变。)
从概念上讲,每个共享这个文件映射的进程都会执行 mmap()
,找到里面的一个空闲块,获取对进程/页面区域的锁,更新这个区域为自己的分配,释放锁,然后继续进行自己的工作。任何进程都可以搜索过期的映射(使用 kill()
并将信号设为零)并清理进程/页面表映射。
(大致来说,我正在构思一个使用Python在Linux上实现的生产者/消费者处理引擎;我希望这个解决方案能够在BSD和其他编程语言中移植——只要它们支持 mmap()
以及必要的 fcntl()
、flock()
或 lockf()
接口。我也对伪代码感兴趣,想看看如何测量锁的竞争情况以及检测任何同步失败。我知道使用 threading 和 multiprocessing 以及它们各自的 Queue()
对象是实现Python生产者/消费者处理模型最简单的方法。)
1 个回答
我相信锁可以确保互斥访问,但我不确定它们是否能提供内存屏障。看起来跳入内核(像使用fcntl、flock和lockf这些函数)可能会做一些事情,强制内存的读写顺序执行,但我怀疑你能否得到一个确切的保证。我觉得这可能是那种“可能有效”的情况,测试可能会显示它确实有效,但你不会知道它是否总是有效,除非你找到相关的参考资料。
我在C语言中做过类似的事情,但我在共享内存中使用了原子自旋锁。以前你需要写一点内联汇编,但现在gcc有一些内置的操作可以使用:
http://gcc.gnu.org/onlinedocs/gcc/Atomic-Builtins.html
如果你愿意写一个非常简单的Python扩展,你可以封装一下__sync_lock_test_and_set(...)和__sync_lock_release(...)来实现你需要的功能。这些应该是相当可移植的。
我相信也有办法把pthread互斥锁放到共享内存中,但我没有这方面的经验。同样,你需要写一个简单的C扩展才能从Python访问这个功能。