91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

高級IO,阻塞于非阻塞

發布時間:2020-07-31 11:05:14 來源:網絡 閱讀:605 作者:小溢 欄目:開發技術




1、1、非阻塞IO

1.阻塞與非阻塞

(1)阻塞:就是當前的函數要執行的話,需要某些條件,但是沒有達到,就被阻塞住,內核掛起,當前進程暫停。CPU被拿去運行別的進程了。比如父進程執行wait這個阻塞函數,等待子進程結束后,去回收子進程剩余的8KB內存資源,如果這個時候子進程沒有結束,父進程的wait就會被阻塞,因為條件沒有達到,這個時候父進程就暫停了,內核就掛起了,CPU的時間就去執行別的進程了,不在父進程這里耗了,當子進程結束的時候,OS會給子進程的父進程發送一個SIGCHILD信號,這時父進程就被喚醒了,wait函數執行就將子進程回收掉了

(2)常見的阻塞:

wait、sleep、pasue等函數;

read或write寫文件的時候

(3)阻塞的好處:有利于操作系統的性能的發揮。因為阻塞住了進程會暫停,CPU可以去做別的事情,并且要完成的任務在一定情況下也會被完成的。

(4)但是一個進程中,進行多路IO操作的時候,有時阻塞式的就不好了,比如你當前進程排在前面的IO,由于因為你被阻塞住了,導致你的當前進程陷入了休眠狀態,雖然你將CPU的時間讓給了別的進程了,但是對于你自己的進程來說,你自己進程的剩下那些IO操作就要等你前面的IO操作完了之后才能進行,這樣就會降低了你當前的一個進程中的工作效率了,因為你排在前面的IO操作沒有進行完,你排在后面的IO操作是不肯能得到運行的,都是在一個進程中的。這個時候阻塞就是不好的了,所以有時也需要非阻塞式的操作。

(5)非阻塞式的操作,當你一個進程中進行多路IO的操作的時候,你排在前面的IO操作,由于你沒有用阻塞式的操作,而是非阻塞式的操作,所以即使你的條件沒有達到你也不會讓整個進程陷入沉睡暫停狀態,而是直接返回,直接執行這個進程的下面的內容,這樣對于當前進程的別IO來說,別的進程的執行效率就加大了,這種情況往往是在IO操作設備文件的時候,比如你在讀鼠標這個設備文件,就因為你這讀這個設備文件的時候被阻塞住了,而影響到了其他的設備文件的IO操作,這樣可想而知,真的不好


(6)如何實現非阻塞呢,就是在打開文件的時候加上O_NONBLOCK這個標志屬性和fcntl,fcntl可以讀出一個文件的flag,然后加上O_NONBLOCK這個標志,在將這個flag放回去


2、用read讀取鍵盤,來看阻塞的感覺

(1)因為鍵盤是標準輸入設備,對應的文件描述符是0,在每個進程中都是默認被打開的,所以我們直接read(0, buf, 2);直接讀這個鍵盤就行,讀取兩個字節放到buf中,我們執行這個時候,當我們鍵盤沒有輸入東西完畢按回車的時候(因為Linux的控制臺是行緩沖的,你沒有按下回車的時候,只是把你輸入的東西放到控制臺上顯示,還沒有送到read中,你按下回車后才會被輸入進去。),當我們沒有輸入東西按回車的時候,發現是被阻塞住的,被卡住了,不動了,這就是阻塞的感覺,這個時候當前的進程被暫停了,因為沒有等待條件,read讀取不到東西,當我們輸入東西按下回車的時候,當前的進程就被喚醒了,read讀取到東西了


3、read讀取鼠標

(1)首先鼠標這個設備文件是需要我們打開的,才能得到文件描述符fd,鼠標的設備文件在/dev/input/mouse0或者可能是/dev/input/mouse1


4、先讀鼠標在鍵盤的情況

(1)我們程序在設計的時候,是先讀取鼠標這個設備文件,在讀取鍵盤這個標準輸入文件,我們會發現,由于我們是阻塞式的,所以我們在鼠標沒有讀取成功的時候,鍵盤輸入了東西敲回車也不好使,只有當鼠標讀取完了之后,才會去讀取鍵盤,這就是阻塞式的壞處,解決方法就是非阻塞



5、并發式IO的解決方案(就是一個進程中對多個IO進行操作時引發的問題,就是上面的4的問題)

(1)解決方案有三個

(2)非阻塞式IO

@1:首先將鍵盤這個文件設置成非阻塞式的,因為鍵盤這個標準輸入,是在每一個進程都打開的,所以我們無法直接用open這個函數去打開這個文件,將其中的flag加上O_NONBLOCK這個標志屬性

