libev原始碼分析(一)----基礎結構體
本篇文章主要分析libev中常用到且十分重要的結構。libev的程式碼很簡練,除了對高效I/O模型等的封裝檔案,核心檔案就兩個:ev.h和ev.c,其中ev.c大概4000行左右。程式碼大量用到了巨集,並且巨集還嵌套了巨集,為了便於理解libev的程式碼,這裡對巨集進行了還原。
ev_watcher結構體(其成員為其它結構的公共部分):
typedef struct ev_watcher { int active;//啟用標識 int pending;//等待事件數 int priority;//優先順序 void* data;// void (*cb)(struct ev_loop* loop, struct ev_watcher *w, int revent);//回撥函式 } ev_watcher;
ev_watcher_list結構體:
typedef struct ev_watcher_list {
int active;
int pending;
int prioirty;
void* data;
void (*cb)(struct ev_loop* loop, struct ev_watcher_list *w,int revent);
struct ev_watcher_list *next;//下一個watcher
}ev_watcher_list;
ev_watcher_time 結構體:
typedef struct ev_watcher_time{ int active; int pending; int priority; void* data; void (*cb)(struct ev_loop *loop, struct ev_watcher_time *w,int revents); ev_tstamp at;// } ev_watcher_time;
ev_io結構體:
typedef struct ev_io { int active;/* 是否已經啟用 */ int pending; /* 是否事件易產生,需要執行回撥 */ int priority; /* 事件優先順序 */ void *data; /* rw */ void (*cb)(struct ev_loop *loop, struct ev_io *w, int revents); /* 回撥 */ struct ev_watcher_list *next; /* private */ int fd; /* 檔案描述符 */ int events; /* 事件型別 */ } ev_io;
ev_timer結構體:
typedef struct ev_timer
{
int active; /* 是否已經啟用 */
int pending; /* 是否事件易產生,需要執行回撥 */
int priority; /* 事件優先順序 */
void *data; /* rw */
void (*cb)(struct ev_loop *loop, struct ev_timer *w, int revents); /* 回撥 */
ev_tstamp at; /* private */
ev_tstamp repeat; /* rw */
} ev_timer;
ev_periodic結構體:
typedef struct ev_periodic {
int active;
int pending;
int priority;
void* data;
void (*cb)(struct ev_loop *loop, struct ev_periodic *w,int revents);
ev_tstamp at;//
ev_tstamp offset;//
ev_tstamp interval;//
ev_tstamp (*reschedule_cb)(struct ev_periodic *w, ev_tstamp now);//
} ev_periodic;
ev_periodic在特定的時間呼叫,可能會在定期間隔反覆呼叫,其基於UTC時間
(PS:UTC:協調時間 也就是從1970年1月1日00:00:00開始記時)觸發事件EV_PERIODIC
ev_signal結構體:
typedef struct ev_signal {
int active;
int pending;
int priority;
void* data;
void (*cb)(struct ev_loop *loop, struct ev_signal *w,int revents);
struct ev_watcher_list *next;
int signum;//
} ev_signal;
ev_signal當接收到指定的訊號時呼叫觸發事件EV_SIGNAL
ev_child結構體:
typedef struct ev_child {
int active;
int pending;
int priority;
void* data;
void (*cb)(struct ev_loop *loop, struct ev_child *w,int revents);
struct ev_watcher_list *next;
int flag;//
int pid;//
int rpid;//
int rstatus;//
} ev_child;
ev_child當接收到SIGCHLD訊號並且waitpid表示了給出的pid時呼叫觸發EV_CHILD事件
其不支援優先順序
ev_stat結構體:
typedef struct ev_stat {
int active;
int pending;
int priority;
void* data;
void (*cb)(struct ev_loop *loop, struct ev_stat *w,int revents);
struct ev_watcher_list *next;
ev_timer timer;//
ev_tstamp interval;//
const char *path;//
ev_statdata prev;//
ev_statdata attr;//
int wd;//
} ev_stat;
ev_stat當每次指定的路徑狀態資料發生改變時呼叫觸發EV_STAT
ev_idle結構體:
typedef struct ev_idle {
int active;
int pending;
int priority;
void* data;
void (*cb)(struct ev_loop *loop, struct ev_idle *w,int revents);
} ev_idle;
ev_idle當啥事情都不需要做的時候呼叫,用來保持程序遠離阻塞觸發EV_IDLE
ev_prepare結構體:
typedef struct ev_prepare {
int active;
int pending;
int priority;
void* data;
void (*cb)(struct ev_loop *loop, struct ev_prepare *w,int revents);
} ev_prepare;
ev_prepare每次執行mainloop主迴圈,在主迴圈之前呼叫觸發EV_PREPARE
ev_check結構體:
typedef struct ev_check {
int active;
int pending;
int priority;
void* data;
void (*cb)(struct ev_loop *loop, struct ev_check *w,int revents);
} ev_check;
ev_check每次執行mainloop主迴圈,在主迴圈之後呼叫觸發EV_CHECK
ev_fork結構體:
typedef struct ev_fork {
int active;
int pending;
int priority;
void* data;
void (*cb)(struct ev_loop *loop,struct ev_fork *w,int revents);
} ev_fork;
ev_fork在fork行為被檢測到,並且在檢測子程序之前呼叫觸發EV_FORK
ev_cleanup結構體:
typedef struct ev_cleanup {
int active;
int pending;
int priority;
void* data;
void (*cb)(struct ev_loop *loop,struct ev_cheanup *w,int revents);
} ev_cleanup;
ev_cleanup在主循被銷燬之後呼叫觸發EV_CLEANUP
ev_embed結構體:
typedef struct ev_embed {
int active;
int pending;
int priority;
void* data;
void (*cb)(struct ev_loop *loop,struct ev_embed *w,int revents);
struct ev_loop* other;//
ev_io io;
ev_prepare prepare;
ev_check check;
ev_timer timer;
ev_periodic periodic;
ev_idle idle;
ev_fork fork;
#if EV_CLEANUP_ENABLE
ev_cleanup cleanup; /* unused */
#endif
} ev_embed;
ev_embed用於將一個事件迴圈巢狀到另一箇中,當事件迴圈處理事件的時候被呼叫
ev_async結構體:
typedef struct ev_async {
int active;
int pending;
int priority;
void* data;
void (*cb)(struct ev_loop *loop, struct ev_async *w, int revents);
sig_atomic_t volatile sent;//
} ev_async;
ev_async當ev_async_send通過watcher呼叫時呼叫,觸發EV_ASYNC
ev_any_watcher結構:
union ev_any_watcher {
struct ev_watcher w;
struct ev_watcher_list wl;
struct ev_io io;
struct ev_timer timer;
struct ev_periodic periodic;
struct ev_signal signal;
struct ev_child child;
#if EV_STAT_ENABLE
struct ev_stat stat;
#endif
#if EV_IDLE_ENABLE
struct ev_idle idle;
#endif
struct ev_prepare prepare;
struct ev_check check;
#if EV_FORK_ENABLE
struct ev_fork fork;
#endif
#if EV_CLEANUP_ENABLE
struct ev_cleanup cleanup;
#endif
#if EV_EMBED_ENABLE
struct ev_embed embed;
#endif
#if EV_ASYNC_ENABLE
struct ev_async async;
#endif
};
該結構的存在用以強制類似結構的佈局
ev_loop結構體(事件迴圈的主體):
struct ev_loop
{
ev_tstamp ev_rt_now;
#define ev_rt_now ((loop)->ev_rt_now)
#define VAR(name,decl) decl;
#include "ev_vars.h" //包含眾多成員
#undef VAR
};
ev_loop的一些成員:
ev_tstamp now_floor;/* last time we refreshed rt_time */
ev_tstamp mn_now;//當前單調時間,系統開機時間
ev_tstamp rtmn_diff;/* difference realtime - monotonic time */
unsigned int origflags;//
int backend;//epoll、kqueue、poll、select、port標記
int activecnt;//啟用事件總數
int backend_fd;//對於epoll,為epoll_create返回的描述符
int * fdchanges;//事件佇列
int fdchangemax;//當前最大事件數
int fdchangecnt;//事件數
ANPENDING *pendings [NUMPRI];//待處理佇列
int pendingmax [NUMPRI];//當前最大等待事件的數量
int pendingcnt [NUMPRI];//記錄每個優先順序的數量
檔案描述符資訊結構
typedef struct{
ev_watcher_list* head; //監聽者連結串列
unsigned char events; //監聽的事件
unsigned char reify;//狀態位 用來表示具體是EV_ANFD_REIFY還是EV_IOFDSET
unsigned char emask;//epoll用來儲存核心mask的值
unsigned char unused;//同名字
#if EV_USE_EPOLL
unsigned int egen;//
#endif
#if EV_SELECT_ISWINSOCKET || EV_USE_IOCP
SOCKET handle;//
#endif
#if EV_USE_IOCP
OVERLAPPED or,ow;//
#endif
} ANFD;
指定等待事件的監聽者結構
typedef struct{
ev_watcher_list* head; //監聽者連結串列
unsigned char events; //監聽的事件
unsigned char reify;//狀態位 用來表示具體是EV_ANFD_REIFY還是EV_IOFDSET
unsigned char emask;//epoll用來儲存核心mask的值
unsigned char unused;//同名字
#if EV_USE_EPOLL
unsigned int egen;//
#endif
#if EV_SELECT_ISWINSOCKET || EV_USE_IOCP
SOCKET handle;//
#endif
#if EV_USE_IOCP
OVERLAPPED or,ow;//
#endif
} ANFD;
每個inotify-id對應的雜湊表的每個節點的結構
typedef struct {
ev_watcher_list* head;
} ANFS;
堆結構的節點
typedef struct {
ev_tstamp at;
ev_watcher_time* w;
} ANHE;