什么是 eventfd ?
eventfd 是 Linux 的一個(gè)系統(tǒng)調(diào)用,創(chuàng)建一個(gè)文件描述符用于事件通知,自 Linux 2.6.22 以后開始支持。
接口及參數(shù)介紹
#include <sys/eventfd.h>
int eventfd(unsigned int initval, int flags);
eventfd() 創(chuàng)建一個(gè) eventfd 對(duì)象,可以由用戶空間應(yīng)用程序?qū)崿F(xiàn)事件等待/通知機(jī)制,或由內(nèi)核通知用戶空間應(yīng)用程序事件。
該對(duì)象包含了由內(nèi)核維護(hù)的無符號(hào)64位整數(shù)計(jì)數(shù)器 count 。使用參數(shù) initval 初始化此計(jì)數(shù)器。
struct eventfd_ctx {
struct kref kref;
wait_queue_head_t wqh;
/*
* Every time that a write(2) is performed on an eventfd, the
* value of the __u64 being written is added to "count" and a
* wakeup is performed on "wqh". A read(2) will return the "count"
* value to userspace, and will reset "count" to zero. The kernel
* side eventfd_signal() also, adds to the "count" counter and
* issue a wakeup.
*/
__u64 count;
unsigned int flags;
};
flags 可以是以下值的 OR 運(yùn)算結(jié)果,用以改變 eventfd 的行為。
- EFD_CLOEXEC (since Linux 2.6.27)
文件被設(shè)置成 O_CLOEXEC,創(chuàng)建子進(jìn)程 (fork) 時(shí)不繼承父進(jìn)程的文件描述符。 - EFD_NONBLOCK (since Linux 2.6.27)
文件被設(shè)置成 O_NONBLOCK,執(zhí)行 read / write 操作時(shí),不會(huì)阻塞。 - EFD_SEMAPHORE (since Linux 2.6.30)
提供類似信號(hào)量語(yǔ)義的 read 操作,簡(jiǎn)單說就是計(jì)數(shù)值 count 遞減 1。
在 Linux 2.6.26 版本之前,沒有使用參數(shù) flags,必須指定為 0。
操作方法
一切皆為文件是 Linux 內(nèi)核設(shè)計(jì)的一種高度抽象,eventfd 的實(shí)現(xiàn)也不例外,我們可以使用操作文件的方法操作 eventfd。
- read(): 讀取 count 值后置 0。如果設(shè)置 EFD_SEMAPHORE,讀到的值為 1,同時(shí) count 值遞減 1。
- write(): 其實(shí)是執(zhí)行 add 操作,累加 count 值。
- epoll()/poll()/select(): 支持 IO 多路復(fù)用操作。
- close(): 關(guān)閉文件描述符,eventfd 對(duì)象引用計(jì)數(shù)減 1,若減為 0,則釋放 eventfd 對(duì)象資源。
使用場(chǎng)景
在 pipe 僅用于發(fā)出事件信號(hào)的所有情況下,都可以使用 eventfd 取而代之。