下文所說的IO,包含IO就緒和IO操作
epoll 是一種Linux下的IO模型,是同步非阻塞的一種,也是當前比較流行的IO模型。
Linux下IO模型大致可以分為:同步阻塞、同步非阻塞、異步。
普通的非阻塞IO是各個IO自行盲詢自己的IO是否就緒,而IO復用則是以一個系統調用來完成所有IO是否就緒的輪詢,如果就緒則執行IO操作。
事件驅動是IO復用的一種升級版本,IO復用是輪詢所有的IO。
而事件驅動是只處理已經就緒的IO,首先開啟socket信號驅動的功能(將socket放到epoll文件系統里file對象對應的紅黑樹,並在內核終端處理程序中注冊回調函數),當網卡檢測到某個socket有數據來到時,內核就會將socket放入IO就緒隊列,並從網卡拷貝數據到內核。
IO復用的缺點:
單線程能輪詢的文件描述符有限1024;
需要輪詢所有的IO,如果當前IO事件很多,但是就緒的非常少,那么會導致效率下降;
事件驅動則可以解決上述兩個缺點,沒有文件描述符的限制(通常都非常大,比如2G內存的機器都有655350);只處理已經就緒的IO,可以過濾掉不活躍的IO輪詢帶來的損失。
同時使用mmap(內存映射)的方式,來減少IO數據從內核-用戶控件的拷貝。
MMAP介紹:
1、用戶空間、內核空間都是不能直接訪問設備的物理地址
2、內核空間如果要訪問設備的物理地址,需要先映射物理地址到內核的虛擬地址(頁緩存)上,以后驅動程序訪問這個虛擬地址
3、用戶空間只能通過系統調用訪問映射好的內核虛擬地址(頁緩存)
這上面會有2次數據拷貝,硬件和內核空間,用戶空間和內核空間。
而MMAP的目的是將2次拷貝轉換為1次拷貝,節約拷貝數據帶來的消耗。
將物理地址映射到一塊內存,應用程序(用戶區域)可以直接訪問這塊內存。
事件驅動的缺點:
如果各個IO都比較活躍,那么IO復用的全輪詢也不會有太多的性能損失,但是注冊socket驅動事件卻會帶來一些負擔。