<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [TOC] ## 概念說明 ### 1. 內核空間、用戶空間 操作系統的核心是內核,獨立于其他應用程序,可以訪問底層會保護的硬件,Linux**為了防止用戶進程直接操作內核**,將虛擬地址空間,分成了用戶空間和內核空間,用戶空間就是用戶進程所在的空間。 ### 2. 進程切換 為了控制進程的執行,內核必須有能力掛起正在CPU上運行的進程,并恢復以前掛起的某個進程的執行。這種行為被稱為進程切換。因此可以說,任何進程都是在操作系統內核的支持下運行的,是與內核緊密相關的 從一個進程的運行轉到另一個進程上運行,這個過程中經過下面這些變化: > 1. 保存處理機上下文,包括程序計數器和其他寄存器。 > 2. 更新PCB信息。 > 3. 把進程的PCB移入相應的隊列,如就緒、在某事件阻塞等隊列。 > 4. 選擇另一個進程執行,并更新其PCB。 > 5. 更新內存管理的數據結構。 > 6. 恢復處理機上下文。 ### 3. 進程的阻塞 > 正在執行的進程,由于期待的某些事件未發生,如請求系統資源失敗、等待某種操作的完成、新數據尚未到達或無新工作做等,則由系統自動執行阻塞原語(Block),使自己由運行狀態變為阻塞狀態。可見,進程的阻塞是進程自身的一種主動行為,也因此只有處于運行態的進程(獲得CPU),才可能將其轉為阻塞狀態。`當進程進入阻塞狀態,是不占用CPU資源的`。 ### 4. 進程緩存區、內核緩沖區 緩沖區的出現是為了減少頻繁的系統調用,由于系統調用需要保存之前的進程數據和狀態等信息,而結束調用之后回來還需要回復之前的信息,為了減少這種耗時耗性能的調用于是出現了緩沖區。在linux系統中,每個進程有自己獨立的緩沖區,叫做**進程緩沖區**,而系統內核也有個緩沖區叫做**內核緩沖區**。 **操作系統使用read函數把數據從內核緩沖區復制到進程緩沖區,write把數據從進程緩沖區 復制到內核緩沖區中** ### 5. 文件描述符fd 文件描述符(File descriptor)是計算機科學中的一個術語,`是一個用于表述指向文件的引用的抽象化概念`。 文件描述符在形式上是一個非負整數。實際上,`它是一個索引值,指向內核為每一個進程所維護的該進程打開文件的記錄表`。當程序打開一個現有文件或者創建一個新文件時,內核向進程返回一個文件描述符。在程序設計中,一些涉及底層的程序編寫往往會圍繞著文件描述符展開 ## Linx/Unix 5種IO模型 當一個io發生時候的,涉及到的步驟和對象 以網絡socket的 read為例子。 涉及到的對象 - 一個是調用這個IO的process (or thread) (用戶進程) - 一個就是系統內核(kernel) 經歷的步驟 - 等待數據準備,比如accept(), recv()等待數據 - 將數據從內核拷貝到進程中, 比如 accept()接受到請求,recv()接收連接發送的數據后需要復制到內核,再從內核復制到進程**用戶空間** ### 阻塞IO ![img](https://upload-images.jianshu.io/upload_images/1446087-9522cafa9e14abd0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/552) > 當用戶進程調用了recvfrom這個系統調用,kernel就開始了IO的第一個階段:準備數據(對于網絡IO來說,很多時候數據在一開始還沒有到達。比如,還沒有收到一個完整的UDP包。這個時候kernel就要等待足夠的數據到來)。這個過程需要等待,也就是說數據被拷貝到**操作系統內核的緩沖區**中是需要一個過程的。而在用戶進程這邊,整個進程會被阻塞(當然,是進程自己選擇的阻塞)。當kernel一直等到數據準備好了,它就會**將數據從kernel中拷貝到用戶內存**,然后kernel返回結果,用戶進程才解除block的狀態,重新運行起來。 ### 非阻塞IO ![img](https://upload-images.jianshu.io/upload_images/1446087-0c604ff4a2d8dc5d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/603) 當用戶進程發出read操作時,如果kernel中的數據還沒有準備好,**那么它并不會block用戶進程,而是立刻返回一個error**。從用戶進程角度講 ,它發起一個read操作后,并不需要等待,而是馬上就得到了一個結果。用戶進程判斷結果是一個error時,它就知道數據還沒有準備好,于是它可以再次發送read操作。一旦kernel中的數據準備好了,并且又再次收到了用戶進程的system call,那么它馬上就將數據拷貝到了用戶內存,然后返回 ### I/O 多路復用( IO multiplexing) IO multiplexing就是我們說的select,poll,epoll,有些地方也稱這種IO方式為event driven IO。select/epoll的好處就在于單個process就可以同時處理多個網絡連接的IO。它的基本原理就是select,poll,epoll這個function會不斷的輪詢所負責的所有socket,當某個socket有數據到達了,就通知用戶進程。 ![img](https://upload-images.jianshu.io/upload_images/1446087-3b0399b077daf0a8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/609) 在一個調用中阻塞`select`,等待數據報套接字可讀。當`select`?返回套接字可讀時,我們然后調用`recvfrom`?將數據報復制到我們的應用程序緩沖區中 .使用`select`需要兩次系統調用而不是一次 在IO multiplexing Model中,實際中,**對于每一個socket,一般都設置成為non-blocking,因為只有設置成non-blocking 才能使單個線程/進程不被阻塞(或者說鎖住),可以繼續處理其他socket。如上圖所示,整個用戶的process其實是一直被block的。只不過process是被select這個函數block,而不是被socket IO給block。** ### 異步 I/O ![img](https://upload-images.jianshu.io/upload_images/1446087-e707464b299104e1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/572) 用戶進程發起read操作之后,立刻就可以開始去做其它的事。而另一方面,從kernel的角度,當它受到一個asynchronous read之后,首先它會立刻返回,所以不會對用戶進程產生任何block。然后,kernel會等待數據準備完成,然后將數據拷貝到用戶內存,當這一切都完成之后,kernel會給用戶進程發送一個signal,告訴它read操作完成了 ### 異步、同步、阻塞、非阻塞 同步就是一個任務的完成需要依賴另外一個任務時,只有等待被依賴的任務完成后,依賴的任務才能算完成,這是一種可靠的任務序列 異步是不需要等待被依賴的任務完成,只是通知被依賴的任務要完成什么工作,依賴的任務也立即執行,只要自己完成了整個任務就算完成了 阻塞調用是指調用結果返回之前,當前線程會被掛起,一直處于等待消息通知,不能夠執行其他業務 非阻塞調用指在不能立刻得到結果之前,該函數不會阻塞當前線程,而會立刻返回 異步、同步是發生在用戶空間內,當用戶發起一個IO的調用的時候,同步的時候,如果這個操作比較耗時間,會阻塞后面的流程 ```php file_get_contents("http://www.qq.com/"); echo "end"; ``` 調用read的操作的時候。后面的操作echo 會等待上面的結果完成,才能繼續。 ```php aysnc_read("http://www.qq.com",function($data){ echo $data; }) echo "end"; ``` 這個aysnc_read 是一個異步讀的操作,當讀的時候,底下的操作不會阻塞住,會先輸出end。當數據到達的時候,再echo $data; 阻塞、非阻塞、發送在內核和用戶空間之間。阻塞是指操作系統會掛起進程,直到數據準備好,非阻塞、操作系統不阻塞,當前進程可以繼續執行。 舉例說明 - 阻塞io 張三去書店買書,然后問書店問老板,有沒有《紅樓夢》,老板說我查下,這個查詢的時間,比較長,然后張三啥都不能干,就在等著。直到老板告訴它,找到了。然后買了這個書,走了。張三的操作都是同步阻塞的,必須等待老板的結果,下面的操作才能執行。 - 非阻塞IO 還是張三去買書,老板去查詢。這是時候,張三可以玩手機,然后隔段時間問,找到了沒有,張三的進程沒有被阻塞。但是這個任務是同步的,必須等待這個結果。就是老板沒有告訴張三結果,張三是不能離開干其他的事。這個過程是同步非阻塞的。 - 異步IO 張三去買書。然后去書店問老板有沒有了。老板需要查詢,張三告訴老板自己的手機號,找到了打電話給我,然后就去干其他的事了。這個過程是異步的。張三的進程沒有被阻塞在這個買書的環節上。這就是異步非阻塞。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看