最新个人博客 shankusu.me
驱动和网卡的交互过程很少人会关注,但是如果你懂这方面的知识,会对用户态的网络编程更加理解深刻和通透。
驱动和网卡之间是异步通信。驱动在请求发送数据之后CPU就去干别的事情去了。网卡发送完包之后通过中断通知CPU,CPU再通过驱动程序了解到结果。和发送数据一样,接收数据也是异步的。网卡把数据倒腾到主存之后再通过中断通知CPU。
因此,预留一些空间来缓存发送和接受的buffer是必要的。大多数情况下,网卡使用环结构,这个环基本上就是一个队列,它具有固定的条目数,每一个条目存储一个发送或者接受的数据。条目被顺序的轮流使用,可以复用。如下图所示,可以看到数据传送过程。
发送数据流
驱动接收上层的数据并创建一个网卡可以理解的数据包描述(send descriptor),包含了主存地址和大小。由于网卡只认识物理地址,所以驱动还需将虚拟地址转换成物理地址,之后把send descriptor放到Tx ring之中。下一步通过通知网卡有新的数据了,之后网卡通过DMA(直接内存访问)获取元数据和数据发送出去。发送完之后通过DMA把结果写回,之后发送中断通知。
数据的接收和发送反推过程差不多,自己看图:
不多说了,自己看图也能理解了。