所以我們要用fcntl這個函數來去利用文件描述符fd,去將這個文件的屬性進行改成非阻塞的。

int fcntl(int fd, int cmd, ... /* arg */ );

@2:第一個參數是文件描述符

@3:第二個參數是要的功能,我們的cmd用的宏是F_GETFD (void) F_SETFD (int),這兩個。

@4:利用F_GETFD這個cmd宏,將fd這個文件的flag讀取出來,之后用F_SETFD這個cmd宏將O_NONBLOCK這個非阻塞式的屬性添加上。

@5:先flag = fcntl(0, F_GETFD);獲取原來的這個文件的flag,然后 flag |= O_NONBLOCK;位或一個O_NONBLOCK。然后在fcntl(0, F_SETFD, flag);將屬性在寫到這個fd中




6、多路復用IO

(1)IO多路復用原理(IO multiplexing),作用和非阻塞IO有點像,是解決并發式IO的問題的

(2)什么時候用多路復用IO呢,在多路IO都是非阻塞式的情況下。為了應對多路非阻塞IO,CPU要一直不停的去輪詢這些非阻塞IO,因為是輪詢,所以必然要消耗時間,有空檔。所以有了多路復用IO。

(3)多路復用IO涉及到的兩個函數:select和poll

(4)IO多路復用的實現原理就是:外部阻塞式,內部非阻塞式自動輪詢多路阻塞式IO。

@1:外部阻塞式的意思是說,select和poll這兩個函數本身是阻塞式的

@2:內部非阻塞式,意思是說,select和poll內部在輪詢幾路IO的時候是非阻塞式的。

@3:select類似于一個監聽的函數,比如,當A這個鼠標IO,和B這個鍵盤IO,我們用select去監聽這兩個IO,我們的鼠標IO,和鍵盤IO,都是阻塞式的,并沒有設置成非阻塞式的,當我們調用select去監聽的時候,當鼠標IO事件和鍵盤IO事件都沒有發生的情況,select本身就是阻塞式的,select會一直在這里等待他監聽的兩個IO事件其中至少發生一個,select去監聽這個兩個IO的時候,是以非阻塞式的方式去輪詢監聽的,這就是外部阻塞式,內部非阻塞式自動輪詢多路阻塞式IO。select函數表現為對外是阻塞式的,對內部監聽的A和B這兩個阻塞式IO表現為非阻塞式的方式去輪詢A和B這兩個阻塞式IO。只要A或者B有一個IO中來數據了,select就會被喚醒,select就會向外面匯報,在沒數據時,select是阻塞式的,select所在的進程變成了暫停狀態


(5)select函數

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval

 *timeout);

@1:第一個參數表示文件描述符的個數,這個值我們應該設置select內部要監聽的多路IO中的那個文件描述符最大的那一個的fd+1,因為文件描述符是從0開始的,所以要加1。

@2:第二個參數中的fd_set是多個文件描述符的集合,是一個結構體。select這個函數在運行的時候,是區分文件描述符所要進行的操作的,所以第二個參數是傳遞了一個要讀的文件描述符,是要對多路文件描述符中那些要讀的文件描述符。第三個參數是傳遞多路文件描述符中要寫的那些文件描述符。第四個參數是那些發生異常的文件描述符,都是輸出型參數。第五個參數是設置超時時間的,因為select是阻塞式的,所以當監聽的IO沒有IO事件時,select就一直被阻塞了,卡住了,當前進程就一直暫停了,所以有時不想select一直被阻塞住,所以有了這個第五個參數,用來設置超時的,時間到了,select就會被喚醒返回

@3:返回值,當select成功的時候,就select監聽的內部有IO事件發生的時候,select返回,這個返回值就是表示select內部有幾個IO事件發生了,如果返回值是0就表示是超時了,沒有監聽到任何的IO事件發生自己超時后返回了,返回值是0,如果返回值是-1,就表示select函數運行錯誤了


@4:void FD_CLR(int fd, fd_set *set);//將fd,從fd_set中清除出去

   int  FD_ISSET(int fd, fd_set *set);//判斷fd,在fd_set中有沒有被置位,發生了IO事件對應fd

//會被置位返回值是1,返回值0表示沒有發生這個fd的IO

//事件

   void FD_SET(int fd, fd_set *set);//將fd,添加到fd_set中

   void FD_ZERO(fd_set *set); //是用來將fd_set這個集合中文件描述符置位的清除置位

