6410 linux DM9000收包机制

来源:互联网 发布:win7系统无法安装软件 编辑:程序博客网 时间:2024/06/05 15:35
  • 中断接收

DM9000网卡注册的中断函数为dm9000_interrupt(),该中断函数调用dm9000_rx()从网卡的buffer中读取接收到的数据,将数据接收到skb中之后,调用netif_rx()处理该数据包,最后的结果是将数据包传递给上层处理。

我们看看netif_rx()函数代码主要部分:

int netif_rx(struct sk_buff *skb){    int ret;    ......#ifdef CONFIG_RPS    ......#else    {        unsigned int qtail;        ret = enqueue_to_backlog(skb, get_cpu(), &qtail);        put_cpu();    }#endif    return ret;}

在enqueue_to_backlog()中,通过__skb_queue_tail(&sd->input_pkt_queue, skb)将skb接入per cpu 变量softnet_data的链中。接着在enqueue_to_backlog()中调用____napi_schedule()。

if (!__test_and_set_bit(NAPI_STATE_SCHED, &sd->backlog.state)) {    if (!rps_ipi_queued(sd)) {        printk(KERN_INFO "skedu napi\r\n");        ____napi_schedule(sd, &sd->backlog);    }}

我们进入____napi_schedule()函数看看做了什么

static inline void ____napi_schedule(struct softnet_data *sd,                     struct napi_struct *napi){    list_add_tail(&napi->poll_list, &sd->poll_list);    __raise_softirq_irqoff(NET_RX_SOFTIRQ);}

该函数将napi->poll_list加入sd->poll_list中,并置位了系统注册的软中断的第NET_RX_SOFTIRQ位。最后函数从DM9000的中断函数中返回退出。Linux中负责将skb传递给上层的函数是__netif_receive_skb(),那么该函数是怎么被调用的呢?

  • 软中断处理函数net_rx_action()
    当软中断被调度执行后,net_rx_action()函数会被调用。
static void net_rx_action(struct softirq_action *h){    ......    while (!list_empty(&sd->poll_list)) {        ......        n = list_first_entry(&sd->poll_list, struct napi_struct, poll_list);        ......        if (test_bit(NAPI_STATE_SCHED, &n->state)) {            work = n->poll(n, weight);            trace_napi_poll(n);        }        ......        if (unlikely(work == weight)) {            if (unlikely(napi_disable_pending(n))) {                local_irq_enable();                napi_complete(n);                local_irq_disable();            } else                list_move_tail(&n->poll_list, &sd->poll_list);        }    ......}

简化之后,该函数首先从poll_list中取出一个napi_struct ,即____napi_schedule()函数中加入到poll_list中的napi_struct,然后调用该napi_struct的poll函数。查找代码,找出poll函数指针指向的函数原型process_backlog(),在process_backlog()函数中执行__netif_receive_skb(skb)将skb传递给上层。

  • 软中断什么时候被调用?

这个问题,我在网上搜了好一会儿工夫,最后发现,每次cpu执行完中断函数后,例如dm9000_interrupt()函数,在cpu退出中断asm_do_IRQ()前调用irq_exit(),在irq_exit()中执行软中断。在软中断中唤醒软中断处理任务,然后,cpu中断彻底退出,等到系统调度任务的时候,软终端所唤醒的任务得以被调度执行。具体来说,就是net_rx_action()函数。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 宝宝拉粑粑干硬怎么办 美国办新生儿护照怎么办 怀孕拉绿色大便怎么办 幼儿园孩子不爱学习怎么办 幼儿园老师管不住孩子怎么办 手机支架夹不住怎么办 画水彩没有留白液怎么办 水彩颜料脱胶了怎么办 指甲油涂到手上怎么办 抖音里没有控雨怎么办 qq视频没有特效怎么办 组长刁难员工员工怎么办 想转行没精力怎么办 桔子树无法退款怎么办 保温箱婴儿哭了怎么办 宝宝不爱吃肉泥怎么办 苹果x卡死了怎么办 苹果6手机用着卡怎么办 二个月宝宝肚子胀气怎么办 一岁半宝宝大便干结怎么办 婴儿上大便费劲怎么办 宝宝便秘半年了怎么办 1岁宝宝便秘怎么办 两个月积食了怎么办 婴儿拉青色大便怎么办 一周岁宝宝便秘怎么办 两岁宝宝内火重怎么办 一岁宝宝内火重怎么办 小孩大便有点血怎么办 一岁半宝宝拉血怎么办 宝宝八个月便秘怎么办 七个月孩子便秘怎么办 小孩肚子胀气怎么办消化不良 骨盆窄孩子卡住怎么办 孕38周便秘怎么办 孕晚期肚子发硬怎么办 小孩脸上有斑怎么办 肚子胀怎么办快速解决 肚子发撑发胀怎么办 怀孕超过40周怎么办 练琴近视了怎么办