linux中断分为顶半部与低半部,顶半部主要用来处理紧急的功能,如硬件中断;不能花太长的时间在处理,所以这里引入低半部,顶半部产生的中断进行登记,然后又低半部进行处理。
1. linux中断编程 1.1 申请中断 int request_irq(unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *devname, void * dev_id); 注解: irq:是中断申请号 handler: 低半部中断处理函数 irqflags:中断处理属性,IRQF_TRIGGER_RAISING, IRQF_TRIGGER_FALLING, IRQF_TRIGGER_HIGH, IRQF_TRIGGER_LOW, 在处理方面若设置了IRQF_DISABLED, 表明是快速中断,处理程序在调用时会屏蔽所有中断,慢速处理程序就不会;若 设置了IRQF_SHARD,则表示多个设备中断共享; 1.2 释放中断 void free_irq(unsigned int irq, void *dev_id); 1.3低半部机制 低半部机制主要有tasklet、工作队列和软中断; 1.3.1 tasklet void my_tasklet_func(unsigned long); //定义一个处理函数 DECLARE_TASKLET(my_tasklet, my_tasklet_func, data); //定义一个my_tasklet结构体,并将它与my_tasklet_func函数绑定; 当以上两步完成之后,在中断处理函数handler中调用tasklet_schedule(&my_tasklet)处理中断; 1.3.2 工作队列 struct work_struct my_wq; //定义一个工作队列 void my_wq_func(unsigned long); //定义一个处理函数 INIT_WORK(&my_wq, (void (*)(void*)) my_wq_func, NULL); //初始化等待队列 当以上两步完成之后,在中断处理函数handler中调用schedule_work(&my_wq)处理中断; 1.3.3 软中断 open_softirq(); //注册软中断对应的处理函数 raise_sftirq(); //触发一个软中断 *NOTE* 软中断和tasklet运行于软中断上下文,仍然属于原子上下文的一种,而工作队列则运行于进程上下文,因此前者不能休眠,后 者允许休眠 2. Linux定时器编程 2.1 定时器结构体 struct timer_list my_timer_list; 2.2 初始化定时器 void init_timer(struct timer_list *timer); 2.3 增加定时器 void add_timer(struct timer_list *timer); 2.4 删除定时器 int del_timer(struct timer_list *timer); 2.5 修改定时器 int mod_timer(struct timer_list *timer, unsigned long experise); 3. 内核延时 3.1 短延迟 void ndelay(unsigned long nsecs); void udelay(unsigned long usecs); void mdelay(unsigned long msecs); 这个几个函数是忙等待,耗CPU资源,mdelay建议用下面的 void msleep(unsigned int millisecs); unsigned long msleep_interrupt(unsigned int millisecs); void ssleep(unsigned int seconds); 3.2 长延迟 time_before(); time_afer(); 3.3 睡着延迟 schedule_timeout()