加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

数据包如何到达应用

(2022-04-15 17:55:23)
分类: tcp/ip
    应用读取到数据包,分两个过程,一是数据包从网卡到达内核,内核调用协议栈处理放进socket,二是应用如何读取到socket的数据。 
    第一个过程:
    网卡收到数据帧,通过DMA方式将数据帧放入内存的RingBuffer,然后向CPU发起一个硬中断;CPU响应硬中断,调用网卡注册的中断处理函数,该函数几乎没做什么事, 然后发起一个软中断,CPU空闲出去做其它事;内核线程ksoftirqd专门处理软中断,它发现有软中断,调用网卡驱动igb_poll()函数,将数据帧从RingBuffer读出,封装成sk_buff,查看数据帧头部的协议,调用相应协议栈函数(如ip包协议栈注册的函数是ip_rcv函数,arp包是arp_rcv函数);ip_rcv函数处理后再根据ip头部协议(tcp或udp等协议),将ip包送进tcp_rcv函数或udp_rcv函数处理;以以udp_rcv为例,udp_rcv调用__udp4_lib_lookup函数,该函数以包的目标port为索引,寻找哈希桶,再以源地址,源端口,目的地址,目的端口去查找sock。如果找到的哈希桶元素较多,会进行二次hash,无论如何,最终会找到唯一的sock;最后,调用__udp_queue_rcv_skb函数将数据包放到sock的接收数据队列sk_receive_queue中。
    第二个过程:
    应用程序调用read或recvfrom函数读取数据时,发起系统调用陷入内核;应用程序的socket描述符最终对应到一个socket,socket包含了sock,它里面有协议及对应处理方法,如udp协议对应函数为udp_recvmsg,最后调用到__skb_recv_datagram,它就是读取sk->sk_receive_queue。如果没有数据,允许阻塞,等待数据到来。有数据就从队列读出复制到应用进程。

两篇好帖子:
https://segmentfault.com/a/1190000038374889
https://www.codeleading.com/article/9506996825/

0

阅读 收藏 喜欢 打印举报/Report
后一篇:端口
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有