Linux 版本下的 sendfile 演进:
Linux 提供 sendfile技术。Kafka中,transferFrom和transferTo方法。
零拷贝技术:先从用户态切换到内核态,把磁盘数据拷贝到内核缓冲区,同时从内环缓冲区拷贝一些offset和length数据到socket缓冲区,
接着从内核态切换到用户态,从内核缓冲区直接把数据拷贝到网络协议引擎里去,
同时从Socket缓冲区拷贝一些offset和length信息到网络协议引擎里去,offset和length量几乎可以忽略。
sendfile:产生 2次切换,2次拷贝。
Linux 2.1 版本,具体如下图:
Linux 2.1 版本 提供了 sendFile 函数,
其基本原理如下:数据根本不经过用户态,直接从内核缓冲区进入到 SocketBuffer区,同时,由于和用户态完全无关,就减少了一次上下文切换。
1、第一次拷贝:调用 sendFile 系统,数据被 DMA 引擎从磁盘拷贝到内核缓冲区,用户态切到内核态。
2、第二次拷贝:调用 write 系统,数据被 CPU 从内核缓冲区拷贝到 Socket缓存区,这时,是没有上下文切换的,因为都在内核空间。
3、第三次拷贝:最后,数据被 DMA 引擎从 Socket 缓冲区拷贝到协议栈,内核态切到用户态。
产生2次上下文切换,3次拷贝。
Linux 在 2.4 版本,具体如下图:
Linux 在 2.4 版本中,做了一些修改,避免了从内核缓冲区拷贝到 Socket buffer 的操作,直接拷贝到协议栈,从而再一次减少了数据拷贝。
index.html 要从文件进入到网络协议栈,只需 2 次拷贝:
1、第一次拷贝:数据被 DMA 引擎从磁盘拷贝到内核缓冲区,用户态切到内核态。
2、第二次拷贝:数据被 DMA 引擎从内核缓冲区将数据拷贝到网络协议栈;内核态切到用户态。
内核缓存区只会拷贝一些 offset 和 length 信息到 SocketBuffer,基本无消耗。
零拷贝的目标就是省略这些无谓的copy。
直接从kernel(内核缓冲区)把数据传输给socket(协议栈,网卡)
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。