C Extending or ctypes in pyinotify

本文回顾了mirrord项目的inotify小文件同步机制,并分析了pyinotify模块的不足之处,包括内存消耗大和映射查找效率低等问题。探讨了pyinotify不同版本的技术差异及ctypes模块直接调用glibc实现inotify功能的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

准备要重构以前的 mirrord 项目,即利用 inotify 做小文件同步,当时的经验还是不够,结构设计上还是太臃肿,用了好几个线程,可靠性也不高。另外,调用了 pyinotify,这个模块的胶合层对于我的需求来说还是太厚,许多功能其实是不需要的,而且,它的 wd(watch id) 和 watch instance(包含 pathname) 之间的映射实际上是内存中的一个 dict,当文件数量比较大的时候,内存消耗也会很大;而且这个映射是单向的,即只能从 wd->pathname,而不能从 pathname->wd,所以,当需要从 pathname 找到 wd 的时候,就需要遍历整个哈希表。例如,其 get_wd 方法如下:

def get_wd(self, path):
    path = os.path.normpath(path)
    for iwd in self._wmd.items():
        if iwd[1].path == path:
            return iwd[0]
        if VERBOSE:
            _print_err('get_wd: unknown path %s' % path)

对比了一下 pyinotify 的最新版本 0.9.0 和以前用过的 0.7.1。在 0.7.1 中,作者使用的是 c extension 方法来使用 Linux 的 inotify 功能,而在 0.9.0 中,则不再使用该方法。读了一下,发现是使用了 ctypes 模块直接调用了 glibc (libc.so.6) 中的 inotify_init() inotify_add_watch() 等函数。

ctypes 是在 Python 2.5 中新增的模块,昨天研究了一下,使用它可以直接调用 library 动态库里面的函数。这可以为我们提供一些简便的 c 扩展的方法:

>>> import ctypes
>>> libc = ctypes.cdll.LoadLibrary("libc.so.6")
>>> print libc
<CDLL 'libc.so.6', handle b808ed38 at b803be4c>
>>> libc = ctypes.CDLL("libc.so.6")
>>> print libc
<DLL 'libc.so.6', handle b808ed38 at b803b98c>
>>> libc.time
<_FuncPtr object at 0xb80537e4>
>>> libc.time(None)
1280294855
>>> libc.inotify_init
<_FuncPtr object at 0xb805391c>

但 ctypes 似乎并不是那么稳定,使用的时候可能会出现一些意想不到的异常。
>>> libc.time(1)
Segmentation fault

所以我考虑在使用的时候还是使用老的方法。可以直接把 pyinotify-0.7.1 中的 inotify.c 拷贝过来直接使用即可。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值