由select引發的思考

来源:https://www.cnblogs.com/xinghuaikang/archive/2018/03/03/8502983.html
-Advertisement-
Play Games

研究了一些操作系統的概念,研究了I/O模式,著重研究了select、poll、epoll 的區別, ...


一、前言

  網路編程里一個經典的問題,select,poll和epoll的區別?這個問題剛學習編程時就接觸了,當時看了材料很不明白,許多概念和思想沒有體會,現在在這個階段,再重新回頭看這個問題,有一種豁然開朗的感覺,

把目前我所能理解到的記錄下來。

  參考資料:https://www.cnblogs.com/zingp/p/6863170.html

       http://blog.csdn.net/a837199685/article/details/45954349

       https://www.zhihu.com/question/32163005

       http://shmilyaw-hotmail-com.iteye.com/blog/1896683

       http://www.cnblogs.com/my_life/articles/3968782.html

       https://www.cnblogs.com/Anker/p/3265058.html

二、從操作系統開始談起

  有幾個以後一直談到的概念,有必要先瞭解,以前就是這個步驟沒做,學習的時候一臉懵逼。

 

  1. 用戶空間和內核空間

    目前操作系統定址模式為虛擬定址,即處理器產生虛擬地址,之後翻譯成物理地址,匯流排到物理地址處理,處理器拿到處理後的數據

    操作系統 的核心為內核,可以訪問受保護的記憶體空間,可以訪問底層硬體設施,可以做任何事情。所以為了系統的穩定,講道理內核應該被保護起來。

    所以虛擬空間被分為內核空間和用戶空間。內核空間在最高的1G中,用戶空間在剩下的記憶體中。

    多數我們所用的進程在用戶空間處理,把請求發給內核,在內核空間中操作硬體。

  

  2. 進程上下文切換(進程切換)

    掛起當前進程,恢復某個進程,大家都知道這是個開銷大的過程,那具體有哪些步驟呢?

    首先,保存當前進程一些必要信息用以日後恢復,如描繪地址空間的頁表,進程表,文件表等等。

    然後切換頁全局目錄,安裝一個新的地址空間

    最後回覆目標進程的上下文

 

  3. 文件描述符(fd)

    電腦的一個術語,指向文件對象的一個抽象表示。形式上是一個非負整數的索引值,指向文件表中的文件

    當程式打開或創建一個文件時,內核向進程返回一個文件描述符,代表該文件。

    通過操作文件描述符,我們實現真實操作文件的目的

 

  4.  進程阻塞(process block)

    當某個進程等待一個執行結果時,自身阻塞(不幹事),直到得到結果,再繼續往下,

    重點是:這個是進程自身行為,且阻塞時不占用cpu資源(cpu也不幹事),

    所以I/O請求最拉低性能,俗話說占著茅坑不拉屎,在電腦里也是存在的,所以人們設計了多線程,多進程等方案來解決這個問題。

  

  5.  I/O過程

    一般有兩種模式,直接 I/O,緩存 I/O(預設),

    緩存 I/O:

      進程發起系統調用(通知系統我要讀寫了!)

      寫: 進程(數據) -------》 進程緩衝池   ------------》 內核緩衝池 ----------》存儲設備

      讀: 存儲設備(數據)---------》內核緩衝池 ----------》進程緩衝池 ---------》進程

 

    直接 I/O(進程緩存池消失了!):      

      進程發起系統調用(通知系統我要讀寫了!)

      寫: 進程(數據)    ------------》 內核緩衝池 ----------》存儲設備

      讀: 存儲設備(數據)---------》內核緩衝池  ---------》進程

    以上每個步驟之間都是有可能進程會有阻塞(block)發生,根據不同位置的阻塞,就產生了多種網路模式,以適應於不同場景。

 

     

