Libevent 是一個輕量級的開源高性能網絡庫,事件驅動(event-driven), 實現基於 Reactor 模式,網上學習資料衆多,這裏分享一下關於 signal 的處理。
首先給出 libevent 對 signal 的處理宏定義:
evsignal_* macros Aliases for working with signal events #define evsignal_add(ev, tv) event_add((ev), (tv)) #define evsignal_assign(ev, b, x, cb, arg) \ event_assign((ev), (b), (x), EV_SIGNAL|EV_PERSIST, cb, (arg)) #define evsignal_new(b, x, cb, arg)\ event_new((b), (x), EV_SIGNAL|EV_PERSIST, (cb), (arg)) #define evsignal_del(ev) event_del(ev) #define evsignal_pending(ev, tv) event_pending((ev), EV_SIGNAL, (tv)) #define evsignal_initialized(ev) event_initialized(ev)
signal 事件的處理函數即是普通 event 事件的處理函數別無二致,唯一不同之處在於在文件描述符,signal 事件該參數的意義是 signal no,我們可以用 kill -l 命令查看系統的 signal table:
常用的信號 有SIGINT ( CTRL+C),SINPIPE(經常用於網絡編程)。
我這裏先寫一個例子:
#include <stdio.h>
#include <stdlib.h>
#include <event2/event.h>
#include <event2/event_struct.h>
void handler(int signo, short events, void* arg) {
printf("Receive signal %d\n", signo);
}
int main()
{
struct event_base* base = event_base_new();
int signo = SIGINT;
struct event *sig_event = evsignal_new(base, signo, handler, NULL);
evsignal_add(sig_event, NULL);
event_base_dispatch(base);
exit(0);
}
這裏我以SIGINT信號爲例,首先寫一個信號處理函數
void handler(int signo, short events, void* arg)
該函數的形參與一般的回調函數無異,處理內容也很簡單,就是打印出收到的 signal,當然真實情況需要做更適當的處理。
上面的代碼處理很簡單:
首先新建一個 event 變量用於處理信號
struct event * sig_event = evsignal_new(base, signo, handler, NULL);
接着將它註冊到信號事件隊列
evsignal_add(sig_event, NULL);
剩下的就和普通事件完全一樣了。
編譯:
gcc -o proc event-signal-demo.c -levent
運行測試:
按下 CTRL + C會發現程序不會像平常那般退出,而是打印出
“^CReceive signal 2”
程序捕捉到了 SIGINT 信號,over。
此外討論一下,如何對特定的線程發出特定的信號,仍以上面的程序爲例,除了採用CTRL + C產生 SIGINT 信號外,更一般的方法是藉助 kill 命令。
首先先求得目的線程的 PID,利用如下命令:
ps aux | grep proc | grep -v grep
在結果中得出 proc 進程的 PID 爲2719。接着使用
kill -2 2719
就可以向 proc 進程發送 SIGINT 信號了(這裏的2是 SIGINT 的 signo)。
允許轉載
參考資料
libevent源碼深度剖析 張亮
Fast portable non-blocking network programming with Libevent (沒發現作者是誰)