内容来自SJTU,IPADS OS-16-Network
文章插图
【Linux网络包从中断到接收的一生】linux
既然要讲,那就把一个包的整个包生都说了算了
触发中断
- 在非虚拟化环境下,网卡通过DMA将packet写入内核的rx_ring环形队列缓冲区,并触发中断 。
- 如果在虚拟化环境下,VMM配置GIC ITS (Interrupt Translation Service),建立物理中断与虚拟中断的映射完成中断虚拟化使得网卡能直接向VM发出中断,同时通过IO虚拟化,网卡通过IOMMU将packet直接写入虚拟机内核的rx_ring
- CPU在收到中断之后,调用网卡ISR也就是所谓的中断handler
- 分配sk_buf并入input_pkt_queue(如果队列已满则丢弃)
- 发出一个软中断NET_RX_SOFTIRQ,软中断可以被调度例如通过tasklet
- sk_buf从input_pkt_queue传入process_queue,根据协议类型调用网络层协议的handler
- ip_rcv执行包头检查,ip_router_input()进行路由,决定本机/转发/丢弃
- tcp_v4_rcv执行包头检查,tcp_v4_lookup查询对应的socket和connection,如果正常,tcp_prequeue将skb放进socket接收队列
- socket随即唤醒所在的进程
文章插图
kqueue
因为epoll没有论文,就说说kqueue是怎么做的吧,kqueue会根据socket绑定的knote链表(每个监听的kqueue都可能创建一个knote),将knote通过反向指针获得kqueue,将knote加入kqueue的就绪队列末尾 。如果此时恰好有进程正在监听的话,将会唤醒进程,kqueue会被扫描,并从就绪队列处获得所有的event,从而了解已经就绪的所有socket 。
- 唤醒的进程调用socket recv系统调用,如果是TCP则调用tcp_recvmsg从sk_buffer拷贝数据
netif_receive_skb_list()
Linux的NAPI还会继续延迟软中断的处理,等待其积累足够的skb后进行轮询,一次性处理所有的skb 。SKBskb并不是直接存储报文,而是存储指针,指针只需要移动,就能完成解包,而本身的报文并不需要修改 。上一层的协议栈会在处理当前层的同时设置好下一层的头指针,并且移动data指针 。与此同时,skb本身是双向链表实现的队列 。qlen为链表元素长度,lock为添加元素时的锁 。
文章插图
skb结构
推荐阅读
- linux终端mysql用户操作只看这篇够了
- Linux uptime命令的使用示例
- 第六十一章、C程序中怎么调用Linux中的shell命令
- 袋泡茶怎样泡最好,买三送开古绿茶袋泡茶包明前龙井茶叶酒店宾馆客房饭店奶茶店调配专用袋泡茶叶包
- 计算机端口详解
- 茶包的实用美观设计,包装设计的要素和要求
- 冬至是什么意思,网络白茶是什么意思
- 淘宝seo的三大相关包括 淘宝seo是什么意思,怎么优化
- 包皮包茎的区别有什么
- 包茎手术后恢复过程