kqueue 实现文件操作监控

kqueue

最近接触到一些比较底层的东西,感觉跟操作系统原理结合起来看,理解起来会更容易。

在使用 kevent 的时候遇到了一个很奇怪的问题,在 stackoverflow 上面提了个问题fileno errors when calling kevent function麻烦有知道的可以回答一下

Stackoverflow 上的大神给我了点提示,如果直接使用 fd = open('test').fileno(),确实是可以取得到打开文件的文件描述符,但是文件本身 file object 会因为没有变量引用而被垃圾回收器回收。我试了一下手动关闭垃圾回收器暂时没有成功,但是用变量引用 fileobject 后确实能解决问题。此处还是有疑惑。

在调试 kevent 的时候遇到了很多问题,直接看 Python 的 C 语言源代码或者 PyPy 的源码会一下子清晰很多。

例如在 Python 2.7.10 的 selectmodule.c 中,kqueue_event_init 函数在处理 ident 的时候会首先判断是不是长整形,如果不是长整型,再尝试用 PyObject_AsFileDescriptor 来作为文件描述符赋值。这个函数位于 fileobject.c 中,它会判断我们传入的 ident 中有没有调用 fileno 方法,如果有,就先执行这个方法,然后将返回的文件描述符返回给 kqueue_event_init。

这里在 CPython 中,kqueue 和 kevent 相关的操作通过直接调用系统 API 而成,在 PyPy 中,它通过 RPython 的 Foreign Function Interface 来调用系统 API。


kqueue 是 BSD 系统下的一套消息接口,其基本原理与 epoll 相似,它避免了遍历所有被监控的文件描述符的操作。

我们在 Python 中可以使用 select 库调用系统接口来实现 kqueue,它有一个 kevent 对象和一个 kqueue 对象,参见参考资料。

import select

fd = open('test')
kq = select.kqueue()

# 规定我们所要做的操作,分别为 添加事件,使能该事件,事件被取出后恢复标记
flags = select.KQ_EV_ADD | select.KQ_EV_ENABLE | select.KQ_EV_CLEAR

# 要监控的事件类型,分别为 删除,写入,追加写入,重命名
fflags = select.KQ_NOTE_DELETE | select.KQ_NOTE_WRITE | select.KQ_NOTE_EXTEND \
         | select.KQ_NOTE_RENAME
# 初始化该事件
ev = select.kevent(fd, filter=select.KQ_FILTER_VNODE, flags=flags, fflags=fflags)

while 1:
    # 将上述事件加入到 kqueue 中,此时程序被阻塞,直到事件发生,或者我们可以设置 timeout 字段
    revents = kq.control([ev], 1, None)
    # 取出返回的事件
    for e in revents:
        # 如果是 EXTEND 事件,下同
        if e.fflags & select.KQ_NOTE_EXTEND:
        # 打印 EXTEND,下同
            print 'extend'
        elif e.fflags & select.KQ_NOTE_WRITE:
            print 'write'
        elif e.fflags & select.KQ_NOTE_RENAME:
            print 'rename'
        elif e.fflags & select.KQ_NOTE_DELETE:
            print 'delete'
        else:
            print e


监控文件系统有个很著名的 watchdog 库,它在 linux 上采用了 inotify,在 MAC 上除了 kqueue 以外还可用 FSEvents 来监控。

inotify 和 FSEvent 都是专门用于监控文件系统的,能监控的文件操作类型更多,而 epoll 和 kqueue 除了文件系统之外,还可以监控 sockets 或者其他的 I/O。详见 Difference between inotify and epoll。

参考资料

  1. select — Waiting for I/O completion

  2. epoll 或者 kqueue 的原理是什么?

  3. KQUEUE(2)

  4. errno.h

  5. watchdog 0.8.3

  6. Difference between inotify and epoll

转载于:https://my.oschina.net/shinedev/blog/501795

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值