linux驱动学习笔记---实现中断下半部以及驱动编写规范(七)

中断下半部:

tasklet :
struct tasklet_struct
{
    struct tasklet_struct *next;
    unsigned long state;
    atomic_t count;
    
    void (*func)(unsigned long); //下半部要执行的代码
    unsigned long data; // 传递给func的参数
};
    
    1, 初始化tasklet 
        tasklet_init(struct tasklet_struct * t, void(* func)(unsigned long), unsigned long data)
    2, 在中断上半部,将tasklet加入到内核线程
    
        tasklet_schedule(struct tasklet_struct * t)
    
    
    3, 模块卸载的时候,需要从内核线程中移除tasklet
    
        tasklet_kill(struct tasklet_struct * t)
------------------------------------------------------------------
typedef void (*work_func_t)(struct work_struct *work);
struct work_struct {
    atomic_long_t data;
    struct list_head entry;
    work_func_t func;//下半部要执行的代码
};

    
    1, 初始化work
    INIT_WORK(struct work_struct * work, work_func_t func);
    
    work_func_t func为结构体struct work_struct中的函数指针;
    2, 在中断上半部,将work加入到内核线程
    schedule_work(struct work_struct * work);
    
    
    3, 模块卸载的时候,需要从内核线程中移除work
    cancel_work_sync(struct work_struct * work)

 

 

工作队列(work queue)是另外一种将工作推后执行的形式,它和前面讨论的tasklet有所不同。工作队列可以把工作推后,交由一个内核线程去执行,也就是说,这个下半部分可以在进程上下文中执行。这样,通过工作队列执行的代码能占尽进程上下文的所有优势。最重要的就是工作队列允许被重新调度甚至是睡眠。

那么,什么情况下使用工作队列,什么情况下使用tasklet。如果推后执行的任务需要睡眠,那么就选择工作队列。如果推后执行的任务不需要睡眠,那么就选择tasklet。另外,如果需要用一个可以重新调度的实体来执行你的下半部处理,也应该使用工作队列。它是唯一能在进程上下文运行的下半部实现的机制,也只有它才可以睡眠。这意味着在需要获得大量的内存时、在需要获取信号量时,在需要执行阻塞式的I/O操作时,它都会非常有用。如果不需要用一个内核线程来推后执行工作,那么就考虑使用tasklet。

引用: https://blog.csdn.net/av_geek/article/details/41278801

一个为 struct tasklet_struct *next任务链表,一个为struct list_head entry;内核链表

驱动编写规范

设计一个对象描述所有的全局变量

//设计一个对象类型--描述所有的全局的变量
struct s5pv210_key{
	__u8 have_data; //用于描述是否有数据
	int major ; //记录主设备号
	struct class *cls; //用于创建 类
	struct device *dev; //用来创建设备文件
	wait_queue_head_t wq_head; //用于实现阻塞的等待队列头
	struct key_event event; //用于存放数据的包
	struct work_struct work;//用于实现中断下半部
};

 声明一个对象

//声明一个对象
struct s5pv210_key  *key_dev;

初始化时统一申请空间(这也是好处之一) 

	// 0-为全局设备/数据对象分配空间
	//参数2--标志--分配内存方式, GFP_KERNEL(如果当前内存不够的时候会等待)
	key_dev = kzalloc(sizeof(struct s5pv210_key), GFP_KERNEL);

 错误判断

if(key_d
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值