內核EPOLL模型的學習

流:就是可以進行內核操作的對象。比如文件,socket,pipe

I/O操作:從流中讀取數據,往流中寫入數據。

阻塞模式:要執行的操作無法進行,一直等待條件滿足時再執行。等待過程中,無操作,靜靜等待。(經濟簡單)

阻塞模式下,內核對於I/o事件的處理是阻塞或者喚醒。

非阻塞模式下,內核對於I/o事件交給其他對象處理,甚至直接忽略。

非阻塞忙輪詢:等待過程中,一直查詢執行條件是否滿足,循環往復。直到條件滿足再執行。(浪費時間精力)

緩衝區:目的是爲了減少I/O操作引起的系統頻繁調用(很慢!)當你操作一個流時,更多的是以緩衝區爲單位進行操作。(用戶和內核都需要緩衝區)

狀態(管道事件)進程A(往管道的寫入數據)管道(數據的存儲,流動)進程B(從管道讀取數據)
緩衝區(管道)空事件A 沒有往管道寫數據管道是空的B無法讀取數據,被阻塞着,就是B睡眠了。
緩衝區非空事件A開始給管道寫數據管道是非空的內核通知B可以進行讀取數據了。B解除阻塞,醒來
緩衝區滿事件A阻塞,管道滿了B沒有讀取數據
緩衝區非滿事件A開始給管道寫數據管道非滿了B進行了讀取數據

阻塞模式缺點:一個線程只能處理一個I/o模式。如果要同時處理多個流,要麼多進程,要麼多線程。但是這兩個方法效率都不高。

非阻塞忙輪詢:不停地把所有流從頭到尾問一遍,又從頭開始,這樣就可以處理多個流了。

​ 缺點是:如果所有的流中都沒有數據,只會白白浪費CPU,

非阻塞無差別輪詢:引進一個代理。代理同時觀察許多流的I/O事件,在空閒的時候,會把當前的線程阻塞掉,當有一個或者多個流有I/o操作事件時,就喚醒線程,於是就輪詢一遍所有的流。

​ 沒有I/o事件時,程序阻塞到代理select處,我們僅僅從select處知道了有I/O事件發生了,但是不知道是哪個流,只能無差別輪詢。當流多的時候,效率也是相當的低了。

非阻塞事件輪詢:代理eventpool會將哪個流發生了什麼I/O事件通知我們。此時對這些流的操作都是有意思的,複雜度降到了n(1)

epoll是對select,poll模型的改進,提高了網絡編程的性能,廣泛用於大規模併發請求的c/s結構中。

1 觸發方式:

​ 邊緣觸發/水平觸發,(只使用unix和linux操作系統)

2 原理

3 步驟

​ 1 創建一個epoll對象

​ 2 告訴epoll對象,在指定的socket上監聽指定的事件

​ 3 詢問epoll對象,從上次查詢以來,那些socket發生了那些指定的事件

​ 4 在這些socket上執行一些操作,

​ 5 告訴epoll對象,修改socket列表和或者事件,並監控

​ 6 重複 3 -5 ,直到完成

​ 7 銷燬epoll對象

4 相關用法:

​ 1 導入select模塊

​ import select

​ 2 創建epoll對象

​ epoll=select.epoll()

​ 3 註冊要監控的文件句柄和事件

​ epoll.register(文件句柄,事件類型)

​ 事件類型:

​ select.EPOLLIN 可讀事件

​ select.EPOLLOUT 可寫事件

​ select.EPOLLERR 錯誤事件

​ select.EPOLLHUP 客戶端斷開事件

​ 4 epoll.unregister(文件句柄) 銷燬文件句柄

​ 5 epoll.fileno() 返回epoll的控制文件描述符

​ 6 epoll.modify(fileno,event) fileno 是文件描述符,event是事件類型,作用是修改文件描述符,所對應的事件

​ 7 epoll.fromfd(fileno) 從一個文件描述符,創建一個epoll對象

​ 8 epoll.close() 關閉epoll對象的控制文件描述符

發佈了42 篇原創文章 · 獲贊 5 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章