假设情景: 一个udp数据包流到达机器X,机器X正在运行两个程序 - 一个正在侦听带有recv()的数据包,另一个正在运行pcap。
在这种情况下,据我所知,数据包存储在接口中,直到它被内核轮询,然后将内核移动到内核内存中的缓冲区,并将数据包复制到另外两个缓冲区 - 一个缓冲区用recv监听的程序,以及用pcap监听程序的一个缓冲区。数据包在读取时从相应的缓冲区中删除 - 通过pcap_next()或recv(),下次进程调度程序运行它们(我假设它们在这种情况下阻塞)。它是否正确?是否真的使用了4个缓冲区,还是以其他方式处理?
我正在寻找尽可能详细的描述,以了解在这种情况下真正涉及哪些缓冲区,以及数据包如何从一个缓冲区移动到另一个(例如,数据包在进入之前被复制到pcaps缓冲区) recv buffer,after或undefined?)。
我知道这似乎是一个很大的问题,但我真正关心的是数据包的存储位置以及数据存储的时间长短。子弹点很好。理想情况下,我想要一个通用答案,但如果它在OS之间有所不同,我对Linux最感兴趣。
答案 0 :(得分:8)
Linux案例(BSD可能有些类似,使用mbuf
而不是skbuff
s):
Linux使用skbuff(套接字缓冲区)来缓冲网络数据。 skbuff包含有关某些网络数据的元数据,以及一些指向该数据的指针。
Taps(pcap用户)创建skbuff克隆。克隆是一个新的skbuff,但它指向相同的数据。当有人需要修改几个skbuff(原始skbuff及其克隆)共享的数据时,它首先需要创建一个新的副本(写时复制)。
当某人不再需要一个skbuff时,kfree_skb()
就是了。 kfree_skb()
递减引用计数,当引用计数达到零时,释放skbuff。考虑克隆会稍微复杂一些,但这是一般的想法。