Zero Copy
===
###### tags: `Note` `MCL` `Zero Copy`
[toc]
## Zero Copy
### scenario
從 disk 讀檔,再將檔案用 socket 傳給另一 client
```c
read(file, tmp_buf, len);
write(socket, tmp_buf, len);
```

* cpu copy 2 次
* dma copy 2 次
* 切 mode 4 次
### mmap + write
利用 mapping 的方式減少 cpu copy
```c
tmp_buf = mmap(file, len);
write(socket, tmp_buf, len);
```

* cpu copy 1 次
* dma copy 2 次
* 切 mode 4 次
#### SIGBUS 問題 (非預期的記憶體存取操作)
解法:
* callback function
* file leasing (opportunistic locking)
* 當另一個 process 嘗試 write 你正在使用的 memory 段時, kernel 會送 RT_SIGNAL_LEASE,表示無法使用,並且在 process 被 SIGBUS kill 之前中斷 write
### sendfile
直接從一個 fd copy 內容到另一個 fd
```c
sendfile(socket, file, offset, len);
```

* cpu copy 1 次
* dma copy 2 次
* 切 mode 2 次
### sendfile + DMA gather
只 copy 些微資訊,例如 fd, offset, len 之類的
```c
sendfile(socket, file, offset, len);
```

* cpu copy 0 次 (嚴格來說有 1 次,但非 copy 整份內容)
* dma copy 2 次
* 切 mode 2 次
### splice
建立 pipe buffer
```c
ssize_t splice(int fd_in, off64_t *off_in, int fd_out,
off64_t *off_out, size_t len, unsigned int flags);
```

* cpu copy 0 次 (嚴格來說有 2 次,但只有 copy pointer)
* dma copy 2 次
* 切 mode 6 次
## Zero Copy 應用
網路封包處理

### PF_RING
* mmap
* mapping kernel_buf and user_buf
###### NIC 到 user space
* cpu copy 1 次
### PF_RING zc
* mmap
* RX_buffer and user_buf
###### NIC 到 user space
* cpu copy 0 次

### DPDK
* UIO + mmap
* UIO (userspace driver)
* mapping RX_buffer and user_buf
* PMD (Poll Mode Driver)
* 禁用 interrupt 改用 polling
* Huge Pages
* 減少 TLB miss
###### NIC 到 user space
* cpu copy 0 次
## Reference
[Zero Copy I: User-Mode Perspective](https://www.linuxjournal.com/article/6345)
[一文带你,彻底了解,零拷贝 Zero-Copy 技术](https://xie.infoq.cn/article/340769913d2202f6387550dd8)
[Performance Review of Zero Copy Techniques](https://www.uidaho.edu/~/media/UIdaho-Responsive/Files/engr/research/csds/publications/2012/Performance%20Review%20of%20Zero%20Copy%20Techniques%202012.ashx)
[Linux I/O 原理和 Zero-copy 技术全面揭秘](https://aijishu.com/a/1060000000149804)
[DPDK解析](https://zhuanlan.zhihu.com/p/363622877)