- 论坛徽章:
- 0
|
本帖最后由 frogsu 于 2013-01-24 00:09 编辑
Netconsole提供了一种通过网络监控调试信息的便捷的方法,它使用了工作队列的机制,可以安全的工作在中断上下文中。
netpoll_send_udp函数主要完成了网络监控调试信息的udp包的生成和发送。在这个函数里,两次调用利用到了netpoll_poll_dev()函数,以find_skb()函数进行如下分析:- static struct sk_buff *find_skb(struct netpoll *np, int len, int reserve)
- {
- int count = 0;
- struct sk_buff *skb;
- zap_completion_queue(); /*获取本地cpu的softnet_data结构,对完成发送的数据包等待释放的队列sd->completion_queue进行释放skb */
- refill_skbs(); /* 确保skb缓冲池的长度不小于MAX_SKBS */
- repeat:
- skb = alloc_skb(len, GFP_ATOMIC);
- if (!skb)
- skb = skb_dequeue(&skb_pool); /*分配失败则从缓冲池里取*/
- if (!skb) {
- if (++count < 10) {
- netpoll_poll_dev(np->dev); /*缓冲池也空了,则调用netpoll_poll_dev()函数轮询并处理网卡的收发的数据,
- * 并释放发送完成的skb,以便有更多的内存空间。*/
- goto repeat;
- }
- return NULL;
- }
- atomic_set(&skb->users, 1);
- skb_reserve(skb, reserve);
- return skb;
- }
复制代码 至于你觉得构造好udp包直接发送不就行了,此处为何如此复杂?
从代码里面也可以看到其实netpoll_send_udp()函数里,有很多是关于清skb空间以及netpoll方法来实现udp包的发送,这估计跟系统的netconsole有关吧,因为netconsole要经常发送监控且数据量较小的UDP数据包,并且得能工作于系统于系统crash或者中断不使能的情况下,而netpoll工作模式刚好适应这些特征,因而没有直接调用发送,而是加入了netpoll操作,最后才调用了dev->hard_start_xmit函数.如下图所示:
|
|