一嗡害、概念理解
linux中IO的類型分為四類:同步(sync)和異步(async),阻塞(block)和非阻塞(unblock)
同步:發(fā)出一個功能調(diào)用時释移,在沒有得到結果前會一直等待瞄摊,直到返回結果逮走。
異步:當異步過程調(diào)用發(fā)出后或悲,調(diào)用者不能立刻得到結果风喇。在完成后,通過通知機制或回調(diào)函數(shù)來通知調(diào)用者
阻塞:調(diào)用結果返回前樊破,當前線程會被掛起(線程進入非可執(zhí)行狀態(tài)愉棱,在這個狀態(tài)下,CPU不會給線程分配時間片哲戚,即線程暫停運行)羽氮。函數(shù)只有在得到結果后才返回
注意:同步和阻塞是不同的,對同步調(diào)用惫恼,線程是激活的档押,當調(diào)用者等待的時候,線程還可以處理其它請求,而阻塞線程是會掛起的令宿,是不會處理其它請求的叼耙。
非阻塞:在結果返回前,函數(shù)不會阻塞當前線程粒没,而會立刻返回
同步IO和異步IP的區(qū)別在于:數(shù)據(jù)拷貝的時候進程是否阻塞筛婉。
阻塞IO和非阻塞IO的區(qū)別在于:應用程序的調(diào)用是否立即返回
二、linux下的五種I/O模型
1癞松、阻塞I/O (blocking I/O)
2爽撒、非阻塞I/O (nonblocking I/O)
3、I/O 復用 (I/O multiplexing)
4响蓉、信號驅(qū)動I/O (signal driven I/O (SIGIO))
5硕勿、異步I/O (asynchronous I/O)
前四種都是同步,只有最后一種才是異步IO
阻塞IO模型:
進程會一直阻塞枫甲,直到數(shù)據(jù)拷貝完成
應用程序調(diào)用一個IO函數(shù)源武,導致應用程序阻塞,等待數(shù)據(jù)準備好想幻。數(shù)據(jù)準備好后粱栖,從內(nèi)核拷貝到用戶空間,IO函數(shù)返回成功指示脏毯。阻塞IO模型圖如下所示:
非阻塞IO模型
通過進程反復調(diào)用IO函數(shù)闹究,在數(shù)據(jù)拷貝過程中,進程是阻塞的食店。模型圖如下所示
IO復用模型
主要是select和epoll渣淤,對一個IO端口,兩次調(diào)用叛买,兩次返回,關鍵能實現(xiàn)同時對多個IO端口進行監(jiān)聽蹋订。模型如下所示
信號驅(qū)動IO
兩次調(diào)用率挣,再次返回
首先我們允許套接口進行信號驅(qū)動IO,并安裝一個信號處理函數(shù)露戒,進程繼續(xù)運行并不阻塞椒功。當數(shù)據(jù)準備好時,進程會收到一個SIGIO信號智什,可以在信號處理函數(shù)中調(diào)用IO函數(shù)處理數(shù)據(jù)动漾,模型如下所示
異步IO模型
數(shù)據(jù)拷貝時進程無阻塞,模型如下所示
5個IO模型的比較
如果這種模型難以理解荠锭,筆者利用去飯館吃面做解釋旱眯,有不符合的地方請諒解:
blocking IO:去飯館點過面后,一直要在飯館等待面做好
nonblocking IO:去飯館點過面后,可以出去删豺,但不知道什么時間面才好共虑,要過1分鐘來看下,處于忙等待呀页,其它什么事也做不了妈拌。
multiplexing IO:這里相當于飯館加了一個服務員,去飯館點面不用知會老板蓬蝶,而是知會服務員尘分,知會后在店里等待服務員通知面做好,在等待這段時間內(nèi)丸氛,服務員也可以招待其它人員培愁。服務員通知面做好了,自己把面端過來
signal-driven IO:在飯館點過面后雪位,可以出去竭钝,等面做好了,老板會打電話通知雹洗,但是面還是要自己端過來
asynchronous IO:去飯館點過面后香罐,可以出去,出去前指定自己坐哪個位置时肿,等面做好了庇茫,老板會把面端到你指定的位置,再打電話通知你
三螃成、select旦签、poll、epoll簡介
epoll是linux所特有寸宏,而select是POSIX所規(guī)定宁炫,一般操作系統(tǒng)均有實現(xiàn)。
select:查找
select本質(zhì)是通過設置或檢查存放fd標志位的數(shù)據(jù)結構來進行下一步處理氮凝。缺點是:
1羔巢、單個進程可監(jiān)視的fd數(shù)量被限制,即能監(jiān)聽端口的大小有限罩阵。
一般來說和系統(tǒng)內(nèi)存有關竿秆,具體數(shù)目可以cat /proc/sys/fs/file-max察看。32位默認是1024個稿壁,64位默認為2048個
2幽钢、對socket進行掃描時是線性掃描,即采用輪詢方法傅是,效率低匪燕。
當套接字比較多的時候蕾羊,每次select()都要遍歷FD_SETSIZE個socket來完成調(diào)度,不管socket是否活躍都遍歷一遍谎懦。會浪費很多CPU時間肚豺。如果能給套接字注冊某個回調(diào)函數(shù),當他們活躍時界拦,自動完成相關操作吸申,就避免了輪詢,這正是epoll與kqueue做的
3享甸、需要維護一個用來存放大量fd的數(shù)據(jù)結構截碴,會使得用戶空間和內(nèi)核空間在傳遞該結構時復制開銷大
poll:
poll本質(zhì)和select相同,將用戶傳入的數(shù)據(jù)拷貝到內(nèi)核空間蛉威,然后查詢每個fd對應的設備狀態(tài)日丹,如果設備就緒則在設備等待隊列中加入一項并繼續(xù)遍歷,如果遍歷所有fd后沒有發(fā)現(xiàn)就緒設備蚯嫌,則掛起當前進程哲虾,直到設備就緒或主動超時,被喚醒后又要再次遍歷fd
它沒有最大連接數(shù)的限制择示,原因是它是基于鏈表來存儲的束凑,但缺點是:
1、大量的fd的數(shù)組被整體復制到用戶態(tài)和內(nèi)核空間之間栅盲,不管有無意義汪诉。
2、poll還有一個特點“水平觸發(fā)”谈秫,如果報告了fd后扒寄,沒有被處理,那么下次poll時再次報告該ffd拟烫。
epoll:
epoll支持水平觸發(fā)和邊緣觸發(fā)该编,最大特點在于邊緣觸發(fā),只告訴哪些fd剛剛變?yōu)榫途w態(tài)硕淑,并且只通知一次课竣。還有一特點是,epoll使用“事件”的就緒通知方式喜颁,通過epoll_ctl注冊fd稠氮,一量該fd就緒曹阔,內(nèi)核就會采用類似callback的回調(diào)機制來激活該fd半开,epoll_wait便可以收到通知。
epoll的優(yōu)點:
1赃份、沒有最大并發(fā)連接的限制
2寂拆、效率提升奢米,只有活躍可用的FD才會調(diào)用callback函數(shù)
3、內(nèi)存拷貝纠永,利用mmap()文件映射內(nèi)存加速與內(nèi)核空間的消息傳遞鬓长。
select、poll尝江、epoll區(qū)別總結:
1涉波、支持一個進程打開連接數(shù)
select:32位機器1024個,64位2048個
poll:無限制炭序,原因基于鏈表存儲
epoll:有上限啤覆,但很大,2G內(nèi)存20W左右
2惭聂、IO效率
select:IO效率低
poll:IO效率低
epoll:只有活躍的socket才調(diào)用callback窗声,IO效率高。
3辜纲、消息傳遞方式
select:內(nèi)核需要將消息傳遞到用戶空間笨觅,都需要內(nèi)核拷貝動作
poll:同上
epoll:通過內(nèi)核與用戶空間共享一塊內(nèi)存來實現(xiàn)。
本文系轉(zhuǎn)載文章耕腾,感謝原作者的辛勤付出见剩!
來源:http://linuxkingdom.blog.51cto.com/6334977/1654813