net_rx_action函数和process_backlog函数解析

本文详细解析了Linux内核中网络数据包下半部处理流程,重点介绍了NET_RX_SOFTIRQ软中断的触发机制及net_rx_action函数的工作原理,并探讨了process_backlog函数如何通过netif_receive_skb将数据包传递到协议栈。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

网络数据包在上半部的处理通常有两种模式:传统的netif_rx模式和NAPI模式,在这里我们主要讨论网络下半部的内容,对这两种模式的机制不作涉及,但无论上半部采用何种收包模式,都会调用__netif_rx_schedule()函数,其中的调用:

__raise_softirq_irqoff(NET_RX_SOFTIRQ);

将触发一个类型为NET_RX_SOFTIRQ的软中断,由do_softirq()函数执行这个软中断,

对于NET_RX_SOFTIRQ类型的软中断来说,系统将其action注册为net_rx_action.

net_rx_action函数

static void net_rx_action(struct softirq_action *h) { struct softnet_data *queue = &__get_cpu_var(softnet_data); unsigned long start_time = jiffies;

//在这里定义了一次中断处理skb的数目,系统定义为300

int budget = netdev_budget;

void *have; //禁止中断 local_irq_disable(); //检查poll_list,看是否有准备等待轮询取得数据 while (!list_empty(&queue->poll_list)) { struct net_device *dev; //轮询的处理时间不能超过一个时间片,防止一次中断处理占用太多时间 //同时限制了处理skb的数目,超过300时,中断处理结束 if (budget <= 0 || jiffies - start_time > 1) goto softnet_break;             //开启中断         local_irq_enable(); //取得等待轮询设备的结构 dev = list_entry(queue->poll_list.next, struct net_device, poll_list); have = netpoll_poll_lock(dev); //调用设备上面的poll方法,如果设备没有注册自己的poll方法,那么系统 //将poll方法指定为process_backlog()函数 if (dev->quota <= 0 || dev->poll(dev, &budget)) { netpoll_poll_unlock(have); local_irq_disable(); list_move_tail(&dev->poll_list, &queue->poll_list); if (dev->quota < 0) dev->quota += dev->weight; else dev->quota = dev->weight; } else { netpoll_poll_unlock(have); dev_put(dev); local_irq_disable(); }        } out:        local_irq_enable(); ……………………………………………………………………………………… softnet_break: __get_cpu_var(netdev_rx_stat).time_squeeze++;        //在这里触发下一次中断处理 __raise_softirq_irqoff(NET_RX_SOFTIRQ);

       goto out; }


process_backlog函数

前面已经说过,中断处理函数net_rx_action调用设备的poll方法(默认为process_backlog),而process_backlog函数将进一步调用netif_receive_skb()将数据包传上协议栈,如果设备自身注册了poll函数,也将调用netif_receive_skb()函数

static int process_backlog(struct net_device *backlog_dev, int *budget)
{
	int work = 0;
       int quota = min(backlog_dev->quota, *budget);
       struct softnet_data *queue = &__get_cpu_var(softnet_data);
       unsigned long start_time = jiffies;
       backlog_dev->weight = weight_p;
       for (;;) {
              struct sk_buff *skb;
              struct net_device *dev;
              local_irq_disable();

              //在这个循环里面,系统将调用__skb_dequeue不断从设备上取出SKB,直到
              //skb处理完为止
              skb = __skb_dequeue(&queue->input_pkt_queue);
              if (!skb)
                     goto job_done;
              local_irq_enable();
              dev = skb->dev;

              //netif_receive_skb的调用就在这里了
              netif_receive_skb(skb);
              dev_put(dev);

              //处理的skb数目+1
              work++;

              //如果处理的skb数目大于事先预定的最大值,或者处理的时间超过一个
              //时间片,则结束处理
              if (work >= quota || jiffies - start_time > 1)
                     break;
       }

       backlog_dev->quota -= work;
       *budget -= work;
       return -1;
………………………………………………………………………………………
}

netif_receive_skb函数在前面已经提到过,根据不同的协议调用不同的协议处理函数,

网桥的处理入口netif_receive_skb里面,针对IP协议,ip_rcv函数被调用。


转载自:http://blog.youkuaiyun.com/weixiuc/article/details/2955569

`static inline struct crypto_async_request *crypto_get_backlog(struct crypto_queue *queue)` 是一个内联函数的定义。 内联函数是一种编译器优化技术,它将函数的代码插入到调用处而不是通过函数调用进行执行。这样可以减少函数调用的开销,提高代码的执行效率。 函数的功能是返回密码算法请求队列中的积压请求的指针。 参数 `struct crypto_queue *queue` 是一个指向密码算法请求队列的指针。 函数的实现如下: ```c static inline struct crypto_async_request *crypto_get_backlog(struct crypto_queue *queue) { if (queue->backlog == &queue->list) { return NULL; // 如果队列中没有积压请求,则返回 NULL } else { return container_of(queue->backlog, struct crypto_async_request, list); // 如果队列中有积压请求,则返回积压请求的指针 } } ``` 在这段代码中,首先通过比较 `queue->backlog` `&queue->list` 的地址来判断队列中是否有积压请求。如果它们相等,表示队列中没有积压请求,则函数返回 `NULL`。 如果队列中有积压请求,那么使用 `container_of` 宏将 `queue->backlog` 的地址转换为 `struct crypto_async_request` 结构体的指针,并将其返回。 总之,`crypto_get_backlog` 函数是一个内联函数,用于返回密码算法请求队列中的积压请求的指针。如果队列中没有积压请求,则返回 `NULL`。 希望以上解释能够帮助您理解 `crypto_get_backlog` 内联函数的功能定义。如果还有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值