成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

IO多路復用之Select、Poll、Epoll

存儲 存儲軟件
I/O多路復用(multiplexing)的本質是通過一種機制(系統內核緩沖I/O數據),讓單個進程可以監視多個文件描述符,一旦某個描述符就緒(一般是讀就緒或寫就緒),能夠通知程序進行相應的讀寫操作。

 [[402481]]

本文轉載自微信公眾號「搬運工來架構」,作者cocodroid。轉載本文請聯系搬運工來架構公眾號。

I/O多路復用(multiplexing)的本質是通過一種機制(系統內核緩沖I/O數據),讓單個進程可以監視多個文件描述符,一旦某個描述符就緒(一般是讀就緒或寫就緒),能夠通知程序進行相應的讀寫操作。

01select

  1. int select (int n, fd_set *readfds, fd_set *writefds,  
  2.                    fd_set *exceptfds, struct timeval *timeout); 
  3.  
  4. // fd_set 結構體簡化為: 
  5. typedef struct{ 
  6.     long int fds_bits[32]; 
  7. }fd_set; 

select 函數監視的文件描述符分3類,分別是writefds、readfds、和exceptfds。調用后select函數會阻塞,直到有描述符就緒(有數據 可讀、可寫、或者有except),或者超時(timeout指定等待時間,如果立即返回設為null即可),函數返回。當select函數返回后,可以通過遍歷fdset,來找到就緒的描述符。

select本質上是通過設置或者檢查存放fd標志位的數據結構來進行下一步處理。

缺點:

1、 單個進程可監視的fd數量被限制,即能監聽端口的大小有限。

一般來說這個數目和系統內存關系很大,具體數目可以cat /proc/sys/fs/file-max察看。32位機默認是1024個。64位機默認是2048.

2、 對socket進行掃描時是線性掃描,即采用輪詢的方法,效率較低:

當套接字比較多的時候,每次select()都要通過遍歷FD_SETSIZE個Socket來完成調度,不管哪個Socket是活躍的,都遍歷一遍。這會浪費很多CPU時間。如果能給套接字注冊某個回調函數,當他們活躍時,自動完成相關操作,那就避免了輪詢,這正是epoll與kqueue做的。

3、需要維護一個用來存放大量fd的數據結構,每次調用select時把fd集合從用戶態拷貝到內核態,這樣會使得用戶空間和內核空間在傳遞該結構時復制開銷大。

02poll

  1. int poll (struct pollfd *fds, unsigned int nfds, int timeout); 
  2.  
  3. struct pollfd { 
  4.     int fd; /* file descriptor */ 
  5.     short events; /* requested events to watch */ // 請求監視的事件 
  6.     short revents; /* returned events witnessed */ // 返回發生的事件 
  7. }; 

和select沒有區別,它將用戶傳入的數組拷貝到內核空間,然后查詢每個fd對應的設備狀態,如果設備就緒則在設備等待隊列中加入一項并繼續遍歷,如果遍歷完所有fd后沒有發現就緒設備,則掛起當前進程,直到設備就緒或者主動超時,被喚醒后它又要再次遍歷fd。這個過程經歷了多次無謂的遍歷。

它沒有最大連接數的限制,原因是它是基于鏈表來存儲的。

缺點:

1、大量的fd的數組被整體復制于用戶態和內核地址空間之間,而不管這樣的復制是不是有意義。

2、poll還有一個特點是“水平觸發”,如果報告了fd后,沒有被處理,那么下次poll時會再次報告該fd。

LT模式:level trigger。當epoll_wait檢測到描述符事件發生并將此事件通知應用程序,

應用程序可以不立即處理該事件。下次調用epoll_wait時,會再次響應應用程序并通知此事件。

ET模式:edge trigger。當epoll_wait檢測到描述符事件發生并將此事件通知應用程序,

應用程序必須立即處理該事件。如果不處理,下次調用epoll_wait時,不會再次響應應用程序并通知此事件。

03epoll

  1. int epoll_create(int size); 
  2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); 
  3. int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout); 

epoll_create:創建一個epoll的句柄,size用來告訴內核這個監聽的數目一共有多大。參數size并不是限制了epoll所能監聽的描述符最大個數,只是對內核初始分配內部數據結構的一個建議。

epoll_ctl:對指定描述符fd執行op操作。

-epfd:是epoll_create()的返回值。

-op操作:對應宏:添加EPOLL_CTL_ADD,刪除EPOLL_CTL_DEL,修改EPOLL_CTL_MOD,對應添加、刪除和修改對fd的監聽事件。

- fd:是需要監聽的fd(文件描述符)。

- epoll_event:是告訴內核需要監聽什么事件(讀、寫事件等)。

epoll_wait:等待epfd上的io事件,最多返回maxevents個事件。

-events:用來從內核得到事件的集合,

-maxevents:告之內核這個events有多大,這個maxevents的值不能大于創建epoll_create()時的size,

-timeout:是超時時間。

epoll有EPOLLLT和EPOLLET兩種觸發模式,LT是默認的模式,ET是“高速”模式。LT模式下,只要這個fd還有數據可讀,每次 epoll_wait都會返回它的事件,提醒用戶程序去操作,而在ET(邊緣觸發)模式中,它只會提示一次,直到下次再有數據流入之前都不會再提示了,無論fd中是否還有數據可讀。所以在ET模式下,read一個fd的時候一定要把它的buffer讀光,也就是說一直讀到read的返回值小于請求值,或者遇到EAGAIN錯誤。還有一個特點是,epoll使用“事件”的就緒通知方式,通過epoll_ctl注冊fd,一旦該fd就緒,內核就會采用類似callback的回調機制來激活該fd,epoll_wait便可以收到通知。

