当前位置: 首页 > news >正文

中断管理常用API详解(三)

一、tasklet_disable_nosync(...)

        该函数主要功能为增加tasklet_struct结构体变量中的count字段的值,此结构体描述的软中断不能被调度执行,使其处于睡眠状态。具体Linux内核源码设计如下:

 

【代码案例】

taskletdisablenosynctest.c

#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>

static struct tasklet_struct tl;
static unsigned long data = 0;

// 自定义中断处理函数
static void irqtask_actionfunc(unsigned long data){
    printk("调用自定义中断处理函数:irqtask_actionfunc(...)函数.\n");

    printk("data : %ld\n",data);

    printk("打印输出:OK.\n");

    printk("退出自定义中断处理函数:irqtask_actionfunc(...)函数.\n");
}

static int __init taskletdisablenosync_initfunc(void){
    printk("调用内核模块函数:taskletdisablenosync_initfunc(...)函数.\n");

    tasklet_init(&tl,irqtask_actionfunc,data);
    tasklet_schedule(&tl); // 将软中断加入到等待队列,等待调度执行处理
    printk("调用tasklet_disable_nosync(...)函数之前 count成员值为:%d\n", atomic_read(&tl.count));

    tasklet_disable_nosync(&tl);

    if(atomic_read(&tl.count) != 0) // 测试当前的count成员值
        printk("tasklet is disable(禁用).\n");

    printk("调用tasklet_disable_nosync(...)函数之后 count成员值为:%d\n", atomic_read(&tl.count));
    tasklet_enable(&tl); 
    if(atomic_read(&tl.count) == 0)
        printk("tasklet is enable(启用).\n");

    printk("tasklet count成员值为:%d\n", atomic_read(&tl.count));

    tasklet_kill(&tl); // 等待软中断的执行结束

    printk("退出内核模块函数:taskletdisablenosync_initfunc(...)函数.\n");

    return 0;
}

static void __exit taskletdisablenosync_exitfunc(void){
    printk("正常退出内核:tasklet_disable_nosync(...)函数.\n");
}

MODULE_LICENSE("GPL");
module_init(taskletdisablenosync_initfunc);
module_exit(taskletdisablenosync_exitfunc);

Makefile

#!/bin/bash

ccflags_y += -O2

ifneq ($(KERNELRELEASE),)
obj-m := taskletdisablenosynctest.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

default:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules 
endif

clean:
	rm -rf *.o *.ko *.mod.c

depend .depend dep:
	$(CC)  -M *.c > .depend 

编译插入卸载

二、 tasklet_disable

        该函数的主要功能是增加软中断描述符的count成员的值,让软中断处于睡眠状态(不能响应对应的中断)。具体Linux源码设计如下:

         该函数会暂时禁止给定的tasklet被tasklet_schedule调度,知道这个tasklet被再次enable。若这个tasklet正在当前执行,这个函数忙等到这个tasklet退出。

tasklet_disable

  • 当前正在运行的 tasklet:当调用 tasklet_disable 时,如果指定的 tasklet 正在某个 CPU 上运行,该函数会进入忙等待状态,直到这个 tasklet 执行完毕。它无法立即终止当前正在运行的 tasklet,只能等待其自然结束。
  • 后续 tasklet 的运行:在等待当前运行的 tasklet 结束后,tasklet_disable 会将该 tasklet 标记为禁用状态。此后,即使有其他事件触发该 tasklet 调度,它也不会再被执行,直到调用 tasklet_enable 重新启用它。

tasklet_disable_nosync

  • 当前正在运行的 tasklettasklet_disable_nosync 不会等待当前正在运行的 tasklet 结束。也就是说,当调用该函数时,如果指定的 tasklet 正在执行,它会继续执行完,tasklet_disable_nosync 不会进行任何等待操作。
  • 后续 tasklet 的运行:调用 tasklet_disable_nosync 后,该 tasklet 会被标记为禁用状态,后续不会再被调度执行,直到调用 tasklet_enable 重新启用它。

        综上所述,这两个函数都不能直接禁止当前正在运行的 tasklettasklet_disable 会等待当前运行的 tasklet 结束后再禁用后续执行,而 tasklet_disable_nosync 则直接禁用后续执行,不等待当前运行的 tasklet 结束。

