非阻塞IO与异步IO
生活随笔
收集整理的這篇文章主要介紹了
非阻塞IO与异步IO
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
一、非阻塞IO的輪詢讀寫
---如果當(dāng)前進(jìn)程有多個輸入終端和多個輸出終端呢?
while((n=read(STDIN_FILENO,buf,buf_size))>0){
? ?if(write(STDOUT_FILENO,buf,n)!=n)
? ? ?err_sys("write_error") }
1、以上結(jié)構(gòu)可以看出,當(dāng)前進(jìn)程具有一個輸入終端(文件)和一個輸出終端(文件)
會很有可能會發(fā)生阻塞。降低了程序的吞吐量,可以采用非阻塞IO解決。
2、如果當(dāng)前進(jìn)程有多個輸入或者輸出呢?
---可以考慮利用多個線程來解決,線程同步的復(fù)雜性,
---可以考慮多進(jìn)程解決,同樣存在父子進(jìn)程之間的信號同步問題
依然利用一個進(jìn)程,利用非阻塞的文件描述符,遍歷每個文件描述符號進(jìn)行非阻塞IO,缺點是浪費CPU資源。
二、異步IO
?非阻塞IO并不是異步IO,切記!!!!!
?非阻塞IO只是調(diào)用時,函數(shù)會立刻或延遲返回,當(dāng)條件不滿足時,不會一直阻塞。
?異步IO是指將當(dāng)前進(jìn)程告訴內(nèi)核,我對哪個文件描述符的讀/寫感興趣,請在條件滿足時通過信號告訴我,
?我去利用預(yù)先定義的函數(shù)去處理。避免了輪詢,節(jié)省CPU資源。
?但同樣存在一些問題:
?1、設(shè)備范圍有限制,可能只對網(wǎng)絡(luò)或終端設(shè)備文件描述符號有效,針對類似設(shè)備才會有信號
?2、條件滿足信號對整個進(jìn)程只有一個,與進(jìn)程打開的文件描述符數(shù)量相比遠(yuǎn)遠(yuǎn)不夠,為了區(qū)分是哪一個描述符準(zhǔn)備好了
? ?,仍然需要將這兩個描述符設(shè)置為非阻塞的,非阻塞IO嘗試輪詢。
三、select/poll/pselect
?針對異步IO的問題,系統(tǒng)提供了IO多路轉(zhuǎn)接。
?select(int maxfdcode,fd_set * readfds,fd_set * writefds,
? ? ?fd_set * exceptfds,struct timeval *tvptr)
?(一)原理
? select我們需要告訴內(nèi)核:
? 1、我們關(guān)心的文件描述符
? 2、對每個描述符,我們關(guān)心的條件,是讀條件滿足還是寫條件滿足,還是異常條件滿足
? 3、我們獲取條件滿足的信息,愿意等待多長時間
? 從select返回后,內(nèi)核會告訴我們:
? 1、已經(jīng)準(zhǔn)備好的描述符總數(shù)量
? 2、對于讀寫或異常這三個條件中的每一個,哪些描述符已經(jīng)準(zhǔn)備好
?利用以上返回消息,就可以調(diào)用相應(yīng)的IO函數(shù),一般是read/write,因為確信該函數(shù)不會阻塞。
?(二)參數(shù)解釋
? 2、fd_set:可以理解為一個文件描述符位列表,位置索引就是文件描述符編號。
? ? ? ? ? ? 如果對某個文件描述符感興趣就設(shè)置相應(yīng)編號索引對應(yīng)的位為1。
? ? ? ? ? ? 當(dāng)條件滿足時,內(nèi)核會設(shè)置相應(yīng)的位為0,當(dāng)返回時,我們就可以判斷出是哪一個描述符準(zhǔn)備好了。
? 1、maxfdcode:是我們感興趣的描述符最大編號+1,因為是從0開始的。目的是減少內(nèi)核掃描的范圍。
? 3、tvptr:如果為NULL,永久等待;如果為0,立即返回不等待;如果》0,就是等待指定時間后返回,無論是否有滿足條件
? ? ? ? ? ?存在。
? 4、返回值:0表示沒有滿足條件存在,大于0表示有滿足條件存在,-1表示有錯
? 5、如果fd_set都設(shè)置為NULL,等加于sleep,精度更高
?(三)感興趣文件描述符設(shè)置
? FD_ISSET(int fd,fd_set *fds):判斷一個文件描述符,是否依然在描述符號條件集合中打開著或者說是條件不滿足。
? FD_ZERO(fd_set *fds):清零,需要重新注冊感興趣的文件描述符。第一步就是要作的。
? FD_SET(int fd,fd_set *fds):注冊感興趣條件的文件描述符
? FD_ClR(int fd,fd_set *fds):注銷感興趣條件的文件描述符
? (四、poll)
? 利用一個描述符列表,代替三個條件列表,更簡單
? 列表中每個元素是一個數(shù)據(jù)結(jié)構(gòu):描述符編號,興趣事件集合,當(dāng)前發(fā)生的事件
四、再論異步IO,重點asio
? ?int aio_read(struct aiocb *aiocb)
? ?int aio_write(struct aiocb *aiocb)
? ?--成功返回操作被系統(tǒng)放入操作請求隊列中
? ?--次(const struct aiocb *aiocb)--返回同步操作的完成狀態(tài) 0-ok -1-fail EINPROGRESS-處理中
? ?--aio_return(const struct aiocb *aiocb)--利用上步驟判斷,同步操作成功后調(diào)用一次,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 返回read/write正確調(diào)用的返回值(比如讀取的字節(jié)數(shù)量),出錯返回-1
? ?--aio_suspend(struct aiocb *aiocbstruct aiocb[] * aiocbs,nsize,timeout)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? --等待異步IO的完成。如果超時沒有任何完成,那么返回-1,errno-EAGAIN
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?-任何一個完成,都返回0
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?-都完成直接返回
? ?--aio_cancel(int fd,const struct aiocb *aiocbstruct aiocb * aiocb)--調(diào)用后,利用aio_error檢查,發(fā)回ECANCELEDconst struct aiocb *aiocb
? ? ? ? ? ? ? ?struct aiocb *aiocbstruct aiocb *aiocbstruct aiocb *aiocbstruct aiocb *aiocbstruct aiocb *aiocb)
? ?可以后跟 aio_fsync(int op,struct aiocb *aiocb)同步或者異步同步文件到存儲
? ?(一) 參數(shù)aiocb
? ?
? ?
? ?
五、更狠的列表IO,批量操作,異步通知
? ?int lio_listio(mode,aiocb[] *aiocbs,nsize,struct sigevent sigevent)
? ? --aio控制塊中的aio_lio_opcode會表明當(dāng)前的動作,是讀還是寫,如果是讀,那么就會去調(diào)用aio_read方法,寫同理。
? ? --mode 決定是否異步,如果是NOWIAT,那么立即返回,IO請求入隊
? ? --sigevent是在列表中所有IO完成后,才會得到通知調(diào)用,這不會妨礙各個IO請求的異步通知,適合于完成后作一些處理
const struct aiocb *aiocb
?
---如果當(dāng)前進(jìn)程有多個輸入終端和多個輸出終端呢?
while((n=read(STDIN_FILENO,buf,buf_size))>0){
? ?if(write(STDOUT_FILENO,buf,n)!=n)
? ? ?err_sys("write_error") }
1、以上結(jié)構(gòu)可以看出,當(dāng)前進(jìn)程具有一個輸入終端(文件)和一個輸出終端(文件)
會很有可能會發(fā)生阻塞。降低了程序的吞吐量,可以采用非阻塞IO解決。
2、如果當(dāng)前進(jìn)程有多個輸入或者輸出呢?
---可以考慮利用多個線程來解決,線程同步的復(fù)雜性,
---可以考慮多進(jìn)程解決,同樣存在父子進(jìn)程之間的信號同步問題
依然利用一個進(jìn)程,利用非阻塞的文件描述符,遍歷每個文件描述符號進(jìn)行非阻塞IO,缺點是浪費CPU資源。
二、異步IO
?非阻塞IO并不是異步IO,切記!!!!!
?非阻塞IO只是調(diào)用時,函數(shù)會立刻或延遲返回,當(dāng)條件不滿足時,不會一直阻塞。
?異步IO是指將當(dāng)前進(jìn)程告訴內(nèi)核,我對哪個文件描述符的讀/寫感興趣,請在條件滿足時通過信號告訴我,
?我去利用預(yù)先定義的函數(shù)去處理。避免了輪詢,節(jié)省CPU資源。
?但同樣存在一些問題:
?1、設(shè)備范圍有限制,可能只對網(wǎng)絡(luò)或終端設(shè)備文件描述符號有效,針對類似設(shè)備才會有信號
?2、條件滿足信號對整個進(jìn)程只有一個,與進(jìn)程打開的文件描述符數(shù)量相比遠(yuǎn)遠(yuǎn)不夠,為了區(qū)分是哪一個描述符準(zhǔn)備好了
? ?,仍然需要將這兩個描述符設(shè)置為非阻塞的,非阻塞IO嘗試輪詢。
三、select/poll/pselect
?針對異步IO的問題,系統(tǒng)提供了IO多路轉(zhuǎn)接。
?select(int maxfdcode,fd_set * readfds,fd_set * writefds,
? ? ?fd_set * exceptfds,struct timeval *tvptr)
?(一)原理
? select我們需要告訴內(nèi)核:
? 1、我們關(guān)心的文件描述符
? 2、對每個描述符,我們關(guān)心的條件,是讀條件滿足還是寫條件滿足,還是異常條件滿足
? 3、我們獲取條件滿足的信息,愿意等待多長時間
? 從select返回后,內(nèi)核會告訴我們:
? 1、已經(jīng)準(zhǔn)備好的描述符總數(shù)量
? 2、對于讀寫或異常這三個條件中的每一個,哪些描述符已經(jīng)準(zhǔn)備好
?利用以上返回消息,就可以調(diào)用相應(yīng)的IO函數(shù),一般是read/write,因為確信該函數(shù)不會阻塞。
?(二)參數(shù)解釋
? 2、fd_set:可以理解為一個文件描述符位列表,位置索引就是文件描述符編號。
? ? ? ? ? ? 如果對某個文件描述符感興趣就設(shè)置相應(yīng)編號索引對應(yīng)的位為1。
? ? ? ? ? ? 當(dāng)條件滿足時,內(nèi)核會設(shè)置相應(yīng)的位為0,當(dāng)返回時,我們就可以判斷出是哪一個描述符準(zhǔn)備好了。
? 1、maxfdcode:是我們感興趣的描述符最大編號+1,因為是從0開始的。目的是減少內(nèi)核掃描的范圍。
? 3、tvptr:如果為NULL,永久等待;如果為0,立即返回不等待;如果》0,就是等待指定時間后返回,無論是否有滿足條件
? ? ? ? ? ?存在。
? 4、返回值:0表示沒有滿足條件存在,大于0表示有滿足條件存在,-1表示有錯
? 5、如果fd_set都設(shè)置為NULL,等加于sleep,精度更高
?(三)感興趣文件描述符設(shè)置
? FD_ISSET(int fd,fd_set *fds):判斷一個文件描述符,是否依然在描述符號條件集合中打開著或者說是條件不滿足。
? FD_ZERO(fd_set *fds):清零,需要重新注冊感興趣的文件描述符。第一步就是要作的。
? FD_SET(int fd,fd_set *fds):注冊感興趣條件的文件描述符
? FD_ClR(int fd,fd_set *fds):注銷感興趣條件的文件描述符
? (四、poll)
? 利用一個描述符列表,代替三個條件列表,更簡單
? 列表中每個元素是一個數(shù)據(jù)結(jié)構(gòu):描述符編號,興趣事件集合,當(dāng)前發(fā)生的事件
四、再論異步IO,重點asio
? ?int aio_read(struct aiocb *aiocb)
? ?int aio_write(struct aiocb *aiocb)
? ?--成功返回操作被系統(tǒng)放入操作請求隊列中
? ?--次(const struct aiocb *aiocb)--返回同步操作的完成狀態(tài) 0-ok -1-fail EINPROGRESS-處理中
? ?--aio_return(const struct aiocb *aiocb)--利用上步驟判斷,同步操作成功后調(diào)用一次,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 返回read/write正確調(diào)用的返回值(比如讀取的字節(jié)數(shù)量),出錯返回-1
? ?--aio_suspend(struct aiocb *aiocbstruct aiocb[] * aiocbs,nsize,timeout)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? --等待異步IO的完成。如果超時沒有任何完成,那么返回-1,errno-EAGAIN
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?-任何一個完成,都返回0
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?-都完成直接返回
? ?--aio_cancel(int fd,const struct aiocb *aiocbstruct aiocb * aiocb)--調(diào)用后,利用aio_error檢查,發(fā)回ECANCELEDconst struct aiocb *aiocb
? ? ? ? ? ? ? ?struct aiocb *aiocbstruct aiocb *aiocbstruct aiocb *aiocbstruct aiocb *aiocbstruct aiocb *aiocb)
? ?可以后跟 aio_fsync(int op,struct aiocb *aiocb)同步或者異步同步文件到存儲
? ?(一) 參數(shù)aiocb
? ?
? ?
? ?
五、更狠的列表IO,批量操作,異步通知
? ?int lio_listio(mode,aiocb[] *aiocbs,nsize,struct sigevent sigevent)
? ? --aio控制塊中的aio_lio_opcode會表明當(dāng)前的動作,是讀還是寫,如果是讀,那么就會去調(diào)用aio_read方法,寫同理。
? ? --mode 決定是否異步,如果是NOWIAT,那么立即返回,IO請求入隊
? ? --sigevent是在列表中所有IO完成后,才會得到通知調(diào)用,這不會妨礙各個IO請求的異步通知,適合于完成后作一些處理
const struct aiocb *aiocb
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/justart/p/7805548.html
總結(jié)
以上是生活随笔為你收集整理的非阻塞IO与异步IO的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iOS-Xcode代码统计
- 下一篇: 面向对象-----封装