zoukankan      html  css  js  c++  java
  • linux内核数据包转发流程(二):中断

        【版权声明:转载请保留出处:blog.csdn.net/gentleliu。邮箱:shallnew*163.com】

        内核在处理2层数据包之前,必须先处理中断系统。设立中断系统,才有可能每秒处理成千的帧。

        当收到一个帧时,驱动程序会代表内核指示设备产生一个硬件中断,内核将中断其它的活动,然后调用一个驱动程序所注冊的处理函数,以满足设备的须要。当事件是接收到一个帧时,处理函数就会把该帧排入队列某处,然后通知内核。
        使用轮询技术会轻易浪费掉非常多系统资源,由于内核会持续去读取检查是否有有帧的到来。

    但使用中断会在每接收到一帧时都强制产生中断。会让cpu处理中断浪费很多时间。在高流量负载下。中断代码会持续抢占正在处理的代码。到某一时刻,输入队列会满,导致旧的帧没办法处理,新的帧又无法排入队列。出现receive-livelock。
        中断长处就是帧的接受及其处理之间延时非常短。缺点就是在高负载下无法良好执行。
        
        当cpu接收一个中断通知信息时,会调用与该中断事件关联的处理函数,这样的关联性有编号表示。在该处理函数运行期间,内核处于中断上下文(interrupt context)中,服务于该中断事件的cpu会被关闭中断功能,即此时不能服务其他中断事件。也不能运行其他进程,cpu全然属于该中断处理函数,不能被抢占。简而言之,中断处理函数是非抢占的,且非可再进入的(reentrant)。这能够减少竞争情况的可能性,可是这对性能有潜在的严重影响。
        因此,中断处理函数所做工作应该尽快完毕。 中断事件能够先对cpu抢占。这是由于假设操作系统让硬件等太久。可能会遗失数据,还有一方面。假设内核或用户空间进程必须被延迟或被抢占。则没有数据会遗失。所以,如今中断处理函数分为上半部和下半部。一般(1)任务对时间敏感或(2)和任务相关或(3)须要保证不被其它中断打断放在上半部运行。能够推迟不太紧急的任务放在下半部运行。

    下半部分为主要分为软中断,tasklet。工作队列。

    下半部的基础架构为:1、把下半部分类成适当类型。2、注冊下半部类型及其处理函数间的关联关系。3、为下半部函数调度。以准备运行。4、通知内核有已调度的BH存在。

    内核(linux-2.6.32)下半部类型有:(定义在include/linux/interrupt.h)

    enum
    {
        HI_SOFTIRQ=0,
        TIMER_SOFTIRQ,
        NET_TX_SOFTIRQ,
        NET_RX_SOFTIRQ,
        BLOCK_SOFTIRQ,
        BLOCK_IOPOLL_SOFTIRQ,
        TASKLET_SOFTIRQ,
        SCHED_SOFTIRQ,
        HRTIMER_SOFTIRQ,
        RCU_SOFTIRQ,    /* Preferable RCU should always be the last softirq */
    
        NR_SOFTIRQS
    };
    
    

    软IRQ通常会在相关联的子系统内注冊。
    内核初始化期间,softirq_init会注冊TASKLET_SOFTIRQ以及HI_SOFTIRQ相关联的处理函数。
    void __init softirq_init(void)
    {
        ......
    
        open_softirq(TASKLET_SOFTIRQ, tasklet_action);
        open_softirq(HI_SOFTIRQ, tasklet_hi_action);
    }
    
    
    
    网络子系统分两种soft IRQ。NET_TX_SOFTIRQ和NET_RX_SOFTIRQ。分别处理发送数据包和接收数据包。这两个soft IRQ在net_dev_init函数(net/core/dev.c)中注冊:
        open_softirq(NET_TX_SOFTIRQ, net_tx_action);
        open_softirq(NET_RX_SOFTIRQ, net_rx_action);
    收发数据包的软中断处理函数被注冊为net_rx_action和net_tx_action。


    当中open_softirq实现为:

    void open_softirq(int nr, void (*action)(struct softirq_action *))
    {
        softirq_vec[nr].action = action;
    }


  • 相关阅读:
    mysql 聚集函数 count 使用详解
    在Docker中使用kettle遇到的问题解决
    整取零存_字段级迁移工具
    快速修改MySQL字段类型
    数据仓库知识点梳理(4)
    五一节分享60多本免费AI电子书
    数据仓库知识点梳理(3)
    数据仓库知识点梳理(2)
    数据仓库知识点梳理(1)
    解决MacVim在macOS Catalina下字母显示不全的问题
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/5397605.html
Copyright © 2011-2022 走看看