epoll為什么要有EPOLLET觸發模式?

如果采用EPOLLLT模式的話,系統中一旦有大量你不需要讀寫的就緒文件描述符,它們每次調用epoll_wait都會返回,這樣會大大降低處理程序檢索自己關心的就緒文件描述符的效率.。而采用EPOLLET這種邊沿觸發模式的話,當被監控的文件描述符上有可讀寫事件發生時,epoll_wait()會通知處理程序去讀寫。如果這次沒有把數據全部讀寫完(如讀寫緩沖區太小),那么下次調用epoll_wait()時,它不會通知你,也就是它只會通知你一次,直到該文件描述符上出現第二次可讀寫事件才會通知你!!!這種模式比水平觸發效率高,系統不會充斥大量你不關心的就緒文件描述符。

epoll優點:

1、沒有最大并發連接的限制,能打開的FD的上限遠大于1024(1G的內存上能監聽約10萬個端口);

2、效率提升,不是輪詢的方式,不會隨著FD數目的增加效率下降。只有活躍可用的FD才會調用callback函數;

即Epoll最大的優點就在于它只管你“活躍”的連接,而跟連接總數無關,因此在實際的網絡環境中,Epoll的效率就會遠遠高于select和poll。

3、 內存拷貝,利用mmap()文件映射內存加速與內核空間的消息傳遞;即epoll使用mmap減少復制開銷。

04區別

0、底層數據結構

select:數組,poll:鏈表,epoll:紅黑樹。

1、支持一個進程所能打開的最大連接數

select 單個進程所能打開的最大連接數有FD_SETSIZE宏定義,其大小是32個整數的大小(在32位的機器上,大小就是32*32,同理64位機器上FD_SETSIZE為32*64),當然我們可以對進行修改,然后重新編譯內核,但是性能可能會受到影響,這需要進一步的測試。

poll本質上和select沒有區別,但是它沒有最大連接數的限制,原因是它是基于鏈表來存儲的。

epoll 雖然連接數有上限,但是很大,1G內存的機器上可以打開10萬左右的連接,2G內存的機器可以打開20萬左右的連接。

2、FD劇增后帶來的IO效率問題

select/poll 因為每次調用時都會對連接進行線性遍歷,所以隨著FD的增加會造成遍歷速度慢的“線性下降性能問題”。

epoll 因為epoll內核中實現是根據每個fd上的callback函數來實現的,只有活躍的socket才會主動調用callback,所以在活躍socket較少的情況下,使用epoll沒有前面兩者的線性下降的性能問題,但是所有socket都很活躍的情況下,可能會有性能問題。

3、消息傳遞方式

select/poll 內核需要將消息傳遞到用戶空間,都需要內核拷貝動作。

epoll通過內核和用戶空間共享一塊內存來實現的。

select、poll與epoll之間的區別總結圖:

歷史背景:

1)select出現是1984年在BSD里面實現的。

2)14年之后也就是1997年才實現了poll,其實拖那么久也不是效率問題, 而是那個時代的硬件實在太弱,一臺服務器處理1千多個鏈接簡直就是神一樣的存在了,select很長段時間已經滿足需求 。

3)2002, 大神 Davide Libenzi 實現了epoll。

參考資料:

https://www.cnblogs.com/Anker/p/3265058.html

https://www.cnblogs.com/aspirant/p/9166944.html

https://www.cnblogs.com/dhcn/p/12731883.html

 

責任編輯:武曉燕 來源: 搬運工來架構
相關推薦

2023-03-01 14:32:31

redisIOEpoll

2025-06-06 00:33:00

2023-01-09 10:04:47

IO多路復用模型

2025-01-07 00:07:17

2020-10-14 09:11:44

IO 多路復用實現機

2025-04-24 10:05:51

2023-12-06 07:16:31

Go語言語句

2024-08-08 14:57:32

2023-12-06 07:28:47

阻塞IO異步IO

2022-09-12 06:33:15

Select多路復用

2023-11-07 08:19:35

IO多路復用磁盤、

2023-12-13 09:45:49

模型程序

2022-08-26 00:21:44

IO模型線程

2024-12-30 00:00:05

2024-09-26 16:01:52

2020-10-13 07:51:03

五種IO模型

2011-12-08 10:51:25

JavaNIO

2009-06-29 18:09:12

多路復用Oracle

2022-02-22 08:55:29

SelectPoll/ Epoll

2021-05-11 08:22:32

Epoll 監聽I
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 在线免费看黄 | 久久1区| 国产日韩欧美91 | 中文字幕 国产精品 | 国产精品久久久久久久久免费桃花 | 91久久久久久久久 | 久久精品一级 | 成年人国产在线观看 | 一区二区三区视频在线观看 | 玖玖在线精品 | 东方伊人免费在线观看 | 免费在线观看黄网站 | 婷婷综合 | 国产一区二区三区在线免费 | 成人免费影院 | 国产精品一区二区三区在线 | 亚洲www| 精品乱码一区二区三四区视频 | 色狠狠一区 | 久久久精品一区二区三区四季av | 国产精品久久久久久久久久久免费看 | 久国产 | 日韩天堂av | 熟女毛片| 国产成人精品网站 | 亚洲国产精品99久久久久久久久 | 一级免费a| 久久在线免费 | 久久综合一区二区 | 成人免费一级 | 亚洲入口 | 亚洲 欧美 在线 一区 | 国产一级片免费看 | 播放一级毛片 | 国产精品激情 | 久久国产精品免费一区二区三区 | 日韩一区中文字幕 | 久热精品在线 | 欧美精品久久久久 | 视频一区二区国产 | 成人av资源在线 |