Linux驱动开发-中断分层机制_工作队列 笔记 7

来源:互联网 发布:逐浪cms怎么样 编辑:程序博客网 时间:2024/05/16 15:42

中断分层机制_工作队列

1.工作队列概念:

a) 任务推后执行b) 被推后的任务由“内核线程”执行c) 允许重新调度和睡眠d) 这些被推后的工作组成一个双向链表,既称为工作队列

2.运行机制

工作队列

注释:

1.每个CPU都有独立的工作队列2.每个工作队列形成一个双向链表3.执行时由内核的一个线程去处理,执行的时机不确定;只有在线程觉得CPU有能 力处理时才去去工作队列的内容去执行

3.工作队列的相关结构

struct work_struct {atomic_long_t data; /*原子类型数据*/struct list_head entry; /*链表入口*/work_func_t func; /*工作函数*/#ifdef CONFIG_LOCKDEPstruct lockdep_map lockdep_map;#endif};struct workqueue_struct;/*好多成员*/

4.工作队列实现过程和相关函数:

法一:交给内核创建默认工作队列

a) 定义工作队列

struct work_struct xx_wq;

b) 定义工作函数

static work_func_t  work_fun(unsingend int xxx)

c) 初始化工作队列,将工作队列与处理函数绑定

INIT_WORK(&xx_wq, work_fun);

d) 提交工作到默认队列;既工作的创建由内核自行处理

schedule_work(&xx_wq);

法二:手工创建工作队列

a) 定义工作队列

struct work_struct  work; /*定义工作*/
workqueue_struct* wq; /*定义的队列*/

b) 定义工作函数

static work_func_t  work_fun(unsingend int xxx)

c) 创建名字为 “mywork” 的工作队列

wq = create_workqueue(“mywork”);

d) 初始化工作队列

INIT_WORK(&xx_wq, work_fun);

e) 提交工作队列

int queue_work(wq, $work);

5.工作队列在中断分层技术的应用

/*1.定义结构体*/struct work_struct xx_wq;/*2.编写底半部函数,既工作函数*/void xxx_do_work(unsigned long x){...}/*4.中断处理顶半部*/static irqreturn_t xxx_interrupt(int irq, void *dev_id){.../*提交工作 并启动调度*/schedule_work(&xx_wq);...}/*5.模块加载*/module_init(xxxx){  ...../*申请中断*//*初始化工作队列,将工作队列与处理函数绑定,这个可以在open函数初始化*/INIT_WORK(&xx_wq,xxx_do_work);       ......}/*6.模块卸载*/module_exit(yyyy){/*释放中断*/}

工作队列模块测试

/*author : hnteadate: 2016/3/14function : key interrupt  work  test*/#include<linux/module.h>#include<linux/init.h>#include<linux/miscdevice.h>#include<linux/fs.h>#include<linux/types.h>#include<linux/io.h>#include<linux/interrupt.h>#define DEV_MINIR 11 /*自己随便取咯*/#define DEV_NAME "key" /*自己随便取咯,该设备名会在 /dev目录下生成相应的设备文件*/#define KEY_GPH0CON  0xE0200C00 /*key_1 /key_2 EXIT0/1*//*定义 work */struct work_struct work1;/******************************************函数名: key_hardinit函数功能:硬件初始化******************************************/void key_hardinit(void){    unsigned int *key_ioconfig = 0;    unsigned int *irq_mask = 0;    unsigned int *irq_enable = 0;    unsigned int temdata = 0;    /*GPIO初始化 32位寄存器*/    key_ioconfig = ioremap(KEY_GPH0CON,4);  /*按键1和2设置成外部中断*/    temdata = ioread32(key_ioconfig);    temdata &= (~0xff);    temdata |= 0xff;    iowrite32(temdata,key_ioconfig);    /*中断控制初始化*/}/******************************************中断底半部用工作队列实现******************************************//*定义服务函数,任务提交后只执行一次*/static void my_work1(struct work_struct *work){    printk("I am work1\n");    printk("I am work1,extern interrupt rase!\n");}/*函数名: key_interrupt函数功能:中断服务函数入口*/static irqreturn_t key_interrupt (int irq, void *dev_id){  /*1、顶部,硬件操作*/  /*2、底部,交个工作队列来处理*/    schedule_work(&work1);    return 0;}/*函数名: key_open函数功能:文件操作*/int  key_open(struct inode *inode, struct file *filp){    key_hardinit();    return 0;}/*函数名:函数功能:文件操作*/struct file_operations key_fop ={.open = key_open,};struct miscdevice key={.minor = DEV_MINIR ,.name = DEV_NAME,.fops = &key_fop,};static int keyInit(void){    int ret = 0;    /*1、注册设备文件*/    ret = misc_register(&key);    /*2、注册中断号,IRQF_TRIGGER_FALLING中断号在    : linux/arch/arm/mach-s5pv210/include/mach/irqs.h文件中有定义*/    ret = request_irq(IRQ_EINT0,key_interrupt,IRQF_TRIGGER_FALLING, DEV_NAME, 0);    /*3.初始化工作*/    INIT_WORK(&work1,my_work1);     printk("ret val is:%d\n",ret);    if(ret < 0)    {        printk("EXINT0 request fail!\n");    }else{        printk("EXINT0 request sucess!\n");    }    return 0;}static void keyExit(void){    int ret = 0;    /*注销中断*/    free_irq(IRQ_EINT0, 0);    /*注销混杂设备*/    ret = misc_deregister(&key);    /*注销设备*/}MODULE_LICENSE("GPL");MODULE_AUTHOR("Hntea");module_init(keyInit);module_exit(keyExit);
1 0
原创粉丝点击