Linux下使用epoll監聽定時器

2021-10-02 06:53:20 字數 3669 閱讀 6436

本文主要講述如何使用epoll來監聽timerfd系列函式建立的定時器,關於timerfd系列函式的使用請看這篇文章。

epoll_create()或epoll_create1():建立乙個epoll物件,並返回乙個檔案描述符指向這個epoll物件

epoll_ctl():新增想要監聽的檔案描述符

epoll_wait():等待i/o事件的發生,如果沒有事件發生就會阻塞呼叫執行緒

這3個api的原型如下,

#include

intepoll_create

(int size)

;// 舊版,size取值必須大於0

intepoll_create1

(int flags)

;// 新版,flags可以是0,或者epoll_cloexec

intepoll_ctl

(int epfd,

int op,

int fd,

struct epoll_event *event)

;int

epoll_wait

(int epfd,

struct epoll_event *events,

int maxevents,

int timeout)

;

關鍵結構體是struct epoll_event,其定義如下,

struct epoll_event 

;typedef

union epoll_data epoll_data_t;

edge-triggered和level-triggered

epoll api可以使用edge-triggered或level-triggered的方式來監聽檔案描述符,可以翻譯為邊沿觸發和電平觸發,學過數位電路的比較好理解,如下圖

綠色的部分屬於電平觸發,當處於高電平或低電平時就會觸發;橘黃色屬於邊沿觸發,當電平發生由高變到低或者由低變成高就會觸發。

這裡再使用linux man手冊裡舉的例子來解釋一下,現在有乙個pipe,用於2個程序間進行通訊,乙個程序負責讀,另外的程序負責寫。操作如下,

讀程序把pipe對應的檔案描述符rfd新增到epoll裡進行監聽

寫程序往pipe裡寫了2kb的資料

讀程序裡的epoll_wait監聽到有資料進來,把rfd作為ready的描述符返回

讀程序通過rfd讀取1kb資料

epoll_wait繼續監聽rfd

如果在第1步裡使用的是邊沿觸發的方式監聽rfd,那麼第5步裡的epoll_wait就不會再把rfd作為ready的描述符返回,這樣讀程序就無法讀取剩餘的1kb資料了。如果使用的是電平觸發,就可以繼續讀取剩餘1kb資料,這是為什麼?

對於讀程序來說,初始時,buffer為空,可以看做電平為0狀態,當寫程序寫入資料後,buffer裡就會有資料,這樣buffer狀態發生變化,此時可以看做是電平1的狀態,這樣就發生了電平由0到1的變化,如果採用的是邊沿觸發,就會觸發,rfd就會作為ready的描述符返回。但是一次並沒有讀取完,buffer裡還有剩餘資料,那麼此時還是處於電平1狀態,這樣的話再次epoll_wait就不會觸發,因為電平狀態沒有發生變化。

但是如果使用電平觸發,buffer裡有資料就觸發,即電平為1就觸發,那麼當buffer由空變成有資料狀態,就會觸發,而且一次沒讀完,再次進入epoll_wait時還會觸發,直到把資料讀完,buffer變成空,就不再觸發了。

epoll預設使用電平觸發。

原始碼如下,

#include

#include

#include

#include

#include

#include

#include

#define handle_error(msg) \

do while (0)

void

print_elapsed_time

(void);

intmain

(void

)struct itimerspec new_value =

; new_value.it_value.tv_sec =1;

// 第一次1s到期

new_value.it_value.tv_nsec =0;

new_value.it_interval.tv_sec =5;

// 後續週期是5s cycle

new_value.it_interval.tv_nsec =0;

if(timerfd_settime

(timerfd,0,

&new_value,

null)==

-1)print_elapsed_time()

;printf

("timer started\n");

int epollfd =

epoll_create1

(epoll_cloexec)

;// or epoll_create(1)

if(epollfd ==-1

)struct epoll_event ev;

ev.events = epollin;

// 表示該檔案描述符可以讀的時候就觸發

ev.data.fd = timerfd;

epoll_ctl

(epollfd, epoll_ctl_add, timerfd,

&ev)

;const

int maxevents =5;

// 也可以設定為1

struct epoll_event events[maxevents]

;while(1

)print_elapsed_time()

;}}}

}return0;

}void

print_elapsed_time

(void);

static

int first_call =1;

if(first_call ==1)

}struct timeval current =;if

(gettimeofday

(¤t,

null)==

-1)static

int old_secs =

0, old_usecs =0;

int secs = current.tv_sec - start.tv_sec;

int usecs = current.tv_usec - start.tv_usec;

if(usecs <0)

usecs =

(usecs +

500)

/1000

;// 四捨五入

if(secs != old_secs || usecs != old_usecs)

}

比較關鍵的地方就是epollin這個引數,表示當檔案描述符可讀的時候觸發,這裡表示定時器到期時檔案描述符就會變成可讀,就會觸發。

執行結果如下,

定時器第一次到期時間是1s,後面迴圈週期是5s,和**裡設定的一樣。

epoll監聽檔案 epoll的使用

epoll i o event notification facility 在linux的網路程式設計中,很長的時間都在使用select來做事件觸發。在linux新的核心中,有了一種替換它的機制,就是epoll。相比於select,epoll最大的好處在於它不會隨著監聽fd數目的增長而降低效率。因為...

epoll監聽檔案 Epoll的簡介及原理

epoll 全稱 eventpoll,是 linux 核心實現io多路復用 io multiplexing 的乙個實現。io多路復用的意思是在乙個操作裡同時監聽多個輸入輸出源,在其中乙個或多個輸入輸出源可用的時候返回,然後對其的進行讀寫操作。在 linux 中,和 epoll 類似的有 select...

linux下的epoll函式

epoll是tcp ip網路程式設計的io服用方法之中一種優於select的函式,相比select,它有兩個優點 1.無需編寫以監視狀態變化為目的的針對所有檔案描述符的迴圈語句。2.呼叫對應於select函式的epoll wait函式時無需每次傳遞監視物件資訊。下面介紹epoll伺服器端實現中需要的...