首页 > 系统相关 >Linux中断下半部处理机制-tasklet

Linux中断下半部处理机制-tasklet

时间:2023-11-28 09:34:30浏览次数:44  
标签:head struct void static 半部 TASKLET Linux tasklet

转载原文:https://www.cnblogs.com/Wangzx000/p/17488378.html

tasklet特性

(1)一种特定类型的tasklet只能运行在一个CPU上,不能并行,只能串行执行
(2)多个不同的类型的tasklet可以并行在多个CPU上
(3)软中断是静态分配的,在内核编译好后,就不能再改变了。但tasklet灵活很多,可以在运行时改变

tasklet是在两种软中断类型的基础上实现的,因此如果不需要软中断的并行也行,tasklet就是最好的选择。所以也可以说tasklet是软中断的一种特殊用法,即延迟情况下的串行执行。

tasklet的数据结构

tasklet描述符

struct tasklet_struct
{
    struct tasklet_struct *next;    // 将多个tasklet链接成单向循环链表
    unsigned long state;            //TASKLET_STATE_SCHED(Tasklet is scheduled for execution)  TASKLET_STATE_RUN(Tasklet is running (SMP only))
    atomic_t count;                 // 0:激活tasklet   非0:禁用tasklet
    void (*func)(unsigned long);    // 用户自定义函数
    unsigned long data;             // 函数入参
};

tasklet链表

static DEFINE_PER_CPU(struct tasklet_head, tasklet_vec);   // 低优先级
static DEFINE_PER_CPU(struct tasklet_head, tasklet_hi_vec);// 高优先级

tasklet API接口

// 定义名字为name的非激活tasklet
#define DECLARE_TASKLET(name, func, data) \
struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data }

// 定义名字为name的激活tasklet
#define DECLARE_TASKLET_DISABLED(name, func, data) \
struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(1), func, data }

//动态初始化tasklet
void tasklet_init(struct tasklet_struct *t,
             void (*func)(unsigned long), unsigned long data);

// 函数暂时禁止给定的tasklet被tasklet_schedule调度,直到这个tasklet被再次被enable;若这个tasklet当前在运行, 这个函数忙等待直到这个tasklet退出
static inline void tasklet_disable(struct tasklet_struct *t);

// 函数暂时禁止给定的tasklet被tasklet_schedule调度,直到这个tasklet被再次被enable;若这个tasklet当前在运行, 这个函数忙等待直到这个tasklet退出
static inline void tasklet_enable(struct tasklet_struct *t);

// 调度 tasklet 执行,如果tasklet在运行中被调度, 它在完成后会再次运行; 这保证了在其他事件被处理当中发生的事件受到应有的注意. 这个做法也允许一个 tasklet 重新调度它自己
static inline void tasklet_schedule(struct tasklet_struct *t);

// 调度 tasklet 执行,如果tasklet在运行中被调度, 它在完成后会再次运行; 这保证了在其他事件被处理当中发生的事件受到应有的注意. 这个做法也允许一个 tasklet 重新调度它自己
static inline void tasklet_hi_schedule(struct tasklet_struct *t);

// 调度 tasklet 执行,如果tasklet在运行中被调度, 它在完成后会再次运行; 这保证了在其他事件被处理当中发生的事件受到应有的注意. 这个做法也允许一个 tasklet 重新调度它自己
void tasklet_kill(struct tasklet_struct *t);

tasklet原理

tasklet调度原理

static inline void tasklet_schedule(struct tasklet_struct *t)
{
    if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state))
        __tasklet_schedule(t);
}

void __tasklet_schedule(struct tasklet_struct *t)
{
    __tasklet_schedule_common(t, &tasklet_vec,
                  TASKLET_SOFTIRQ);
}

static void __tasklet_schedule_common(struct tasklet_struct *t,
                      struct tasklet_head __percpu *headp,
                      unsigned int softirq_nr)
{
    struct tasklet_head *head;
    unsigned long flags;

    local_irq_save(flags);
    head = this_cpu_ptr(headp);
    t->next = NULL;
    *head->tail = t;
    head->tail = &(t->next);             // 加入tasklet列表
    raise_softirq_irqoff(softirq_nr);    // 触发软中断
    local_irq_restore(flags);
}

tasklet执行过程

TASKLET_SOFTIRQ对应执行函数为tasklet_action,HI_SOFTIRQ为tasklet_hi_action,以tasklet_action为例:

static __latent_entropy void tasklet_action(struct softirq_action *a)
{
    tasklet_action_common(a, this_cpu_ptr(&tasklet_vec), TASKLET_SOFTIRQ);
}

