後臺開發之IO緩衝區管理

来源:http://www.cnblogs.com/gaorong/archive/2017/06/11/6986561.html
-Advertisement-
Play Games

Linux系統IO中write原型為 ssize_t write(int filedes, const void * buff, size_t nbytes) ; 當調用write寫數據的時候,調用完成後write直接返回,但是磁碟是個慢速設備,操作系統會將數據保存在內核中的緩衝區中,並負責非同步地將 ...


Linux系統IO中write原型為  ssize_t write(int  filedes, const void * buff, size_t nbytes) ;

當調用write寫數據的時候,調用完成後write直接返回,但是磁碟是個慢速設備,操作系統會將數據保存在內核中的緩衝區中,並負責非同步地將數據寫至磁碟。當然如果此時系統宕機了則會丟失數據。write是系統調用,每次調用都會陷入內核,所以選取一個合適的塊長度buffsize,並儘量減少它的調用可以優化效率。在ANSI C的標準IO中我們調用printf/fprintf/fputs等會以流的方式進行處理,我們只需要寫入流中,而不用像write一樣選擇一個buffsize,因為標準IO庫幫我們處理了很多細節,例如緩衝區分配,以優化長度執行IO等。這樣的話就會減少wirte/read系統調用的數量,提高效率。但是與此同時會引入另外一個問題:數據拷貝,例如當使用函數fgets和fputs時,通常需要經過兩次緩衝區:一次是標準IO緩衝區,還有一次是調用read和write的內核緩衝區。但是總的來說使用標準IO相對於系統IO來說介面簡單,且效率相當。

標準IO提供了三種類型的緩衝區:全緩存,行緩存和不帶緩存,全緩存只有在緩衝區滿時才會主動flush,通常用在對一個磁碟文件IO。行緩存在緩衝區中遇到換行符就會flush,還有一種情況是需要從標準輸入輸出得到輸入數據時也會flush緩衝區,行緩存一般用在交互的終端中。不帶緩存則相當於直接 write系統調用輸出,標準出錯流stderr通常是不帶緩存的,這就使得出錯信息可以儘快顯示出來。除了預設的flush條件外,顯式調用fflush函數和程式正常終止時也會flush緩衝區。我們可以使用setbuf/setvbuf來更改預設的緩衝區長度,參見APUE 5.4節。

在使用標準IO的程式中,當我們將一個標準輸出重新定向到一個文件時,會將行緩存變為全緩存,在某些情況下可能會導致一些非預期錯誤,比如調用printf(“*****\n”)時,當以交互方式運行該程式時,會正常輸出。但是當將標準輸出重新定向到一個文件時,緩衝區區變為全緩存,printf就不會正常輸出,該行數據仍在緩衝區中。如果此時再fork一個子進程,數據空間被覆制到子進程中時,該緩衝區數據也被覆制到子進程中。接著在子進程中如果輸出則會刷新之前在緩衝區的內容,產生一些非預期的輸出。

在網路編程中,應該直接使用系統IO,標準IO為提升性能而引入緩衝機制增加了網路應用程式的複雜性。並且,某種意義上說標準IO流是全雙工的,能同時執行輸入和輸出,然而對流的限制和對套接字的限制,有時候會互相衝突。(參見CSAPP P611)

某些高級的網路庫中(比如說muduo庫)在使用系統IO的基礎上會創建自己的緩衝區,幫助用戶屏蔽系統IO的某些不便,例如調用write發送大量數據的時候,發送緩衝區滿時需要應用層等待,read接收數據的時候粘包和數據接受的緩慢。當增加應用層緩衝區後,由網路庫處理這些實現細節,簡化用戶操作。

