libeventイベント処理フレームワーク分析
いくつかの重要な構造体定義:
event_baseオブジェクトには、イベントエンジン関数オブジェクト(evsel,evbase)、現在のエントリイベントリスト(event_count,event_count_active,eventqueue)、グローバル終了信号(event_gotterm)、アクティブイベントリスト(avtivequeues,nactivequeues)、タイムイベントタイマスタック(timeheap)を含むイベント処理のグローバル変数が統合されています.
イベント_Init()関数は主にevent_baseオブジェクトを初期化し、現在のOSでサポートされているイベントエンジンモデル(evport,kqueue,epoll,devpoll,rtsig,poll,select)を選択し、グローバル信号キュー(evsivevents[NSIG]、NSIG 65)、アクティブキューメモリ割り当て(個数nactivequeues、デフォルト1)を作成します.
イベントオブジェクト構造体定義:
event_add()関数はイベントを追加するために使用されます.
int event_add(struct event *ev, struct timeval *tv)
このインタフェースには2つのパラメータがあり、1つ目は追加するイベントであり、2つ目のパラメータはイベントのタイムアウト値(timer)である.この値がNULLでない場合、イベントの追加と同時にタイムアウトイベント(EV_TIMEOUT)をタイムキューツリー(timetree)に追加し、イベントタイプに応じて次のように処理します.
EV_READ => EVLIST_INSERTED => eventqueue
EV_WRITE => EVLIST_INSERTED => eventqueue
EV_TIMEOUT => EVLIST_TIMEOUT => timetree
EV_SIGNAL => EVLIST_SIGNAL => signalqueue
また信号処理も巧みでパイプ通信で実現
最初に信号処理イベントを追加すると、fdハンドルがパイプの反対側にある信号常駐イベントが追加されます.
信号イベントが追加されると、パイプの一端に「a」という文字がパイプに送信され、イベント駆動モデルはfdハンドルに読み取り可能なイベントが発生したことを検出し、recvはevsignal_をトリガする.プロセス実行処理呼び出しevent_Activeアクティブイベントキューに信号イベントを挿入して処理する(EVLIST_ACTIVE)
struct event_base {
const struct eventop *evsel;/* , event_init */
void *evbase;/* */
int event_count; /* counts number of total events */
int event_count_active; /* counts number of active events */
int event_gotterm; /* Set to terminate loop */
int event_break; /* Set to terminate loop immediately */
/* active event management */
struct event_list **activequeues;/* */
int nactivequeues;/* */
/* signal handling info */
struct evsignal_info sig;
struct event_list eventqueue;/* */
struct timeval event_tv;/* */
struct min_heap timeheap;/* */
struct timeval tv_cache;/* */
};
event_baseオブジェクトには、イベントエンジン関数オブジェクト(evsel,evbase)、現在のエントリイベントリスト(event_count,event_count_active,eventqueue)、グローバル終了信号(event_gotterm)、アクティブイベントリスト(avtivequeues,nactivequeues)、タイムイベントタイマスタック(timeheap)を含むイベント処理のグローバル変数が統合されています.
イベント_Init()関数は主にevent_baseオブジェクトを初期化し、現在のOSでサポートされているイベントエンジンモデル(evport,kqueue,epoll,devpoll,rtsig,poll,select)を選択し、グローバル信号キュー(evsivevents[NSIG]、NSIG 65)、アクティブキューメモリ割り当て(個数nactivequeues、デフォルト1)を作成します.
イベントオブジェクト構造体定義:
struct event {
TAILQ_ENTRY (event) ev_next;
TAILQ_ENTRY (event) ev_active_next;
TAILQ_ENTRY (event) ev_signal_next;
unsigned int min_heap_idx; /* for managing timeouts */
struct event_base *ev_base;
int ev_fd;
short ev_events;
short ev_ncalls;
short *ev_pncalls; /* Allows deletes in callback */
struct timeval ev_timeout;
int ev_pri; /* smaller numbers are higher priority */
void (*ev_callback)(int, short, void *arg);
void *ev_arg;
int ev_res; /* result passed to event callback */
int ev_flags;
};
event_set()関数は、所有者eventを含むeventオブジェクトを設定するために使用されます.baseオブジェクト、fd、イベント(EV_READ|EV_WRITE)、リターン関数とパラメータ、イベント優先度は現在のevent_ベースの中間レベル(current_base->nactivequeues/2)event_add()関数はイベントを追加するために使用されます.
int event_add(struct event *ev, struct timeval *tv)
このインタフェースには2つのパラメータがあり、1つ目は追加するイベントであり、2つ目のパラメータはイベントのタイムアウト値(timer)である.この値がNULLでない場合、イベントの追加と同時にタイムアウトイベント(EV_TIMEOUT)をタイムキューツリー(timetree)に追加し、イベントタイプに応じて次のように処理します.
EV_READ => EVLIST_INSERTED => eventqueue
EV_WRITE => EVLIST_INSERTED => eventqueue
EV_TIMEOUT => EVLIST_TIMEOUT => timetree
EV_SIGNAL => EVLIST_SIGNAL => signalqueue
また信号処理も巧みでパイプ通信で実現
最初に信号処理イベントを追加すると、fdハンドルがパイプの反対側にある信号常駐イベントが追加されます.
信号イベントが追加されると、パイプの一端に「a」という文字がパイプに送信され、イベント駆動モデルはfdハンドルに読み取り可能なイベントが発生したことを検出し、recvはevsignal_をトリガする.プロセス実行処理呼び出しevent_Activeアクティブイベントキューに信号イベントを挿入して処理する(EVLIST_ACTIVE)