中断处理和内核数据结构

版权声明:没有技术的的技术宅 https://blog.csdn.net/qq_23084801/article/details/82423719

注册中断

并口的标准规定设置端口2的第4位将启动中断报告,short 模块调用outb来设置这个位。开启之后,每当引脚10的电平从低到高改变时,并口就会产生一个中断。(连接输出口到引脚10可软件控制产生中断)

内核维护一个中断信号线的注册表,模块在使用中断前要先请求一个中断通道(或中断请求IRQ)。中断报告显示在文件/proc/interrupts中。

int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *)
                , unsigned long flags, const char *dev_name, void *dev_id);
dev_id用于共享的中断信号线

中断处理程序不能向用户空间发送或接收任何数据,因为它在任何进程上下文中执行;也不能做任何可能发生休眠的操作。

检测IRQ号

设备将要使用哪条IRQ 信号线的自动检测是驱动程序的基本要求。

unsigned long probe_irq_on(void);返回未分配中断的位掩码
int probe_irq_off(unsigned long);
probe_irq_on之后启动中断,产生中断,关闭该中断
然后调用probe_irq_off(参数上前函数的返回值)返回irq号


禁用单个中断
void disable_irq(int irq);

禁用所有中断
void local_irq_disable(void);
 

 顶半部和底半部

顶半部是实际响应中断的例程,即request_irq中注册的程序。底半部被顶半部调用并在稍后更安全的时间执行。底半部执行时所有中断都是打开的。典型的情况是顶半部保存设备的数据到设备特定的缓冲区并调用底半部。tasklet通常是底半部处理的优选机制,这种机制快而且所有tasklet代码必须是原子的。还可以使用工作队列,其有更高的延迟,但允许休眠。

tasklet是一个由系统决定在软件中断上下文被调度运行的特殊函数。不会有同一个tasklet的多个实例并行的运行,因为它们 只运行一次,但tasklet 可以和其他tasklet并行的运行在SMP系统。tasklet可确保和第一次调度它们的函数运行在同样的CPU上。

内核的数据结构

内核中的普通内存地址通常是unsigned long。 至少在当前Linux支持的所有平台 上,指针和long整形的大小总是相同的。

Linux特有的类型
无符号 u8, u16, u32, u64
有符号 s8, s16, s32, s64

如果用户空间程序需要使用这些类型,它可以在名字前面加上两个下划线作为前缀。__u8和其他类型是独立于__KERNEL__定义的。如果使用-Wall 编译选项并且细心的清除了所有警告,就可以确信代码是可移植的了。使用内存页时,要记住内存页的大小是PAGE_SIZE而不是64K。

#include <asm/page.h>
int order = get_order(16*1024);
buf = get_free_pages(GFP_KERNEL, order);

猜你喜欢

转载自blog.csdn.net/qq_23084801/article/details/82423719