一文帶你搞懂 Mmap 技術
大家好,我是樹哥。
相信大家在面試的時候會被問到:Kafka 為啥會這么快?其中我們都會說是因為 zero-copy 的緣故,但 zero-copy 中其實有很多種實現方式,例如:mmap + write、sendfile 等等。這其中的 mmap 到底是咋回事呢?今天我們就來講講 mmap 技術。
mmap 是一種內存映射文件的方法,即將一個文件或者其它對象映射到進程的地址空間,實現文件磁盤地址和進程虛擬地址空間中一段虛擬地址的一一對映關系。
那么 mmap 技術有啥用呢?
答案是:減少數據文件復制,提高效率。
想一下我們讀取文件,然后將其通過網卡發送出去的流程,其整體流程如下所示:
圖片來自知乎博主艾小仙
上述數據讀取和發送過程發生了 4 次用戶態和內核態的上下文切換和 4 次拷貝,具體流程如下:
- 用戶進程通過 read () 方法向操作系統發起調用,此時進程從用戶態轉向內核態。
- DMA 控制器把數據從硬盤中拷貝到讀緩沖區。
- CPU 把讀緩沖區數據拷貝到應用緩沖區,上下文從內核態轉為用戶態,read () 返回
- 用戶進程通過 write () 方法發起調用,上下文從用戶態轉為內核態
- CPU 將應用緩沖區中數據拷貝到 socket 緩沖區
- DMA 控制器把數據從 socket 緩沖區拷貝到網卡,上下文從內核態切換回用戶態,write () 返回
可以看到數據要從內核空間的讀緩沖區讀取到用戶空間的用戶緩沖區,再拷貝到內核空間的 socket 緩沖區,這個過程其實是很浪費時間的。而 mmap 技術的出現,就是為了提高這個效率。 使用 mmap 技術進行文件讀寫操作的過程如下圖所示:
圖片來自知乎博主艾小仙
整個過程發生了 4 次用戶態和內核態的上下文切換和 3 次拷貝,具體流程如下:
- 用戶進程通過 mmap () 方法向操作系統發起調用,上下文從用戶態轉向內核態
- DMA 控制器把數據從硬盤中拷貝到讀緩沖區
- 上下文從內核態轉為用戶態,mmap 調用返回
- 用戶進程通過 write () 方法發起調用,上下文從用戶態轉為內核態
- CPU 將讀緩沖區中數據拷貝到 socket 緩沖區
- DMA 控制器把數據從 socket 緩沖區拷貝到網卡,上下文從內核態切換回用戶態,write () 返回
使用了 mmap 方式的文件讀寫節省了一次 CPU 拷貝,我們不需要再次從內核空間拷貝到用戶空間,然后再從用戶空間拷貝到內核空間。
此時我們會想:那這到底是怎么實現的呢?
其實這一切的背后都是操作系統的功勞。操作系統在這背后為我們做好了所有的映射和回寫工作。當我們對內存特定區域進行讀寫時,操作系統便會檢測到這一操作,然后根據不同場景去做讀磁盤或者寫磁盤的操作。
看到這里,對于 mmap 的理解基本上足夠我們應用開發人員使用了。