Linux网络子系统内核分析(2)

在进行初始化时,设备驱动程序会分配一个 net_device 结构,然后使用必须的程序对其进行初始化。这些程序中有一个是 dev->hard_start_xmit ,它定义了上层应该如何对 sk_buff 排队进行传输。这个程序的参数为 sk_buff 。这个函数的操作取决于底层硬件,但是通常 sk_buff 所描述的报文都会被移动到硬件环或队列中。就像是设备无关层中所描述的一样,对于 NAPI 兼容的网络驱动程序来说,帧的接收使用了 netif_rx 和 netif_receive_skb 接口。NAPI 驱动程序会对底层硬件的能力进行一些限制。

分析内核代码实现:

1.发送UDP数据包

  在应用程序中

  通过socket()函数建立一个socket,然后通过write()函数讲数据写入socket发送出去

  在内核中:

  a.在系统调用层和协议无关层中

  首先通过socket_file_ops结构找出应用程序在内核中的入口,其函数为sock_aio_write,紧接着调用do_sock_write---__sock_sendmsg---__sock_sendmsg_nosec

  b.在网络协议层中

  调用udp_sendmsg---ip_route_output_flow(选择路由)  udp_flush_pending_frames---ip_flush_pending_frames(ip协议入口)---ip_local_out---dst_output---ip_finish_output---ip_finish_output2---arp_generic_ops->neigh_resolve_output(建立邻居信息)

  c.在设备无关接口中

  调用dev_queue_ximt---dev_hard_start_xmit

  d.在驱动程序层中

  调用ndo_start_xmit

2.接收IP数据包

  在应用程序中

  通过系统调用recvmsg函数获取包的内容

  在内核中:

  网卡接收到数据包之后发生中断,通过netif_rx(此处触发一个软中断,当处理器空闲时再处理)函数将包递给上层的netif_rx_action(除驱动层之外,上面四层的总入口),继续调用netif_receive_skb(判断由哪个协议处理该包)---deliver_skb,然后将数据包递交给ip协议层处理(ip_rcv-ip协议栈层处理入口),紧接着有丢给udp协议层处理(udp_rcv-udp协议栈层处理入口),udp层处理完之后,递交给sock->ops->recvmsg,即为recvmsg系统调用对应的函数。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/8ede86e6c4f96012eb089ba66b7e0d57.html