eventfd epoll 消費者執行緒池

2021-09-26 02:29:40 字數 2580 閱讀 8934

在linux系統中,eventfd 是乙個用來通知事件的檔案描述符,timerfd 是定時器事件的檔案描述符。二者都是核心向使用者空間的應用傳送通知的機制,可以有效地被用來實現使用者空間的事件/通知驅動的應用程式。

簡而言之,就是 eventfd 用來觸發事件通知,timerfd 用來觸發將來的事件通知。

當僅用於實現訊號通知的功能時,eventfd() 完全可以替代 pipe(),對於核心來說,eventfd 的開銷更低,消耗的檔案描述符數目更少(eventfd 只占用乙個描述符,而 pipe 則需要兩個)。

eventfd 的兩個核心操作

read()

消費者需要對訊號量進行 down 操作時,呼叫 read 從 eventfd 讀即可。read返回值:

如果當前 counter > 0,那麼 read 返回 counter 值,並重置 counter 為0;

如果當前 counter 等於0,那麼 read 阻塞直到 counter 大於0;如果設定了nonblock,那麼返回-1,並設定 errno 為eagain。

可以看到,eventfd 實現的資源是一次性消耗品,只允許一次 read。

write()

生產者需要執行 up 操作時,呼叫 write 寫乙個 64bit 的整數 value 到 eventfd 即可。write 返回值:

counter 最大能儲存的值是 0xffff ffff ffff fffe(以max表示此值),那麼 write 嘗試將 value 加到 counter上,如果結果超過 max,那麼 write 一直阻塞直到有 read 操作發生,或者返回-1並設定 errno 為 eagain。

所以 write 可以多次連續呼叫,但 read 讀一次即可清零。實質上它應該是乙個二元訊號量,只有0和非0兩種狀態。但是應用程式也可以利用 counter 的值實現自己的邏輯,比如每次 write 都加 1,那麼 read 就能夠知道在兩次呼叫之間有多少次 write 操作發生,也就表示對應的事件發生了多少次。

消費者

消費者執行緒池中的執行緒和生產者共用乙個 epoll 物件,每個消費者執行緒並行地進行針對 eventfd 或 timerfd 觸發的事件迴圈的輪詢。如果是讀事件,且事件 id 為註冊過的 eventfd 或 timerfd,則進行相應的處理。然後執行 eventfd/timerfd 的 read() 操作(相當於 down),並登出執行完的 eventfd 或 timerfd。

建立消費者執行緒池:

class eventpool(object):

def __init__(self, name, num_threads=4):

super(eventpool, self).__init__()

self.name = name

self._epoll = select.epoll()

self._events = {}

for _ in range(num_threads):

w = epollthread(self.name, self._epoll, self._events, self._attach_event)

w.start()

消費者執行緒執行:

def run(self):

while true:

events = self._epoll.poll(1)

for fd, event in events:

if fd in self._events and event & select.epollin:

self._exec_handler(self._events[fd])

self._events[fd]['fd'].read()

self._events.pop(fd)

生產者建立 eventfd/timerfd 並在 epoll 物件中註冊事件,然後執行 eventfd/timerfd 的 write() 操作(相當於 up)。

if expire is not none:

tfd = timerfd()

v = max(1e-3, expire)

self._epoll.register(tfd.get_fd(), select.epollin | select.epollet)

_add_event(tfd, msg)

tfd.set_time(v)

else:

efd = eventfd()

self._epoll.register(efd.get_fd(), select.epollin | select.epollet)

_add_event(efd, msg)

efd.write()

參考

讓事件飛 ——linux eventfd 原理與實踐

worker pool with eventfd

eventfd 函式使用介紹

生產消費者

producer consumer model include include define buffer size 100 緩衝區數量 define max seq 200 define n consumer 10 消費者數量 define n producer 3 生產者數量 define t ...

生產者消費者 生產者與消費者模式

一 什麼是生產者與消費者模式 其實生產者與消費者模式就是乙個多執行緒併發協作的模式,在這個模式中呢,一部分執行緒被用於去生產資料,另一部分執行緒去處理資料,於是便有了形象的生產者與消費者了。而為了更好的優化生產者與消費者的關係,便設立乙個緩衝區,也就相當於乙個資料倉儲,當生產者生產資料時鎖住倉庫,不...

生成者消費者問題

自己實踐的 生成者消費者問題 public class threaddemo 生產者 class producer implements runnable public void run 消費者 class consumer implements runnable public void run c...