IO模型、IO多路複用、select poll epoll
基礎知識
基礎知識
高效能架構設計主要有兩方面:
1.提高單伺服器的效能。
2.伺服器採用叢集。
提升單伺服器的效能的關鍵之一就是服務端採用併發模型。
併發模型主要有兩方面:
1.伺服器如何管理連線。
2.伺服器如何處理請求。
以上兩點都和 作業系統的 IO模型和程序模型有關。
1.IO模型:阻塞、非阻塞、同步、非同步。
2.程序模型:單程序、多程序、多執行緒。
在討論 IO模型之前,先梳理一下基礎知識。
同步、非同步
POSIX術語定義:
同步I/O操作,導致請求程序阻塞,直到I/O操作完成;
非同步I/O操作,不導致請求程序阻塞。
同步和非同步:關注的是通訊機制。
同步:發生一個“呼叫”時,呼叫方主動等待,一直到被呼叫方生產出結果,然後返回。
非同步:發生一個“呼叫”時,呼叫方不等待被呼叫方的結果,而是直接返回,當被呼叫方生產出結果後,通知呼叫方。
程序的阻塞
正在執行的程序,由於期待的某些事件未發生,如請求系統資源失敗、等待某種操作的完成、新資料尚未到達或無新工作做等,則由系統自動執行阻塞原語(Block),使自己由執行狀態變為阻塞狀態。
可見,程序的阻塞是程序自身的一種主動行為,也因此只有處於執行態的程序(獲得CPU),才可能將其轉為阻塞狀態。當程序進入阻塞狀態,是不佔用CPU資源的。
阻塞和非阻塞:關注的是呼叫方自身的狀態。
理解 IO操作
對於一次IO的Read:
【資料】—>【核心的緩衝區】————>【應用程式的緩衝區】—>【應用程序】
所以,當一個read操作發生時,它會經歷兩個階段:
1. 等待資料準備(把資料拷貝到核心)
2. 將資料從核心快取拷貝到程序快取中
同步:(阻塞、非阻塞、IO多路複用)第2步是使用者執行緒自行完成拷貝。此過程使用者程序阻塞於 recvfrom呼叫。
非同步:第2步是核心完成拷貝,將資料拷貝到了使用者執行緒指定的快取區,並通知使用者執行緒。全程無阻塞。
Unix下可用的5種I/O模型
同步模型:
阻塞式I/O:blocking IO
非阻塞式I/O:nonblocking IO ——Socket被設定為NONBLOCK。
I/O複用:IO multiplexing(select和poll)——Reactor設計模式。
訊號驅動式I/O:signal driven IO ——不常用。
非同步模型:
非同步I/O:asynchronous IO(POSIX的aio_系列函式)——Proactor設計模式。
【插播】:
陳皓說,非同步 I/O 模型的發展技術是: select -> poll -> epoll -> aio -> libevent -> libuv。Unix/Linux 用了好幾十年走過這些技術的變遷,然而,都不如 Windows I/O Completion Port 設計得好。
在《從0開始學架構》的評論裡有人說,Reactor與Proactor能不能這樣打個比方:
1、假如我們去飯店點餐,飯店人很多,如果我們付了錢後站在收銀臺等著飯端上來我們才離開,這就成了同步阻塞了。
2、如果我們付了錢後給你一個號就可以離開,飯好了老闆會叫號,你過來取。這就是Reactor模型。
3、如果我們付了錢後給我一個號就可以坐到坐位上該幹啥幹啥,飯好了老闆會把飯端上來送給你。這就是Proactor模型了。
同步阻塞 IO
程序在第一步和第二步都是阻塞的。
虛擬碼:
{
read(socket, buffer);
process(buffer);
}
同步非阻塞 IO
{
while(read(socket, buffer) != SUCCESS)
;
process(buffer);
}
IO 多路複用
{
select(socket);
while(1) {
sockets = select();
for(socket in sockets) {
if(can_read(socket)) {
read(socket, buffer);
process(buffer);
}
}
}
}
非同步 IO
void UserCompletionHandler::handle_event(buffer) {
process(buffer);
}
{
aio_read(socket, new UserCompletionHandler);
}
5中IO模型的比較
IO多路複用的理解
《unix網路程式設計》v3的6.1:
————————————
在5.12節中,我們看到TCP客戶同時處理兩個輸入:標準輸入和TCP套接字。
我們遇到的問題是就在客戶阻塞於(標準輸入上的)fgets呼叫期間,伺服器程序會被殺死。伺服器TCP雖然正確地給客戶TCP傳送了一個FIN,但是既然客戶程序正阻塞於從標準輸入讀入的過程,它將看不到這個EOF,直到從套接字讀時為止(可能已過了很長時間)。
這樣的程序需要一種預先告知核心的能力,使得核心一旦發現程序指定的一個或多個I/O條件就緒(也就是說輸入已準備好被讀取,或者描述符已能承接更多的輸出),它就通知程序。這個能力稱為I/O複用(I/Omultiplexing),是由select和poll這兩個函式支援的。
What we need is the capability
to tell the kernel that we want to be notified if one or more I/O conditions are ready
(i.e., input is ready to be read, or the descriptor is capable of taking more output).
This capability is called I/O multiplexing and is provided by the select and poll functions.
I/O複用典型使用在下列網路應用場合。
- 當客戶處理多個描述符(通常是互動式輸入和網路套接字)時,必須使用I/O複用。
- 一個客戶同時處理多個套接字是可能的,不過比較少見。
- 如果一個TCP伺服器既要處理監聽套接字,又要處理已連線套接字,一般就要使用I/O複用。
- 如果一個伺服器即要處理TCP,又要處理UDP,一般就要使用I/O複用。
- 如果一個伺服器要處理多個服務或者多個協議(例如我們將在13.5節講述的inetd守護程序),一般就要使用I/O複用。
I/O複用並非只限於網路程式設計,許多重要的應用程式也需要使用這項技術。
————————————
【我的註解】
對此處的定義的理解:IO複用是一種能力(功能)。
step1. 使用者程序先告訴核心:有一些IO,例如:[a,b,c],如果它們中有準備好的,核心你就通知我。
step2. 核心發現在 [a,b,c]中有準備好了的,然後核心會把“有IO準備好了”這個資訊通知給使用者程序。
step3. 使用者程序再檢查哪個IO是準備好的,然後操作這個IO。
這個過程中,核心如果能支援上述的行為,那麼核心就支援IO多路複用。
這種解釋是從“功能”的角度作出解釋。我從字面解釋一下:
- case1. 沒有IO複用的時候,使用者程序需要對自己關心的每一個IO是否準備好,進行查詢(非阻塞)。例如,迴圈對[a,b,c]按個查詢,對3個IO物件查詢,就好比是走3條不同的“路”。
- case2. 而使用了IO複用後,使用者程序不需要對每個IO進行查詢,而是核心通知使用者程序,只需要這一條“路”。
- 由case1到case2,就好像是需要3條路才能解決的事情,變成了只需1條路就可以解決,即“多路複用”。
與多程序和多執行緒技術相比,I/O多路複用技術的最大優勢是系統開銷小,系統不必建立程序/執行緒,也不必維護這些程序/執行緒,從而大大減小了系統的開銷。
IO多路複用的具體實現有select、poll和epoll三種。
select poll epoll的區別
select,poll,epoll都是IO多路複用的機制。I/O多路複用就通過一種機制,可以監視多個描述符,一旦某個描述符就緒(一般是讀就緒或者寫就緒),能夠通知程式進行相應的讀寫操作。
但select,poll,epoll本質上都是同步I/O,因為他們都需要在讀寫事件就緒後自己負責進行讀寫,也就是說這個讀寫過程是阻塞的,而非同步I/O則無需自己負責進行讀寫,非同步I/O的實現會負責把資料從核心拷貝到使用者空間。
三種IO多路複用進行對比:
select
呼叫過程:
(1)使用 copy_from_user從使用者空間拷貝 fd_set到核心空間
(2)註冊回撥函式 __pollwait
(3)遍歷所有fd,呼叫其對應的poll方法(對於socket,這個poll方法是sock_poll,sock_poll根據情況會呼叫到tcp_poll,udp_poll或者datagram_poll)
(4)以tcp_poll為例,其核心實現就是__pollwait,也就是上面註冊的回撥函式。
(5)__pollwait的主要工作就是把current(當前程序)掛到裝置的等待佇列中,不同的裝置有不同的等待佇列,對於tcp_poll來說,其等待佇列是sk->sk_sleep(注意把程序掛到等待佇列中並不代表程序已經睡眠了)。在裝置收到一條訊息(網路裝置)或填寫完檔案資料(磁碟裝置)後,會喚醒裝置等待佇列上睡眠的程序,這時current便被喚醒了。
(6)poll方法返回時會返回一個描述讀寫操作是否就緒的mask掩碼,根據這個mask掩碼給fd_set賦值。
(7)如果遍歷完所有的fd,還沒有返回一個可讀寫的mask掩碼,則會呼叫schedule_timeout是呼叫select的程序(也就是current)進入睡眠。當裝置驅動發生自身資源可讀寫後,會喚醒其等待佇列上睡眠的程序。如果超過一定的超時時間(schedule_timeout指定),還是沒人喚醒,則呼叫select的程序會重新被喚醒獲得CPU,進而重新遍歷fd,判斷有沒有就緒的fd。
(8)把fd_set從核心空間拷貝到使用者空間。
select的缺點:
(1)每次呼叫select,都需要把fd集合從使用者態拷貝到核心態,這個開銷在fd很多時會很大
(2)同時每次呼叫select都需要在核心遍歷傳遞進來的所有fd,這個開銷在fd很多時也很大
(3)select支援的檔案描述符數量太小了,預設是1024
poll
poll的實現和select非常相似,只是描述fd集合的方式不同,poll使用pollfd結構而不是select的fd_set結構,其他的都差不多。
epoll
epoll既然是對select和poll的改進,就應該能避免上述的三個缺點。那epoll都是怎麼解決的呢?
在此之前,我們先看一下epoll和select和poll的呼叫介面上的不同,select和poll都只提供了一個函式——select或者poll函式。
而epoll提供了三個函式:
epoll_create 是建立一個epoll控制代碼;
epoll_ctl 是註冊要監聽的事件型別;
epoll_wait 則是等待事件的產生。
對於第一個缺點,epoll的解決方案在epoll_ctl函式中。每次註冊新的事件到epoll控制代碼中時(在epoll_ctl中指定EPOLL_CTL_ADD),會把所有的fd拷貝進核心,而不是在epoll_wait的時候重複拷貝。epoll保證了每個fd在整個過程中只會拷貝一次。
對於第二個缺點,epoll的解決方案不像select或poll一樣每次都把current輪流加入fd對應的裝置等待佇列中,而只在epoll_ctl時把current掛一遍(這一遍必不可少)併為每個fd指定一個回撥函式,當裝置就緒,喚醒等待佇列上的等待者時,就會呼叫這個回撥函式,而這個回撥函式會把就緒的fd加入一個就緒連結串列)。epoll_wait的工作實際上就是在這個就緒連結串列中檢視有沒有就緒的fd(利用schedule_timeout()實現睡一會,判斷一會的效果,和select實現中的第7步是類似的)。
對於第三個缺點,epoll沒有這個限制,它所支援的FD上限是最大可以開啟檔案的數目,這個數字一般遠大於2048,舉個例子,在1GB記憶體的機器上大約是10萬左右,具體數目可以cat /proc/sys/fs/file-max察看,一般來說這個數目和系統記憶體關係很大。
總結:
(1)select,poll實現需要自己不斷輪詢所有fd集合,直到裝置就緒,期間可能要睡眠和喚醒多次交替。
而epoll其實也需要呼叫epoll_wait不斷輪詢就緒連結串列,期間也可能多次睡眠和喚醒交替,但是它是裝置就緒時,呼叫回撥函式,把就緒fd放入就緒連結串列中,並喚醒在epoll_wait中進入睡眠的程序。雖然都要睡眠和交替,但是select和poll在“醒著”的時候要遍歷整個fd集合,而epoll在“醒著”的時候只要判斷一下就緒連結串列是否為空就行了,這節省了大量的CPU時間。這就是回撥機制帶來的效能提升。
(2)select,poll每次呼叫都要把fd集合從使用者態往核心態拷貝一次,並且要把current往裝置等待佇列中掛一次。
而epoll只要一次拷貝,而且把current往等待佇列上掛也只掛一次(在epoll_wait的開始,注意這裡的等待佇列並不是裝置等待佇列,只是一個epoll內部定義的等待佇列)。這也能節省不少的開銷。
原型
select
基於點陣圖型集合,通過巨集和fd_set結構體設定事件和檢測事件的發生。
最早被提出所以可移植性最好,該實現有以下缺點:
1.每次呼叫都需要將fd集合從使用者空間拷貝到核心空間,完成後再從核心空間拷貝回用戶空間,fd很多時開銷很大。
2.實現過程是在核心中遍歷所有fd,fd很多時開銷很大。
3.支援同時可監控的檔案描述符數少,1024或2048。
4.fd_set在select返回後會改變,所以再次呼叫select時需要再次設定fd_set
原型:
#include <sys/select.h>
#include <sys/time.h> int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, const struct timeval *timeout)
返回值:就緒描述符的數目,超時返回0,出錯返回-1
函式引數:
(1)第一個引數 maxfdp1 指定待測試的描述字個數。
它的值是待測試的最大描述字加1(因此把該引數命名為maxfdp1),描述字0、1、2...maxfdp1-1均將被測試。因為檔案描述符是從0開始的。
(2)中間的三個引數 readset、writeset和exceptset 指定我們要讓核心測試讀、寫和異常條件的描述字。
如果對某一個的條件不感興趣,就可以把它設為空指標。
struct fd_set可以理解為一個集合,這個集合中存放的是檔案描述符,可通過以下四個巨集進行設定:
void FD_ZERO(fd_set *fdset); //清空集合
void FD_SET(int fd, fd_set *fdset); //將一個給定的檔案描述符加入集合之中
void FD_CLR(int fd, fd_set *fdset); //將一個給定的檔案描述符從集合中刪除
int FD_ISSET(int fd, fd_set *fdset); // 檢查集合中指定的檔案描述符是否可以讀寫
(3)timeout 告知核心等待所指定描述字中的任何一個就緒可花多少時間。
其timeval結構用於指定這段時間的秒數和微秒數。
struct timeval{
long tv_sec; //seconds
long tv_usec; //microseconds
};
這個引數有三種可能:
(1)永遠等待下去:僅在有一個描述字準備好I/O時才返回。為此,把該引數設定為空指標NULL。
(2)等待一段固定時間:在有一個描述字準備好I/O時返回,但是不超過由該引數所指向的timeval結構中指定的秒數和微秒數。
(3)根本不等待:檢查描述字後立即返回,這稱為輪詢。為此,該引數必須指向一個timeval結構,而且其中的定時器值必須為0。
poll
poll的機制與select類似,與select在本質上沒有多大差別,管理多個描述符也是進行輪詢,根據描述符的狀態進行處理,但是poll沒有最大檔案描述符數量的限制。
poll和select同樣存在一個缺點就是,包含大量檔案描述符的陣列被整體複製於使用者態和核心的地址空間之間,而不論這些檔案描述符是否就緒,它的開銷隨著檔案描述符數量的增加而線性增大。
要比select高階一些,實現和select大致相同,核心中遍歷所有檔案描述符。使用連結串列式集合,不需要重複設定監控事件,同時監控檔案描述符數遠大於select。
缺點也和select大致相同:
1.每次呼叫都需要將pollfd集合從使用者空間拷貝到核心空間,完成後再從核心空間拷貝回用戶空間。
2.實現過程是在核心中遍歷所有pollfd。
原型:
# include <poll.h>
int poll ( struct pollfd * fds, unsigned int nfds, int timeout);
返回值:
成功時返回revents不為0的檔案描述符個數,0表示超時但沒有任何事件發生,-1表示失敗
引數:
struct pollfd {
int fd; 檔案描述符
short events; 等待的事件,掩碼控制多個事件
short revents; 實際發生的事件,掩碼控制多個事件
}
fds連結串列是要監控檔案描述符的pollfd連結串列
nfds指定描述符個數
timeout:0表示立即返回,非阻塞;正值表示等待的毫秒數;負值表示無限等待,阻塞模式
返回值:revents不為0的pollfd數,-1表示出錯
events和revents中的事件:
合法事件:
POLLIN 有資料可讀
POLLRDNORM 有普通資料可讀
POLLRDBAND 有優先資料可讀
POLLPRI 有緊迫資料可讀
POLLOUT 寫資料不會導致阻塞
POLLWRNORM 寫普通資料不會導致阻塞
POLLWRBAND 寫優先資料不會導致阻塞
POLLMSGSIGPOLL 訊息可用不會導致阻塞
非法事件:
POLLER 檔案描述符發生錯誤
POLLHUP 檔案描述符掛起事件
POLLNVAL 檔案描述符非法
epoll
epoll是在2.6核心中提出的,是之前的select和poll的增強版本。相對於select和poll來說,epoll更加靈活,沒有描述符限制。epoll使用一個檔案描述符管理多個描述符,將使用者關係的檔案描述符的事件存放到核心的一個事件表中,這樣在使用者空間和核心空間的copy只需一次。
通過3個函式來實現,更加高效,當前使用也最多。
在epoll_ctl中註冊事件到epoll檔案描述符中,把fd全部拷貝進核心,而不是在epoll_wait中重複拷貝。實現中核心通過為每個fd指定一個回撥函式,當fd就緒時呼叫回撥函式把就緒fd加入一個就緒連結串列,epoll_wait只需要檢視這個就緒連結串列是否有就緒fd就可。可監控檔案描述符數是系統可同時開啟檔案數(超過10萬)
原型:
#include <sys/epoll.h>
int epoll_create(int size);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
int epoll_create(int size); //返回epoll檔案描述符,size表示要監聽的數目 (這個返回的fd要記得close)
建立一個epoll的控制代碼,size用來告訴核心這個監聽的數目一共有多大。這個引數不同於select()中的第一個引數,給出最大監聽的fd+1的值。需要注意的是,當建立好epoll控制代碼後,它就是會佔用一個fd值,在linux下如果檢視/proc/程序id/fd/,是能夠看到這個fd的,所以在使用完epoll後,必須呼叫close()關閉,否則可能導致fd被耗盡。
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); //epoll事件註冊函式
epoll的事件註冊函式,它不同與select()是在監聽事件時告訴核心要監聽什麼型別的事件epoll的事件註冊函式,它不同與select()是在監聽事件時告訴核心要監聽什麼型別的事件,而是在這裡先註冊要監聽的事件型別。
引數:
epfd 是epoll_create返回的值
op 是動作:
EPOLL_CTL_ADD:註冊新的 fd到epfd中;
EPOLL_CTL_MOD:修改已註冊的fd的監聽事件;
EPOLL_CTL_DEL:從epfd刪除1個fd。
fd 是要監聽的fd
event 是告訴核心要監聽什麼事件
struct epoll_event{
__uint32_t events; //epoll events
epoll_data_t data; //user data variable
}
event是巨集的集合:
EPOLLIN :表示對應的檔案描述符 可以讀(包括對端SOCKET正常關閉);
EPOLLOUT:表示對應的檔案描述符 可以寫;
EPOLLPRI:表示對應的檔案描述符 有緊急的資料可讀(這裡應該表示有帶外資料到來);
EPOLLERR:表示對應的檔案描述符 發生錯誤;
EPOLLHUP:表示對應的檔案描述符 被結束通話;
EPOLLET: 將EPOLL設為邊緣觸發(Edge Triggered)模式,這是相對於水平觸發(Level Triggered)來說的。
EPOLLONESHOT:只監聽一次事件,當監聽完這次事件之後,如果還需要繼續監聽這個socket的話,需要再次把這個socket加入到 EPOLL佇列裡
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout); //等待事件發生
等待事件的產生,類似於select()呼叫。
引數:
events 用來從核心得到事件的集合,是返回的事件連結串列;
maxevents 告之核心這個events連結串列元素個數,這個maxevents的值不能大於建立epoll_create()時的size
timeout是超時時間(毫秒,0會立即返回,非阻塞;正值表示等待的毫秒數;負值表示無限等待,阻塞模式)。
返回值:
需要處理的事件數,通過events返回需要處理的事件。(通過events[i].data.fd和events[i].events匹配判斷)
工作模式
epoll對檔案描述符的操作有兩種模式:LT(level trigger)和ET(edge trigger)。
LT模式是預設模式,LT模式與ET模式的區別如下:
LT模式:當epoll_wait檢測到描述符事件發生並將此事件通知應用程式,應用程式可以不立即處理該事件。下次呼叫epoll_wait時,會再次響應應用程式並通知此事件。
ET模式:當epoll_wait檢測到描述符事件發生並將此事件通知應用程式,應用程式必須立即處理該事件。如果不處理,下次呼叫epoll_wait時,不會再次響應應用程式並通知此事件。
ET模式在很大程度上減少了epoll事件被重複觸發的次數,因此效率要比LT模式高。epoll工作在ET模式的時候,必須使用非阻塞套介面,以避免由於一個檔案控制代碼的阻塞讀/阻塞寫操作把處理多個檔案描述符的任務餓死。
參考:
《UNIX網路程式設計》
伺服器回射echo程式:
相關推薦
Linux多路複用之select/poll/epoll實現原理及優缺點對比
一、select的實現原理 支援阻塞操作的裝置驅動通常會實現一組自身的等待佇列如讀/寫等待佇列用於支援上層(使用者層)所需的BLOCK或NONBLOCK操作。當應用程式通過裝置驅動訪問該裝置時(預設為
I/O多路復用之select,poll,epoll簡介
重新 才會 增長 文件描述 brush 重新編譯 () 情況 包含 一、select 1.起源 select最早於1983年出現在4.2BSD中(BSD是早期的UNIX版本的分支)。 它通過一個select()系統調用來監視多個文件描述符的數組,當select()返回後,該
IO模型、IO多路複用、select poll epoll
基礎知識 同步、非同步 程序的阻塞 非同步 IO 基礎知識 高效能架構設計主要有兩方面: 1.提高單伺服器的效能。 2.伺服器採用叢集。 提升單伺服器的效能的關鍵之一就是服務端採用併發模型
Linux IO模式(BIO、NIO、IO多路複用、非同步IO)及 select、poll、epoll詳解
同步IO和非同步IO,阻塞IO和非阻塞IO分別是什麼,到底有什麼區別?不同的人在不同的上下文下給出的答案是不同的。所以先限定一下本文的上下文。 本文討論的背景是Linux環境下的network IO。 一 概念說明 在進行解釋之前,首先要說明幾個概念: -
網路通訊 :IO多路複用之select、poll、epoll詳解
目前支援I/O多路複用的系統呼叫有 select,pselect,poll,epoll,I/O多路複用就是通過一種機制,一個程序可以監視多個描述符,一旦某個描述符就緒(一般是讀就緒或者寫就緒),能夠通知程式進行相應的讀寫操作。但select,pselect,poll,epoll
看看八年前的(阻塞、非阻塞、多路複用、訊號驅動、非同步)IO總結
尊重原創,來自八年前的IO總結https://blog.csdn.net/historyasamirror/article/details/4270633 阻塞IO: 執行過程 使用者請求資料,系統核心(kernel)開始準備資料,使用者程序被阻塞
IO多路複用之select、poll、epoll詳解
ET(edge-triggered)是高速工作方式,只支援no-block socket。在這種模式下,當描述符從未就緒變為就緒時,核心通過epoll告訴你。然後它會假設你知道檔案描述符已經就緒,並且不會再為那個檔案描述符傳送更多的就緒通知,直到你做了某些操作導致那個檔案描述符不再為就緒狀態了(比如,你在
Linux IO多路複用之select
Linux IO多路複用之select 首先,我我們來介紹一下什麼是IO多路複用: IO多路複用是指核心一旦發現程序指定的一個或者多個IO條件準備讀取,它就通知該程序。 IO多路複用適用如下場合: 當客戶處理多個描述符時(一般是互動式輸入和網路套介面),
IO 多路複用之select(高效併發伺服器)
一、I/O 多路複用概述 I/O 多路複用技術是為了解決程序或執行緒阻塞到某個 I/O 系統呼叫而出現的技術,使程序不阻塞於某個特定的 I/O 系統呼叫。 select,poll,epoll都是I/O多路複用的機制。I/O多路複用通過一種機制,可以監視多個描述符,一旦某個
IO多路複用:select,poll,epoll的區別
I/O多路複用: (1)單個執行緒,通過記錄跟蹤每個I/O流(sock)的狀態,來同時管理多個I/O流) (2)I/O多路複用就通過一種機制,可以監視多個描述符,一旦某個描述符就緒(一般是讀就緒或者
IO多路複用之select總結
轉載自 阻塞式I/O程式設計有兩個特點: 一、如果一個發現I\O有輸入,讀取的過程中,另外一個也有了輸入,這時候不會產生任何反應,也就是需要你的程式語句去select的時候才知道有資料輸入。 二、程式去select的時候,如果沒有資料輸入,程式會一直等待,直到有資
HTTP協議篇(一):多路複用、資料流
管道機制、多路複用 管道機制(Pipelining) HTTP 1.1 引入了管道機制(Pipelining),即客戶端可通過同一個TCP連線同時傳送多個請求。如果客戶端需要請求兩個資源,以前的做法是在同一個TCP連線裡面,先發送A請求,然後等待伺服器做出迴應,收到後再
I/O多路複用之select、poll、epoll
很早之前有寫過篇IO多路複用的文章:https://www.cnblogs.com/klcf0220/archive/2013/05/14/3077003.html 參考連結:https://segmentfault.com/a/1190000003063859 select,poll,epoll都是IO多路
非同步套接字基礎:多路複用、select函式以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET
select函式: 系統提供select函式來實現多路複用輸入/輸出模型。原型: #include sys/time.h> #include unistd.h> int select(int maxfd,f
關於非阻塞I/O、多路複用、epoll的雜談
本文主要是想解答一下這樣幾個問題: - 什麼是非阻塞I/O - 非阻塞I/O和非同步I/O的區別 - epoll的工作原理 檔案描述符 檔案描述符在本文有多次出現,難免有的朋友不太熟悉,有必要簡單說明一下。 檔案描述符是一個非負整數,用於標識一個開啟的檔案。 這裡“檔案”一詞是更寬泛的概念,可以是程序中使用的
Linux網路程式設計---I/O多路複用之select
1.I/O多路複用(IO multiplexing) 我們之前講了I/O多路複用和其他I/O的區別,在這裡,我們再具體討論下I/O多路複用是怎麼工作? I/O 多路複用技術就是為了解決程序或執行緒阻塞到某個 I/O 系統呼叫而出現的技術,使程序不阻塞於某個特定的 I/O 系統呼叫。
嵌入式Linux網路程式設計,I/O多路複用,select()示例,select()客戶端,select()伺服器,單鏈表
文章目錄 1,IO複用select()示例 1.1 select()---net.h 1.2 select()---client.c 1.3 select()---sever.c 1.4 select()---linklist.h
Linux I/O複用中select poll epoll模型的介紹及其優缺點的比較
關於I/O多路複用: I/O多路複用(又被稱為“事件驅動”),首先要理解的是,作業系統為你提供了一個功能,當你的某個socket可讀或者可寫的時候,它可以給你一個通知。這樣當配合非阻塞的socket使用時,只有當系統通知我哪個描述符可讀了,我才去執行read操
IO模型——阻塞IO、非阻塞IO、多路複用IO、非同步IO、selectors模組
目錄 一、IO模型介紹 為了更好地瞭解IO模型,我們需要事先回顧下:同步、非同步、阻塞、非阻塞 同步(synchronous) IO和非同步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blo
多路複用IO模型中的select和epoll
多路複用IO模型中的select和epoll 一,前提知識——檔案描述符fd 1、檔案描述符簡介 首先從檔案描述符開始講起。因為,對於核心而言,所有開啟的檔案都是通過檔案描述符引用的。那麼檔案描述符到底是什麼? 檔案描述符(file descriptor)通常是一個小的非負整