【代码案例】

 taskletdisabletest.c

#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>

static struct tasklet_struct tl;
static unsigned long data = 0;

static void irqtasklet_actionfunc(unsigned long data){
    printk("data : %ld\n",data);

    printk("调用自定义中断函数:irqtasklet_actionfunc(...)函数.\n");
}

static int __init taskletdisalbe_initfunc(void){
    tasklet_init(&tl,irqtasklet_actionfunc,data);
    tasklet_schedule(&tl);

    printk("调用内核模块函数:taskletdisalbe_initfunc(...)函数.\n");

    printk("输出调用tasklet_disable之前的count成员的值为:%d\n",atomic_read(&tl.count));
    tasklet_disable(&tl); // 调用此函数使tasklet对应的处理函数不能执行
    if(atomic_read(&tl.count)!=0)
        printk("tasklet is disabled.\n");

    printk("输出调用tasklet_disable之后的count成员的值为:%d\n",atomic_read(&tl.count));
    tasklet_enable(&tl); // 调用此函数使tasklet启用
    if(atomic_read(&tl.count)==0)
        printk("tasklet is enabled.\n");

    printk("调用tasklet_enable函数之后tasklet的count成员值为:%d\n",atomic_read(&tl.count));
    tasklet_kill(&tl);

    printk("退出内核模块函数:taskletdisalbe_initfunc(...)函数.\n");

    return 0;
}

static void __exit taskletdisalbe_exitfunc(void){
    printk("正常退出内核:tasklet_disable(...)函数.\n");
}

MODULE_LICENSE("GPL");

module_init(taskletdisalbe_initfunc);
module_exit(taskletdisalbe_exitfunc);

Makefile

#!/bin/bash

ccflags_y += -O2

ifneq ($(KERNELRELEASE),)
obj-m := taskletdisabletest.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

default:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules 
endif

clean:
	rm -rf *.o *.ko *.mod.c

depend .depend dep:
	$(CC)  -M *.c > .depend 

编译插入卸载

 

https://github.com/0voice

http://www.dtcms.com/a/98166.html

相关文章:

  • flatMap 介绍及作用
  • C#连接sqlite数据库实现增删改查
  • 大模型最新面试题系列:微调篇之微调框架(二)
  • AI赋能python数据处理、分析与预测操作流程
  • Vue背景介绍+声明式渲染+数据响应式
  • 基于Baklib的云内容中台落地实践
  • JMeter运行日志详细分析
  • Kafka Stream从入门到精通:构建高吞吐、低延迟的实时流处理应用
  • 力扣.旋转矩阵Ⅱ
  • sqli-labs靶场 less6
  • Android 串口配置
  • 双磁条线跟踪控制
  • LJF-Framework 第12章 LjfFilter拦截器设计
  • hbuilderx打包iOS上传苹果商店的最简流程
  • AI坦克智能决策:MOE模型的动态专家协作与加权融合
  • Python自动化模块:开启高效编程新时代
  • 乘AI之势,劲吹正能量之风:生成式人工智能(GAI)认证引领新时代
  • AudioFlinger与AudioPoliceManager初始化流程
  • unity客户端面试高频2(自用)
  • Redis底层数据结构实现
  • Python 科学计算
  • QML输入控件:Dial外观深度定制(4)
  • angr基础学习
  • 基于改进粒子群算法的多目标分布式电源选址定容规划(附带Matlab代码)
  • 【区块链安全 | 第十篇】智能合约概述
  • Unity编辑器功能及拓展(1) —特殊的Editor文件夹
  • Linux 一键安装 Docker 的万能脚本
  • python和c中作用域的差异
  • Windows 系统中使用 fnm 安装 Node.js 的完整指南
  • 为什么idea显示数据库连接成功,但操作数据库时,两边数据不同步