static void tasklet_action_common(struct softirq_action *a,
                  struct tasklet_head *tl_head,
                  unsigned int softirq_nr)
{
    struct tasklet_struct *list;

    local_irq_disable();
    list = tl_head->head;
    tl_head->head = NULL;
    tl_head->tail = &tl_head->head;   // 获取tasklet链表
    local_irq_enable();

    while (list) {
        struct tasklet_struct *t = list;

        list = list->next;

        if (tasklet_trylock(t)) {
            if (!atomic_read(&t->count)) {
                // 执行tasklet
                if (!test_and_clear_bit(TASKLET_STATE_SCHED,
                            &t->state))
                    BUG();
                t->func(t->data);
                tasklet_unlock(t);
                continue;
            }
            tasklet_unlock(t);
        }

        // 如果t->count的值不等于0,说明这个tasklet在调度之后,被disable掉了,所以会将tasklet结构体重新放回到tasklet_vec链表,并重新调度TASKLET_SOFTIRQ软中断,在之后enable这个tasklet之后重新再执行它
        local_irq_disable();
        t->next = NULL;
        *tl_head->tail = t;
        tl_head->tail = &t->next;
        __raise_softirq_irqoff(softirq_nr);
        local_irq_enable();
    }
}

 

标签:head,struct,void,static,半部,TASKLET,Linux,tasklet
From: https://www.cnblogs.com/riveruns/p/17861112.html

相关文章

  • 本地Linux 服务器实现公网SSH远程连接
     公网SSH远程连接Linux的好处在于可以在任何地方通过互联网连接到Linux服务器,无需在服务器所在的局域网内。这样可以方便地进行远程管理、维护和操作,提高了工作效率和灵活性。同时,公网SSH连接还可以加强服务器的安全性,因为可以通过SSH协议进行加密通信,保护数据的安全性。下面简......
  • Linux学习总结7
    文件搜索 find/-namefile1从'/'开始进入根文件系统搜索文件和目录 find/-useruser1搜索属于用户'user1'的文件和目录 find/home/user1-name\*.bin在目录'/home/user1'中搜索带有'.bin'结尾的文件 find/usr/bin-typef-atime+100搜索在过去100天内未......
  • Linux基本命令之文件权限(一)
    一、文件权限文件的权限针对三类对象进行定义owner属主,缩写ugroup属组,缩写gother其他,缩写o每个文件针对每类访问者定义了三种主要权限r:Read读w:Write写x:eXecute执行另X:针对目录加执行权限,文件不加执行权限(因文件具备执行权限有安全隐患)注意:root账户不受文件权限的......
  • Linux基本命令之用户管理(二)
    用户组管理命令添加用户组groupadd[选项]组名选项: -gGID: #指定组ID修改用户组groupmod[选项]组名选项: -gGID: #修改组ID -n新组名: #修改组名例如将user1改为user2(但不建议修改组名):groupmod-nuser1user2删除用户组groupdel组名如果该组没有初始用户才可进行删......
  • Linux文件权限
     权限的意义在于允许某一个用户或某个用户组以规定的方式去访问某个文件。基本权限UGO  首先介绍U、G、O这三个字母所代表的含义。   U:owne,属主   G:group,属组   O:other,其他用户  Linux系统通过U、G、O将用户分为三类,并对这三类用户分别设置三种......
  • 第十四周 Linux课后技术总结
    2.3Vim编辑器安装Vim使用yum-yinstallvim-enhancedVim常用命令......2.4文件时间查看文件时间2.5文件类型看第一个字符,开头为-的是普通文件,开头为d的是目录文件(蓝色)。......
  • 【linux常见问题】Aws机器磁盘在线扩容
    Aws机器磁盘在线扩容获取需求(adc机器磁盘扩容至50G--原磁盘:30G)aws控制台登录3、选择卷组4、修改卷组登录实例修改实际大小a、通过df-h查看磁盘目前大小目前磁盘大小(30G)b、通过lsblk查看存储卷的真实size以及分区情况--磁盘已扩容但并未实际纳入使用存储卷已经调整为50G其上只有......
  • linux心得
    前几次上课时对Linux系统和命令还不是很熟练,能深入理解体会的却也不是太多,在虚拟机里反复练。    通过一次又一次重复的敲命令和记命令来熟悉命令,还有老师上课要求我们去默写命令促使我们更好的记住命令,来学好这门课。从开始的的虚拟机的安装,一开始还没有界面,通过上网查......
  • linux 查看GPU程序占用
    nvidia-smi查看gpu的具体占用情况。ps-f-pPID查看某个程序的详细信息。参考:https://www.cnblogs.com/dyc99/p/14597853.html......
  • Linux--I/O重定向与管道
    首先用一个例子来描述重定向的含义: 在生产环境中,每天凌晨需要备份娄据库,这时工作人员会编写一个简单的脚本创建计划任务,把脚本执行结果放到一个或几个文件中以便第二天查看,这个过程就叫重定向。在使用“psaux”命令时,为了快速找到所需信息,经常使用grep命令进行过滤,此时就需要......