Linux還提供了零拷貝技術來減少記憶體拷貝,進而提升效率,我們知道利用read/write從磁碟發送數據到網卡會經過四次拷貝操作:當應用程式需要訪問某塊數據的時候,操作系統內核會先檢查這塊數據是不是因為前一次對相同文件的訪問而已經被存放在操作系統內核地址空間的緩衝區內,如果在內核緩衝區中找不到這塊數據,Linux 操作系統內核會先將這塊數據從磁碟讀出來放到操作系統內核的緩衝區里。如果這個數據讀取操作是由 DMA 完成的,那麼在 DMA 進行數據讀取的這一過程中,CPU 只需要進行緩衝區管理,以及創建和處理 DMA ,除此之外,CPU 不需要再做更多的事情,DMA 執行完數據讀取操作之後,會通知操作系統做進一步的處理。Linux 操作系統會根據 read系統調用指定的應用程式地址空間的地址,把這塊數據存放到請求這塊數據的應用程式的地址空間中去,待用戶對數據完成操作後,操作系統需要將數據再一次從用戶應用程式地址空間的緩衝區拷貝到與網路堆棧相關的內核緩衝區中去,這個過程也是需要占用 CPU 的。數據拷貝操作結束以後,數據會被打包,然後發送到網路介面卡上去。從上面的描述可以看出,在這種傳統的數據傳輸過程中,數據至少發生了四次拷貝操作,即便是使用了 DMA 來進行與硬體的通訊,CPU 仍然需要訪問數據兩次。

   (ps:記得之前看過一個面試題說是printf輸出過程經過幾次緩衝區,現在大家明白了吧!)

使用零拷貝技術可以避免數據在系統內核地址空間的緩衝區和用戶應用程式地址空間的緩衝區進行拷貝。有時候,應用程式在數據傳輸的過程中不需要對數據進行訪問,傳輸的數據可以不用複製到用戶應用區,直接通過內核發送到網卡就可以,這樣可以提高性能,而此時就需要零拷貝技術。linux下可以用mmap,sendfile,splice實現零拷貝。具體參見  linux 中的零拷貝技術 第1部分  第2部分


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

-Advertisement-
Play Games
更多相關文章
  • 轉自:http://cheneyph.iteye.com/blog/824746 系統 資源 磁碟和分區 網路 進程 用戶 服務 程式 ...
  • 如有錯誤希望各位大佬批評指正,郵件請發:[email protected] ...
  • 下麵來說說如何用不用消息隊列來進行進程間的通信,消息隊列與命名管道有很多相似之處。有關命名管道的更多內容可以參閱我的另一篇文章:Linux進程間通信——使用命名管道 一、什麼是消息隊列 消息隊列提供了一種從一個進程向另一個進程發送一個數據塊的方法。 每個數據塊都被認為含有一個類型,接收進程可以獨立地 ...
  • 配置vim配置 編輯配置文件 配置如下 主要配置為自動換行,設置行號,設置tab鍵為4個空格,同時將tab鍵自動轉換成空格 ...
  • 參考資料: Nginx中文文檔: http://www.nginx.cn/nginxchscommandline Nginx的啟動、停止、平滑重啟、信號控制和平滑升級:http://zachary-guo.iteye.com/blog/1358312 命令行參數: 常用命令: -c filename ...
  • 官網安裝教程鏈接:https://docs.openstack.org/developer/devstack/ 我在ubuntu14.04 LTS 桌面版/伺服器版都安裝DevStack成功後,在這裡記錄下安裝過程。 介紹下安裝環境: VMware Workstation Pro 12 ubuntu ...
  • 1. 安裝完整的vim# apt-get install vim-gnome 2. 安裝ctags,ctags用於支持taglist,必需!# apt-get install ctags 3. 安裝taglist#apt-get install vim-scripts#apt-get install ...
  • 家裡電腦是Win10的,原來可以在公司通過遠程桌面訪問,最近自動升級了一次補丁後,遠程可以連接,但是輸入正確的用戶密碼後總提示憑據錯誤 (Win10是被訪問的一方,修改的也是被訪問的機器) 修複方式為 命令:gpedit.msc 打開“本地組策略編輯器” Windows設置->安全設置->本地策略- ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...