Linux内核处理网络包流程
⾸先在开始收包之前,Linux 要做许多的准备⼯作:
- 创建ksoftirqd线程,为它设置好它⾃⼰的线程函数,后⾯就指望着它来处理软中断呢。
- 协议栈注册,linux要实现许多协议,⽐如arp,icmp,ip,udp,tcp,每⼀个协议都会将⾃⼰的处理函数注册⼀下,⽅便包来了迅速找到对应的处理函数
- ⽹卡驱动初始化,每个驱动都有⼀个初始化函数,内核会让驱动也初始化⼀下。在这个初始化过程中,把⾃⼰的DMA准备好,把NAPI的poll函数地址告诉内核
- 启动⽹卡,分配RX,TX队列,注册中断对应的处理函数
以上是内核准备收包之前的重要⼯作,当上⾯都 ready 之后,就可以打开硬中断,等待数据包的到来
了。
当数据到到来了以后,第⼀个迎接它的是⽹卡: - ⽹卡将数据帧 DMA 到内存的 RingBuffer 中,然后向 CPU 发起中断通知
- CPU 响应中断请求,调⽤⽹卡启动时注册的中断处理函数
- 中断处理函数⼏乎没⼲啥,就发起了软中断请求
- 内核线程 ksoftirqd 线程发现有软中断请求到来,先关闭硬中断
- ksoftirqd 线程开始调⽤驱动的 poll 函数收包
- poll 函数将受到的包送到协议栈注册的 ip_rcv 函数中
- ip_rcv 函数再讲包送到 udp_rcv 函数中(对于 tcp 包就送到 tcp_rcv )
linux 内核socket对象
accept
当 accept 之后,进程会创建⼀个新的 socket 出来,专⻔⽤于和对应的客户端通信,然后把它放到当前进程的打开⽂件列表中。