這四個函數是用來操作fd_set這個文件描述符集合的


(6)poll函數

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

@1:第一個參數是輸出型參數,是文件描述符的集合,第二個參數是poll函數內部監聽的多路IO的最大的文件描述符fd+1,第三個參數是超時時間,是毫秒級別的

@2: struct pollfd {

               int   fd;         /* file descriptor */

               short events;     /* requested events */

               short revents;    /* returned events */

           };

我們給poll傳遞第一個參數的時候,要設置這個結構體的fd和events,fd表示我們要監測哪個fd,events表示要監測這個fd的什么事件

@3:events如果是

 POLLIN 表示監測的是讀

 POLLOUT 表示監測的是寫

@4:revents是內核設置的,當監測的IO事件發生POLLIN或者POLLOUT,我們可以判斷events和revents是否相等來確定是否發生我們想要的IO事件

@5:返回值,當poll成功的時候,返回值是一個正數,非零,表示內核幫我們設置了一個revents,表示有IO事件發生,有幾路IO事件發生了,返回值就是幾,超時時返回0,返回-1表示poll函數運行錯誤了,和select的返回值定義是一樣的


7、多路復用IO的代碼實戰

(1)select函數實現的讀取鍵盤和鼠標的IO多路復用

(2)poll函數實現的讀取鍵盤和鼠標的IO多路復用


8、異步通知(異步IO)

(1)什么是異步IO,可以認為是操作系統用軟件實現的一種軟件中斷響應系統

(2)異步IO的工作方法就是,當前進程在做自己該做的事情,當有一個異步IO的信號SIGIO的時候,就會去執行這個異步IO信號對應的信號處理函數。

(3)所以就是一個進程中向操作系統注冊了一個異步IO的信號對應的信號處理函數,用signal或者sigaction注冊了一個SIGIO對應的信號處理函數,當前進程可以做想做的事情,當有異步IO事件發生了的時候,操作系統會給當前進程發一個SIGIO的異步信號,進程接受到這個SIGIO信號后就會去執行這個信號對應的信號處理函數。就跟被中斷了一樣,去執行了中斷處理函數一樣,只不過這個中斷是由信號來產生的。

(4)異步IO涉及到的函數:

fcntl(主要是設置一些異步通知,F_GETFL,F_SETFL,O_ASYNC,F_SETOWN)

@1:F_GETFL來獲取flag屬性信息

@2:F_SETFL來設置flag屬性信息

@3:O_ASYNC來指示當前的文件描述符可以被接受異步通知,也是一個flag文件屬性,將文件描述符添加這個屬性

@4:F_SETOWN用這個告訴當異步IO事件發生的時候讓OS通知誰,fcntl帶上這個參數后,后面一個變參要加上當前進程的pid,可以getpid來獲得,表示發生異步IO事件的時候OS通知當前的這個進程

signal或者sigaction(綁定SIGIO對應的信號處理函數的)




8、存儲映射IO

(1)mmao函數

void *mmap(void *addr, size_t length, int prot, int flags,

                  int fd, off_t offset);

把一個文件和一個內存區域映射起來。

(2)在LCD顯示的時候和IPC共享內存通信的時候會用到

比如,你的LCD要顯示的圖片的話,是和驅動層的一個LCD驅動中劃分出來的一個物理內存中的顯存區域,將這個內存區域設置到LCD控制器中的一個參數中,當這個內存區域有一個圖片的數據的時候,硬件就會自動刷新到LCD屏幕去顯示,但是我們現在是在應用層下,我們在文件系統中的一個打開了一個圖片文件,得到了這個圖片的數據,我們要將這個打開的圖片的數據,也就是要將一塊內存復制到LCD的顯存的那一個內存區域中,這樣每次都直接復制是很浪費CPU時間的,所以就可以mmap將LCD的顯存內存區域和我們的這個打開這個文件時的內存區域映射起來,這樣就相當于關聯起來了,實際上就變成了一個內存區域了,









向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

阿拉善右旗| 松江区| 保德县| 静乐县| 桐柏县| 始兴县| 湖口县| 蚌埠市| 西城区| 元阳县| 舟曲县| 南昌县| 元朗区| 华容县| 科技| 武穴市| 古交市| 镇远县| 黔南| 临颍县| 周至县| 北京市| 淮安市| 安阳市| 佛山市| 庆云县| 郸城县| 姜堰市| 崇仁县| 肥东县| 平湖市| 大兴区| 元朗区| 桂林市| 远安县| 新龙县| 洞口县| 高碑店市| 宁陕县| 特克斯县| 三都|