日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

概述

考慮這樣一種常用的情形:你需要將靜態(tài)內(nèi)容(類似圖片、文件)展示給用戶。那么這個情形就意味著你需要先將靜態(tài)內(nèi)容從磁盤中拷貝出來放到一個內(nèi)存buf中,然后將這個buf通過socket傳輸給用戶,進而用戶或者靜態(tài)內(nèi)容的展示。這看起來再正常不過了,但是實際上這是很低效的流程,我們把上面的這種情形抽象成下面的過程:

read(file, tmp_buf, len);
write(socket, tmp_buf, len);

首先調(diào)用read將靜態(tài)內(nèi)容,這里假設(shè)為文件A,讀取到tmp_buf, 然后調(diào)用write將tmp_buf寫入到socket中,如圖:

還不懂零拷貝(Zero-Copy)?怎么稱得上高級程序員

 

在這個過程中文件A的經(jīng)歷了4次copy的過程:

  1. 首先,調(diào)用read時,文件A拷貝到了kernel模式;
  2. 之后,CPU控制將kernel模式數(shù)據(jù)copy到user模式下;
  3. 調(diào)用write時,先將user模式下的內(nèi)容copy到kernel模式下的socket的buffer中;
  4. 最后將kernel模式下的socket buffer的數(shù)據(jù)copy到網(wǎng)卡設(shè)備中傳送;

從上面的過程可以看出,數(shù)據(jù)白白從kernel模式到user模式走了一圈,浪費了2次copy(第一次,從kernel模式拷貝到user模式;第二次從user模式再拷貝回kernel模式,即上面4次過程的第2和3步驟。)。而且上面的過程中kernel和user模式的上下文的切換也是4次。

幸運的是,你可以用一種叫做Zero-Copy的技術(shù)來去掉這些無謂的copy。應(yīng)用程序用Zero-Copy來請求kernel直接把disk的data傳輸給socket,而不是通過應(yīng)用程序傳輸。Zero-Copy大大提高了應(yīng)用程序的性能,并且減少了kernel和user模式上下文的切換。

詳述

Zero-Copy技術(shù)省去了將操作系統(tǒng)的read buffer拷貝到程序的buffer,以及從程序buffer拷貝到socket buffer的步驟,直接將read buffer拷貝到socket buffer. JAVA NIO中的FileChannal.transferTo()方法就是這樣的實現(xiàn),這個實現(xiàn)是依賴于操作系統(tǒng)底層的sendFile()實現(xiàn)的。

public void transferTo(long position, long count, WritableByteChannel target);

他底層的調(diào)用時系統(tǒng)調(diào)用**sendFile()**方法:

#include <sys/socket.h>
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);

下圖展示了在transferTo()之后的數(shù)據(jù)流向:

還不懂零拷貝(Zero-Copy)?怎么稱得上高級程序員

 

下圖展示了在使用transferTo()之后的上下文切換:

還不懂零拷貝(Zero-Copy)?怎么稱得上高級程序員

 

使用了Zero-Copy技術(shù)之后,整個過程如下:

  1. transferTo()方法使得文件A的內(nèi)容直接拷貝到一個read buffer(kernel buffer)中;
  2. 然后數(shù)據(jù)(kernel buffer)拷貝到socket buffer中。
  3. 最后將socket buffer中的數(shù)據(jù)拷貝到網(wǎng)卡設(shè)備(protocol engine)中傳輸;

這顯然是一個偉大的進步:這里把上下文的切換次數(shù)從4次減少到2次,同時也把數(shù)據(jù)copy的次數(shù)從4次降低到了3次。

但是這是Zero-Copy么,答案是否定的。

進階

linux 2.1內(nèi)核開始引入了sendfile函數(shù)(上一節(jié)有提到),用于將文件通過socket傳送。

sendfile(socket, file, len);

該函數(shù)通過一次系統(tǒng)調(diào)用完成了文件的傳送,減少了原來read/write方式的模式切換。此外更是減少了數(shù)據(jù)的copy, sendfile的詳細過程如圖:

還不懂零拷貝(Zero-Copy)?怎么稱得上高級程序員

 

通過sendfile傳送文件只需要一次系統(tǒng)調(diào)用,當調(diào)用sendfile時:

  1. 首先(通過DMA)將數(shù)據(jù)從磁盤讀取到kernel buffer中;
  2. 然后將kernel buffer拷貝到socket buffer中;
  3. 最后將socket buffer中的數(shù)據(jù)copy到網(wǎng)卡設(shè)備(protocol engine)中發(fā)送;

這個過程就是第二節(jié)(詳述)中的那個步驟。

sendfiel與read/write模式相比,少了一次copy。但是從上述過程中也可以發(fā)現(xiàn)從kernel buffer中將數(shù)據(jù)copy到socket buffer是沒有必要的。

Linux2.4 內(nèi)核對sendfile做了改進,如圖:

還不懂零拷貝(Zero-Copy)?怎么稱得上高級程序員

 

改進后的處理過程如下:

  1. 將文件拷貝到kernel buffer中;
  2. 向socket buffer中追加當前要發(fā)生的數(shù)據(jù)在kernel buffer中的位置和偏移量;
  3. 根據(jù)socket buffer中的位置和偏移量直接將kernel buffer的數(shù)據(jù)copy到網(wǎng)卡設(shè)備(protocol engine)中;

經(jīng)過上述過程,數(shù)據(jù)只經(jīng)過了2次copy就從磁盤傳送出去了。

這個才是真正的Zero-Copy(這里的零拷貝是針對kernel來講的,數(shù)據(jù)在kernel模式下是Zero-Copy)。

正是Linux2.4的內(nèi)核做了改進,Java中的TransferTo()實現(xiàn)了Zero-Copy,如下圖:

還不懂零拷貝(Zero-Copy)?怎么稱得上高級程序員

 

Zero-Copy技術(shù)的使用場景有很多,比如Kafka, 又或者是Netty等,可以大大提升程序的性能。

版權(quán)聲明:本文為CSDN博主「朱小廝」的原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。

原文鏈接:https://blog.csdn.net/u013256816/article/details/52589524

分享到:
標簽:拷貝
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運動步數(shù)有氧達人2018-06-03

記錄運動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定