以read函式分析:
read函式從描述符為fd的當前檔案位置拷貝最多n個位元組到儲存器位置buf。返回-1表示乙個錯誤,而返回0表示eof,否則,返回值表示是實際串送位元組的數量。
在沒有dma時,read函式實際上會經過下邊的步驟
使用者程序呼叫read函式,使用者態切換成核心態,cpu傳送指令到磁碟控制器
磁碟控制器接收指令後,把資料放入磁碟控制器的內部緩衝區,產生乙個中斷。
cpu收到中斷指令後,把磁碟緩衝區的資料讀進自己的暫存器,然後把暫存器的資料寫入記憶體。核心態切換為使用者態。
cpu需要參與資料搬運過程,如果資料量大的話,太消耗cpu資源了。
由此,出現了dma技術。
先了解下什麼是dma
dma(直接記憶體訪問)direct memory access:在進行 i/o 裝置和記憶體的資料傳輸的時候,資料搬運的工作全部交給 dma 控制器。
同樣的read命令。
使用者程序呼叫read方法,cpu將請求發給dma.
dma將請求發給磁碟
磁碟控制器接收指令後,把資料放入磁碟控制器的內部緩衝區,產生乙個中斷。
dma 收到磁碟的訊號,將磁碟控制器緩衝區中的資料拷貝到核心緩衝區中.
當dma讀取足夠多的資料,就傳送中斷訊號給cpu
cpu 收到 dma 的訊號,知道資料已經準備好,於是將資料從核心拷貝到使用者空間,系統呼叫返回。
cpu不在參與資料搬運的工作,而是由dma完成。
以正常一次讀取磁碟檔案傳送資料為例,需要呼叫下列命令
read(file, tmp_buf, len);
write(socket, tmp_buf, len);
發生了4次使用者態和核心態的上下文切換(兩次呼叫都是:使用者態->核心態,核心完成任務後:核心態->使用者態),4次資料的拷貝(磁碟資料->作業系統核心緩衝區->使用者緩衝區->核心的socket的緩衝區->網絡卡的緩衝區)
檔案傳輸的效能
減少上下文切換次數(每一次系統呼叫,都會經過兩次上下文切換)
減少資料拷貝次數
優化方案
mmap+write
sendfile
buf = mma(file,len)
mmap函式會直接吧核心緩衝區裡的資料對映到使用者空間,作業系統不需要進行任何資料的拷貝操作
發生了4次使用者態和核心態的上下文切換(兩次呼叫都是:使用者態->核心態,核心完成任務後:核心態->使用者態),3次資料的拷貝(磁碟資料->作業系統核心緩衝區(應用程序和作業系統共享)->核心的socket的緩衝區->網絡卡的緩衝區)
linux核心版本2.1後
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
前兩個引數分別是目的端和源端的檔案描述符,後面兩個引數是源端的偏移量和複製資料的長度,返回值是實際複製資料的長度。
發生了2次使用者態和核心態的上下文切換(一次呼叫),3次資料的拷貝(磁碟資料->作業系統核心緩衝區->核心的socket的緩衝區->網絡卡的緩衝區)
網絡卡支援 sg-dma技術,從 linux 核心 2.4 版本開始起支援
2次資料的拷貝(磁碟資料->作業系統核心緩衝區->網絡卡的緩衝區)
這就是零拷貝,2次上下問切換,2次資料拷貝,全是dma拷貝,沒有cpu拷貝。
當檔案傳輸時,第一步都是需要先把磁碟檔案資料拷貝待核心快取區(pagecache)
讀寫磁碟相比與讀寫記憶體速度慢太多了,所以要用讀寫磁碟替換為讀寫記憶體。
pagecache來快取最近被訪問的資料,當空間不足時淘汰最久未被訪問的快取。
pagecache使用可預讀功能
因為區域性性(剛訪問的資料,短時間內再次訪問的概率很高),所以快取到pagecache裡
pagecache來快取最近被訪問的資料,當空間不足時淘汰最久未被訪問的快取。
因為磁碟資料讀取時(通過磁頭旋轉到資料所在的扇區,然後開始順序讀取)。旋轉磁頭非常耗時。預讀功能(kafka順序讀寫,很快)
讀磁碟資料->先在pagecache找,找不到,再從磁碟中讀取,快取到pagecache。
pagecache被大檔案佔據,其他熱點小檔案無法使用pagecache,磁碟讀寫下降
pagecache沒有享受到快取帶來的好處,卻耗費了dma多拷貝到pagecache一次
非同步io,前半部分,核心向磁碟發起請求,不等資料就位,就返回;
後半部分,核心資料拷貝到緩衝區後,程序將接收到核心的通知,處理資料,繞開pagecache,直接io;
非同步io+直接io(繞過pagecache)。
傳統IO的特點
1傳統io 2 傳統io有兩種方式 1 單執行緒方式 這種方式的io是阻塞的,伺服器的serversocket只能為乙個客戶端socket服務,不能接收到新的客戶端socket連線 public static void main string args catch ioexception e pri...
IO程式設計 一 傳統IO程式設計
假設我們要實現乙個需求 客戶端每隔兩秒向服務端傳送一次資訊,服務端接收列印 首先我們需要乙個服務端乙個客戶端 服務端socketserver 服務端監聽8000埠.迴圈接收新的客戶端連線請求.同時列印客戶端傳送來的訊息 public class socketserver catch ioexcept...
零拷貝問題
零拷貝 定義 避免cpu將資料從一塊儲存空間拷貝到另乙個儲存空間的技術。通常用於網路檔案傳輸 以減少cpu消耗和記憶體頻寬的占用 減少使用者空間 使用者可操作的記憶體快取區域 和cpu核心空間 cpu核心可操作的記憶體快取和暫存器快取 的拷貝過程,減少使用者上下文和cpu核心上下文的切換,讓cpu解...