重溫IO中零拷貝技術實現的細節,Java對零拷貝的封裝實現

什麼是零拷貝?

    零拷貝是指計算機操作的過程中,CPU不需要爲數據在內存之間的拷貝消耗資源。而它通常是指計算機在網絡上發送文件時,不需要將文件內容拷貝到用戶空間(User Space)而直接在內核空間(Kernel Space)中傳輸到網絡的方式

傳統的IO

    操作系統將數據從磁盤讀到內核空間的緩存

    應用程序將數據從內核空間讀取到應用空間

    應用程序接着將數據寫回到內核空間socket緩衝區

    操作系統將數據從socket緩衝區複製到網卡緩衝區,最後數據經網絡傳輸

零拷貝

   操作系統將數據從磁盤讀到內核空間的緩存

   將數據的位置、長度信息描述符添加到內空間socket緩衝區

    操作系統將數據從內核空間拷貝到網卡緩衝區,最後數據經網絡傳輸

零拷貝的底層實現

使用mmap()替代read(),減少一次拷貝

在Linux中有一個mmap操作,可以減少拷貝次數,我們將read操作換成mmap操作

換成mmap操作後,仍然需要3次copy動作。

第一次,DMA將數據從磁盤中拷貝(DMA copy)到kernel read buffer內核緩衝區中;

第二次,當應用調用write方法時,會將kernel read buffer中的數據拷貝(CPU copy)到kernel socket buffer內核緩衝區;

第三次,將kernel socket buffer中的數據拷貝到protocol engine(協議引擎)。

使用sendfile()減少一次上下文切換

藉助DMA引擎的gather操作減少一次內核拷貝

gather操作可以從多個不同的緩衝區中讀取數據,DMA引擎是可以直接從kernel read buffer中讀取數據的,而不用先將數據從kernel read buffer拷貝到kernel socket buffer後再進行讀取操作。

到此,數據拷貝已經完全跟CPU沒關係了,都是由內核操作的,內核只需要兩次拷貝動作。

Java對零拷貝的封裝實現

舉個簡單的例子,將某apk文件傳輸到某目錄下

        String filePath="/usr/local/file/test.apk";
        String toFilePath="/usr/local/target/test.apk";
        try (
                FileInputStream fileInputStream=new FileInputStream(new File(filePath));
                FileOutputStream fileOutputStream=new FileOutputStream(toFilePath);
                FileChannel fileChanneInput=fileInputStream.getChannel();
                FileChannel fileChannelOutput=fileOutputStream.getChannel()
        ){
            fileChanneInput.transferTo(0,fileChanneInput.size(),fileChannelOutput);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章