三、 I/O模式(以讀為例)

   1.  block I/O 

    過程 :  

      進程發起系統調用(通知系統我要讀寫了!)

      讀: 存儲設備(數據)---------》內核緩衝池  ---------》進程------------》內核通知進程ok,進程解除阻塞

                 進程阻塞                   進程阻塞

    解釋:

      進程一直等文件準備好,再繼續下一步。

    應用場景:

      以上原理是一個用戶連接的情況,很容易理解。

      當一個伺服器對接多個客戶端的時候:

      初級方案:開多進程(大數據或長時間任務、開銷大,更安全)或多線程(很多連接,開銷低,數據放一起不太安全)為每一個客戶端建立一個連接來處理。

      不足:高併發的情況就體現出開銷大,性能低。一個是多線程切換,上下文切換的性能開銷,另一個是多線程數量大,會占據大量系統資源

 

      優化方案:採用線程池(減少創建和銷毀線程的頻率)或連接池(維持連接的緩存池,儘量重用已有的連接),降低系統開銷

      不足:降低開銷還是有限度的,在這個時代,高併發大,很容易到達瓶頸。

   

   2. non-block I/O   

    過程 :  

      發起系統調用(通知系統我要讀寫了!)

      讀: 存儲設備(數據)-------------》內核緩衝池  -----------》進程-------------》內核通知進程ok,進程解除阻塞

                 非阻塞                              阻塞

    解釋:

      在內核准備數據階段,立即返回一個error給進程,

      因此進程知道內核還沒準備好,

      所以進程再問內核,內核再回error,直到內核准備好,被詢問時返回準備好的信號,進程再接觸阻塞,

    應用場景:

      連接量小,沒差別,

      當連接數大的時候,這個模式理論上可以用一個線程實現多個連接:

      由於非阻塞,這個線程可以迴圈去詢問所有連接目標有沒有準備好,內核都是立馬回覆,error往下,準備好就交給進程,所以不會浪費時間,

      但是,(凡事都有但是),這個簡單的實現方案,效率還是很低的,畢竟從內核空間到用戶空間還是block的,而且會極大推高cpu占用率。

      特別是當響應事件(讀取或者其他)龐大的時候,執行速度就會很緩慢。

      下麵的select等就是基於此想法的發展。

 

   3. I/O multiplexing

    目標:低開銷,高效率得處理高併發請求

    方案:select 、poll、epoll 三種實現方案

    本質:用 select、poll、epoll 去監聽所有 socket對象,當socket對象發生變化時,通知用戶進程處理。

    特征:

       select(最早出現):多平臺支持

                通過輪詢,效率較低

                處理連接數量有限制,預設1024個,

                大量用戶態和內核態fd的拷貝,性能低,

                返回的是所有句柄列表,沒有告訴是哪一個發生變化,用戶進程還得再次遍歷。

       poll(略微改進):改進了數量連接限制,做到了數量無限制

       epoll(改進所有缺點):當socket變化時,通知進程哪一個完成了,

                  數量無限制(為系統最大打開文件數量)

                  fd句柄只拷貝一次,性能高

    性能對比:

      

      橫坐標是連接數,Dead Connections 是軟體命名的,縱坐標是此時處理連接數

      可以看出 epoll 性能比較穩定,而且性能較優。

    仔細過程討論:

        這裡只討論大致原理,具體實現不同語言有不同的差別。(不是因為我沒做過,不是的)

        首先。在多路復用模型中,對於每一個 socket,一般都設置成為 non-blocking,但是,整個用戶的 process 其實是一直被 block 的

        即用戶進程被select、poll阻塞,但是select、poll是非阻塞的,他們不斷輪詢、掛起來完成工作。

 

        select:

          1. 從用戶態拷貝 fd_set 至內核空間(告訴內核要監聽的socket)

          2..註冊回調函數pollwait(將進程掛到等待隊列中,當socket準備好後(執行mask狀態碼判斷),再喚醒進程)

          3. 內核遍歷fd,調用每一個的poll方法(本質上是pollwait回調函數,返回值socket的mask狀態掩碼,即現在準備好了沒,給fd_set賦值)

          4. 當無可讀寫mask碼(沒有任何準備好的),select睡眠,等睡眠時間到,再次醒來輪詢fd-set

          5. 有值時返回fd_set(已經賦值完,例如可以讀的value為1)、將其拷貝至用戶空間

          6. 用戶進程迴圈fd_set,

        分析:

          每次迴圈都要執行上面流程,

          一次迴圈兩次拷貝fi_set,即每次監聽都重新告訴內核要監聽的事件,在用戶量很大的時候是一個很大的開銷

          返回所有的fd_set,卻沒有告訴進程哪一個是完成的,進程還得迴圈判斷,用戶量很大(十萬,百萬)的時候,性能太低

          因此,select只支持1024個連接。

          這也解釋了上圖中為什麼連接量越大,性能越低的現象,許多時間用來處理無活躍的連接、迴圈判斷中,在高併發低活躍的場景中尤為如此。

        poll:

          將fd_set結構改為pollfd結構,可以不限數量,但是其他問題咩有解決。

        epoll:

          改進:

            fd只拷貝一次(開始就告訴內核所有註冊事件,監聽對象)。

            只返回包含所有變化的fd的鏈表。

            連接無限制

          epoll提供三個函數

          epoll_create(句柄),開始是有size參數,說明fd數量,現在內核動態分配,

          epoll_ctl(註冊事件類型),註冊監聽事件

          epoll_wait(等待事件發生),捕捉fd信號,

    三者區別小結:

      select、poll 孿生兄弟,有許多缺點,優點不多,應用場景也不多。是時代的產物

      epoll  是進階版,但是只有Linux有,

      具體情況具體分析。

  

  4. 非同步io

    解釋:進程完全不阻塞,請求發完就去做其他事,等數據全部準備好,內核發消息給進程,進程接著處理,

    實現:聽說很複雜,沒研究。

 

