事件驅動模型是一種常見的計算機編程模型,用于處理用戶輸入或系統事件。當用戶執行操作如鼠標點擊、移動或鍵盤按鍵等,操作系統將產生相應事件,隨后應用程序接收并處理這些事件。
基本模型
Introduction
在編寫服務器處理程序時,有多種模型可供選擇:
- 創建新進程以處理每個請求,這種方法雖然簡單,但由于創建新進程的開銷較大,可能導致服務器性能較差。
- 創建新線程以處理每個請求,這種方法可能會涉及線程同步,從而導致潛在的死鎖問題。
- 將每個請求放入事件列表中,由主進程通過非阻塞 I/O 方式處理請求。盡管這種方法在編寫應用程序代碼時邏輯較為復雜,但在大多數網絡服務器中廣泛采用。
Select
Select 是一種跨平臺的事件驅動庫,適用于 Linux 和 Windows 平臺。使用 select 庫的典型步驟包括:
1. 創建關注事件的描述符集 (fd_set),通常包括讀、寫和異常事件的描述符集。
2. 調用 `select()` 函數,等待事件發生。`select()` 的阻塞行為與其是否設置非阻塞 I/O 無關。函數原型如下:
```C++
int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, const struct timeval* timeout);
```
其中,`timeout` 參數可用于設置 `select()` 等待的時間。若設置為 0,則 `select()` 在有事件發生時立即返回。否則,`select()` 將等待指定時間后再返回。函數返回值指示發生的 fd 數量。
3. 遍歷所有的 fd_set 中的每個 fd,檢查是否有相關事件發生,并進行處理。
Poll
Poll 庫自 Linux 2.1.23 版本起可用,Windows 平臺不支持。Poll 與 Select 的基本原理相同,均包含創建描述符集、等待事件發生以及遍歷描述符集檢查事件的過程。Poll 的使用步驟大致如下:
1. 創建描述符集并設置關注的事件。
2. 調用 `poll()` 函數,等待事件發生。函數原型如下:
```C++
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
```
`poll()` 同樣允許設置等待時間,其效果與 `select()` 相同。
3. 遍歷描述符集,檢查事件并進行處理。
Poll 與 Select 的主要區別在于,Select 需要分別為讀、寫、異常事件創建單獨的描述符集,而在遍歷時需要分別遍歷這三組集合。相比之下,Poll 只需一個集合,并在每個描述符對應的結構上分別設置讀、寫、異常事件,最終遍歷時可以同時檢查三種事件。
Epoll
Epoll 是 Linux 2.5.44 版本引入的一種高效事件驅動庫,它是 Poll 的變種。Epoll 的特點是能夠提高描述符較多情況下的處理效率,因為它將描述符列表交由內核管理,并在事件發生時直接通知進程。Epoll 的使用步驟如下:
1. 創建一個 Epoll 描述符,通過調用 `epoll_create()` 實現。該函數帶有一個整型參數 `size`,用于指定要創建的描述符列表大小。
```C++
int epoll_create(int size);
```
2. 設置描述符的關注事件,并將其添加到內核的事件列表中,此操作可通過 `epoll_ctl()` 完成。
```C++
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
```
`op` 參數有三種取值,分別表示添加、刪除或修改描述符及其關注的事件。
3. 等待內核通知事件發生,獲取已發生事件的描述符結構列表,這一過程由 `epoll_wait()` 完成。
```C++
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
```
在使用 Epoll 時,需要注意以下兩點:
- Edge Triggered (ET) 觸發模式下,事件由數據達到邊界觸發。因此,在處理讀、寫時應不斷調用 `read()/write()`,直至返回 EAGAIN 錯誤碼,之后再調用 `epoll_wait()` 等待下一個事件。ET 模式的使用原則包括:
- 使用非阻塞 I/O;
- 直至 `read()/write()` 返回 EAGAIN 時,才等待下一次事件的發生。
- Level Triggered (LT) 觸發模式下,只要仍有未讀/未寫的剩余數據,調用 `epoll_wait()` 時就會觸發事件。相比 Poll,Epoll 在 LT 模式下的處理速度可能更快。
參考資料 >
事件驅動模型-CSDN博客.CSDN博客.2024-11-01
6 種事件驅動的架構模式_事件驅動模型-CSDN博客.CSDN博客.2024-11-01
事件驅動模型.博客園.2024-11-01