学习笔记之中断下半部

中断下半部:由于中断处理力求时间短,所以引出了下半部。
tasklet工作在中断上下文,处理中不允许休眠,而workqueue工作在进程上下文,这是不同点。
1,softirq: 处理比较快,但是内核级别的机制,需要修改整个内核源码,不推荐也不常用
2,tasklet: 内部实现实际调用了softirq
3, workqueue: 工作队列

1,tasklet:
	struct tasklet_struct
	{
		struct tasklet_struct *next;
		unsigned long state;
		atomic_t count;
		void (*func)(unsigned long); // 下半部的实现逻辑
		unsigned long data; // 传递给func
	};

	a, 初始化
		struct tasklet_struct mytasklet;

		tasklet_init(struct tasklet_struct * t, void(* func)(unsigned long), unsigned long data)

		例子:
		void key_tasklet_half_irq(unsigned long data)
		{
			// 表示有数据,需要去唤醒整个进程/等待队列
			wake_up_interruptible(&key_dev->wq_head);
			//同时设置标志位
			key_dev->key_state  = 1;

			//发送信号
			kill_fasync(&key_dev->faysnc, SIGIO, POLLIN);
		}

		tasklet_init(&key_dev->mytasklet, key_tasklet_half_irq, 45);


	b,在上半部中放入到内核线程中--启动
		// 启动下半步
		tasklet_schedule(&key_dev->mytasklet);

	c,模块卸载的时候:
		tasklet_kill(&key_dev->mytasklet);


2,工作队列和工作
	typedef void (*work_func_t)(struct work_struct *work);

	struct work_struct {
		atomic_long_t data;
		struct list_head entry;
		work_func_t func;
	};

	a, 初始化
		
		void work_irq_half(struct work_struct *work)
		{
			printk("-------%s-------------\n", __FUNCTION__);
			// 表示有数据,需要去唤醒整个进程/等待队列
			wake_up_interruptible(&key_dev->wq_head);
			//同时设置标志位
			key_dev->key_state  = 1;

			//发送信号
			kill_fasync(&key_dev->faysnc, SIGIO, POLLIN);
			
		}
		struct work_struct mywork;

		INIT_WORK(struct work_struct *work, work_func_t func);

	b, 在上半部中放入到内核线程中--启动

		schedule_work(&key_dev->mywork);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值