四、總結和挖坑

  研究了一些操作系統的概念,研究了I/O模式,著重研究了select、poll、epoll 的區別,

  有時間 具體實現和操作,實踐出真知,許多細節可能還有謬誤,待以後水平上升,再來修改。

          

          

          

       

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • DNS是應用層協議,埠號為tcp/53和udp/53 DNS查詢過程,比如訪問www.test.com1.客戶機查詢www.test.com2.查詢首選DNS伺服器,Linux下/etc/resolv.conf, Windows下是網路設置中的3.首選DNS伺服器中沒有test.com域的授權記錄 ...
  • 1.資料庫(Database)是按照數據結構來組織、存儲和管理數據的倉庫 2.RDBMS即關係資料庫管理系統(Relational Database Management System)的特點: 1).數據以表格的形式出現 2).每行為各種記錄名稱 3).每列為記錄名稱所對應的數據域 4).許多的行 ...
  • persist(): 把數據以序列化的形式緩存在JVM的堆空間中; cache(): 與使用預設存儲級別調用persist()是一樣的; collect(): 只有當你的整個數據集能在單台機器的記憶體中放得下時,才能使用collect(),因此,collect() 不能用在大規模數據集上;把RDD 篩 ...
  • Description 學校組織了一次新生舞會,Cathy作為經驗豐富的老學姐,負責為同學們安排舞伴。有n個男生和n個女生參加舞會 買一個男生和一個女生一起跳舞,互為舞伴。Cathy收集了這些同學之間的關係,比如兩個人之前認識沒計算得出 a[i][j] ,表示第i個男生和第j個女生一起跳舞時他們的喜 ...
  • 整理了一下前端時間學習Java併發的筆記,大約有40篇。 1. Java併發基礎知識 "併發基礎(一) 線程介紹" "併發基礎(二) Thread類的API總結" "併發基礎(三) java線程優先順序" "併發基礎(四) java中線程的狀態" "併發基礎(五) 創建線程的四種方式" "併發基礎(六 ...
  • CDN 什麼是CDN 初學Web開發的時候,多多少少都會聽過這個名詞 CDN。 CDN在我沒接觸之前,它給我的印象是用來優化網路請求的,我第一次用到CDN的時候是在找JS文件時。當時找不到相對應的JS文件下載地址(之前一般我都是把JS下載下來,然後在項目中引用的。PS:當然了,我覺得大部分初學者都一 ...
  • 覆選框checkbox和單選框radio是web網站里經常會使用到的兩個控制項,那麼在web自動化測試的時候如何利用Selenium來操作這倆控制項呢?今天我們就來簡單入門練習一下! html測試頁面代碼如下: 從HTML代碼看,這裡面的覆選框checkbox和單選框radio都是input標簽,那麼我 ...
  • 解法一: 這種解法使用的是Brute Force演算法,即是暴力搜索匹配,時間複雜度較高 解法二: 這種解法的思想是計算兩個相同的字元之間的長度,好比作一個視窗在字元串上右邊框向右拉伸,若右邊框碰到視窗內已存在的字元,那麼左邊框向右拉伸到到視窗已存在字元的右邊,時間複雜度較低 github地址:htt ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...