一图总结内核是如何发送网络包的?

大家好,今天我们用一张图总结下内核是如何发生网络包的,并且给大家解释下几个经常遇到的问题。话不多说,直接开干!

 了解了整个发送过程以后,我们回头再来看几个问题。

1. 我们在监控内核发送数据消耗的 CPU 时,是应该看 sy 还是 si
在⽹络包的发送过程中,⽤户进程(在内核态)完成了绝⼤部分的⼯作,甚⾄连调⽤驱动的
事情都⼲了。 只有当内核态进程被切⾛前才会发起软中断。 发送过程中,绝⼤部分( 90%
以上的开销都是在⽤户进程内核态消耗掉的。
只有⼀少部分情况下才会触发软中断( NET_TX 类型),由软中断 ksoftirqd 内核进程来发
送。
所以,在监控⽹络 IO 对服务器造成的 CPU 开销的时候,不能仅仅只看 si ,⽽是应该把 si sy
都考虑进来。
2. 在服务器上查看 /proc/softirqs ,为什么 NET_RX 要⽐ NET_TX ⼤的多的多?
之前我认为 NET_RX 是读取, NET_TX 是传输。对于⼀个既收取⽤户请求,⼜给⽤户返回的
Server 来说。 这两块的数字应该差不多才对,⾄少不会有数量级的差异。但事实上,我⼿
头的⼀台服务器是这样的:
经过今天的分析,发现这个问题的原因有两个。
第⼀个原因是当数据发送完成以后,通过硬中断的⽅式来通知驱动发送完毕。但是硬中断⽆
论是有数据接收,还是对于发送完毕,触发的软中断都是 NET_RX_SOFTIRQ ,⽽并不是
NET_TX_SOFTIRQ
第⼆个原因是对于读来说,都是要经过 NET_RX 软中断的,都⾛ ksoftirqd 内核进程。⽽对于
发送来说,绝⼤部分⼯作都是在⽤户进程内核态处理了,只有系统态配额⽤尽才会发出
NET_TX ,让软中断上。
综上两个原因,那么在机器上查看 NET_RX NET_TX ⼤的多就不难理解了。
3. 发送⽹络数据的时候都涉及到哪些内存拷⻉操作?
这⾥的内存拷⻉,我们只特指待发送数据的内存拷⻉。
第⼀次拷⻉操作是内核申请完 skb 之后,这时候会将⽤户传递进来的 buffer ⾥的数据内容都
拷⻉到 skb 中。如果要发送的数据量⽐较⼤的话,这个拷⻉操作开销还是不⼩的。
第⼆次拷⻉操作是从传输层进⼊⽹络层的时候,每⼀个 skb 都会被克隆⼀个新的副本出来。
⽹络层以及下⾯的驱动、软中断等组件在发送完成的时候会将这个副本删除。传输层保存着
原始的 skb ,在当⽹络对⽅没有 ack 的时候,还可以重新发送,以实现 TCP 中要求的可靠传
输。
第三次拷⻉不是必须的,只有当 IP 层发现 skb ⼤于 MTU 时才需要进⾏。会再申请额外的
skb ,并将原来的 skb 拷⻉为多个⼩的 skb。
看到这⾥,相信内核发送数据包对于你来说,已经不再是⼀个完全不懂的⿊盒了。本⽂哪怕
你只看懂⼗分之⼀,你也已经掌握了这个⿊盒的打开⽅式。这在你将来优化⽹络性能时你就
会知道从哪⼉下⼿了。
推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,点击立即学习:

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值