最近也是刚刚拿到这本书,对于linux网络这块,自己也是小白一个,所以就以自己基础知识为零的起点,来做读数笔记。有不懂点也会查阅资料,来补充知识点。
书目录:第二章-内核是如何接收网络包的,这一章节的2.2.1 linux网络收包总览中的其中一段文章:
当网卡收到数据以后,以DMA的方式把网卡收到的帧写到内存里,再向CPU发起⼀个中断,以通知CPU有数据到达。当CPU收到中断请求后,会去调用网络设备驱动注册的中断处理函数。网卡的中断处理函数并不做过多工作,发出软中断请求,然后尽快释放CPU资源。ksoftirad内核线程检测到有软中断请求到达,调用poll开始轮询收包,收到后交由各级协议栈处理。对于TCP包来说,会被放到用户socker的接收队列中。
内核收包的路径⽰意图,从书中摘抄过来。
根据上图,网络数据从网卡到用户空间的执行顺序整理出的链路:
1. 网卡接收数据
-
网卡接收到外部网络发送的数据包。
2. 使用DMA将数据写入内存
-
网卡通过DMA(直接内存访问)将接收到的数据包直接写入系统内存中,不经过CPU的处理,以提高效率。
3. 网卡向CPU发起硬中断
-
网卡将数据写入内存后,向CPU发出一个硬中断请求,通知CPU有新的数据包需要处理。
4. CPU调用中断处理函数
-
CPU响应硬中断,调用网卡驱动程序中注册的中断处理函数。
-
中断处理函数通常只做少量工作,如记录中断事件、标记需要进一步处理的任务,然后发起一个软中断请求,尽快释放CPU资源以继续处理其他任务。
5. 软中断请求处理
-
内核中的ksoftirqd线程检测到有软中断请求,随后被唤醒。
-
ksoftirqd线程开始执行软中断处理,这个处理通常会涉及调用网卡驱动程序的poll方法。
6. poll轮询网卡的收包队列
-
poll轮询网卡的收包队列,从队列中读取到内存中的数据包。
7. 协议栈处理数据包
-
数据包被传递到内核中的网络协议栈,经过各个协议层的处理(如IP层、TCP层等)。
-
对于TCP数据包,最终会被放入用户socket的接收队列中。
8. 用户空间程序读取数据
-
应用程序通过调用系统接口(如
recv
或read
)从socket的接收队列中读取数据包,完成整个数据接收过程。
整个链路依次经过:网卡接收数据 -> DMA写入内存 -> 硬中断 -> 中断处理函数 -> 软中断请求 -> ksoftirqd线程处理 -> poll轮询 -> 协议栈处理 -> 用户socket接收队列 -> 应用程序读取数据
什么是poll轮询?
在Linux网络处理流程中,poll轮询(polling)是一种机制,用来检查网卡或其他设备的状态,看是否有数据包需要处理。具体来说,在网络数据接收流程中,poll轮询指的是ksoftirqd线程调用网卡驱动中的poll函数,以查看是否有新的数据包已经被接收到内存中并准备好进一步处理。
poll轮询是ksoftirqd线程用来主动检查网卡状态的一种方法,它在网络数据包接收流程中扮演着关键角色,确保数据包能够及时从网卡传递到内核协议栈,最终到达用户空间应用程序。
poll
函数通常是由网卡驱动程序实现的,具体实现因不同的网络设备而异。不过,Linux内核中有一套通用的框架用于实现网络设备的 poll
处理,下面是一个简化的示例,展示了 poll
函数的基本结构和作用。
int my_poll(struct napi_struct *napi, int budget) {
int work_done = 0;
// 1. 轮询网卡接收队列,获取数据包
while (work_done < budget) {
struct sk_buff *skb = my_net_device_receive();
if (!skb)
break; // 没有更多数据包可处理
// 2. 数据包处理,将其传递给内核协议栈
netif_receive_skb(skb);
work_done++;
}
// 3. 判断是否已经处理了所有数据包
if (work_done < budget) {
// 释放NAPI,以便可以再次被唤醒处理更多数据
napi_complete_done(napi, work_done);
// 重新启用网卡的中断
enable_irq(napi->dev->irq);
}
return work_done;
}
ksoftirqd线程是Linux内核中的一个内核线程,它专门用于处理软中断(softirq)。软中断是一种比硬中断优先级低的中断机制,旨在将一些中断处理中的较为耗时的任务延后,以在合适的时机完成。ksoftirqd线程在Linux内核中是自动创建和管理的,它负责在系统空闲时处理这些被延迟的任务。
每个CPU核心都有一个对应的ksoftirqd
线程,以便能够并行处理多核系统中的软中断任务。