Linux eventfd 的初始值及其在可轮询锁中的应用
问题
eventfd()
是一个在 Linux 2.6.22 版本后新增的系统调用。它的调用方式是
int eventfd(unsigned int initval, int flags);
我正在利用这个调用来构建一个可以在轮询循环中使用的 新光剑Lock
类。
Python 的 Lock
对象一开始是处于未锁定状态的。我的使用方式要求初始值必须是非零的。如果这个值在内部是一个 uint64_t
,
这个对象包含一个由内核维护的无符号 64 位整数 (uint64_t) 计数器。
那么为什么初始值的类型是 unsigned int
呢?
详细说明
如果我使用非零值作为 未锁定 状态的 Lock
,那么释放操作是通过写入来完成的。如果没有进行获取就进行多次释放,这样是错误的,需要失败。这就要求在事件对象的值为非零时,写入操作应该失败。在默认模式下,事件对象会将写入的值累加到 (uint64_t)0xfffffffffffffffe
,然后才会阻止写入调用。为了检测这种情况,我会进行一个非阻塞的写入,试图将值推到这个最大值之上,从而触发这种情况:
如果加法会导致计数器的值超过最大值,那么 write(2) 要么会阻塞,直到对文件描述符执行 read(2),要么在文件描述符被设置为非阻塞时失败,并返回错误 EAGAIN。
1 个回答
1
如果我理解得没错,你是想让这个东西的状态在 0
和 UINT64_MAX-1
之间交替变化,对吧?
最开始的值类型可能只是出于历史原因而存在。一旦使用了这样的接口,就很难再去改变它了。
如果你需要这个值一开始就是 UINT64_MAX-1
,那为什么不先用 eventfd
调用一个 0
的参数,然后紧接着再用 write
写入 UINT64_MAX-1
呢?这样在把文件描述符传给其他人之前就可以完成了:
int ev = eventfd(0, 0);
write(ev, &(uint64_t const){ UINT64_MAX-1 }, sizeof(uint64_t));
(当然,你会加上错误检查的代码,对吧)