linux中断机制

 

一、中断基本概念

1、中断的定义

         中断,是指CPU在正常运行程序时,由于内部/外部事件或由程序预先安排的事件引起CPU暂时停止正在运行的程序,转到为该内部/外部事件或预先安排的事件服务的程序中去,服务完毕再返回去继续运行被暂时中断的程序。简单地说就是CPU在忙着作自己的事情,这时候硬件(比如说键盘按了一下)触发了一个电信号,这个信号通过中断线到达中断控制器 8259A,8259A接受到这个信号,向CPU发送INT信号申请CPU来执行刚才的硬件操作,并且将中断类型号也发给CPU,此时CPU就丢下自己正在做的事情,但不是随便丢到旁边而是保存了当前正在做的事情的相关资料,然后去处理这个申请,根据中断类型号找到它的中断向量(也就是中断程序在内存中的 地址),然后去执行这段程序(这段程序是已经写好的,在内存中),执行完后再向8259A发送一个INTA信号表示我已经处理完你刚才的申请。这个时候 CPU就可以继续做它刚才被打断做的事情了,这个时候刚才保存的相关信息就帮助CPU接着执行下面的程序,而不至于忘记自己刚才正在做什么。

 

                 linux中断机制

                              图1.中断示意图

因此一个中断有如下几个主要部分:

中断源:中断源是指打断CPU的事件,没有中断源便没有中断,它可以是硬件的也可以是软件的。

CPU:中断就是要用CPU来处理一些事情的

中断控制器8259A:硬件中断源与CPU之间的桥梁,没有它中断就无法被CPU所知道。

中断服务程序:你打断了CPU,CPU就得根据这个程序来为你办事。

2、 Linux的中断分类:

         Linux的中断通常分为两种:软中断和硬中断。软件中断也称作异常,同步中断,硬件中断也叫异步中断。

3、中断向量

Inter x86共支持256个向量中断,并将它们从0到255进行编号,Inter将这个整数叫做中断向量,Linux对这256个中断向量的分配如下:
1)0~31为异常和非屏蔽中断
2)32~47为可屏蔽中断(硬件中断)
3)48~255用来表示软中断,Linux只用了其中的一个(即128或0x80向量)作为系统调用。

4、中断描述符表

中断描述符表,也叫中断向量表,每个表项叫做门描述符占8个字节,简单的说是用来存放中断处理程序入口函数地址,当然还包括了一些其他信息。其作用就是当一个中断发生时我们根据它的中断号确定其中断向量,然后在此表中找到它的入口函数从而执行它。这个表存放在内存中的一片区域中。我们需要一个系统寄存器——中断描述符寄存器IDTR来存放中断描述符表在内存的起始地址。IDTR占48位,在低字节(低16位)中装的是界 限,在高字节(高32位)中装的是基址。如下图所示:

 

           32位基址

      界限

 47                               16 15                0

 

二、认识linux中断

         在Linux系统中,中断又分为两个半部:上半部(tophalf)和下半部(bottom half)。上半部的功能是"登记中断",当一个中断发生时,它进行相应地硬件读写后就把中断例程的下半部挂到该设备的下半部执行队列中去。因此,上半部 执行的速度就会很快,可以服务更多的中断请求。但是,仅有"登记中断"是远远不够的,因为中断的事件可能很复杂。因此,Linux引入了一个下半部,来完 成中断事件的绝大多数使命。下半部和上半部最大的不同是下半部是可中断的,而上半部是不可中断的,下半部几乎做了中断处理程序所有的事情,而且可以被新的 中断打断!下半部则相对来说并不是非常紧急的,通常还是比较耗时的,因此由系统自行安排运行时机,不在中断服务上下文中执行。因此,对上半部内核立即执行,而下半部留待稍候处理。上半部运行时是关中断的,下半部运行时是允许中断请求的。上半段只能通过中断处理程序实现,下半部可以通过很多机制来实现:小任务机制(tasklet),工作队列,软中断。

中断号的查看可以使用下面的命令:“cat /proc/interrupts”。

eg:小任务tasklet的实现

其数据结构为struct tasklet_struct,每一个结构体代表一个独立的小任务,定义如下

struct tasklet_struct

{

    struct tasklet_struct *next;

    unsigned long state;

    atomic_t count;

    void (*func)(unsigned long);

    unsigned long data;

};

声明和使用小任务tasklet

静态的创建一个小任务的宏有一下两个:

#define DECLARE_TASKLET(name, func, data) \

struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data }

#define DECLARE_TASKLET_DISABLED(name, func, data) \

struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(1), func, data }

这两个宏的区别在于计数器设置的初始值不同,前者可以看出为0,后者为1。为0的表示激活状态,为1的表示禁止状态。

 

三、中断应用

1时钟中断

         大部分PC机中有两个时钟源,分别是实时时钟(RTC)和操作系统(OS)时钟。实时时钟也叫CMOS时钟,它靠电池供电,即使系统断电,也可以维持日期和时间。内核可通过0x70和0x71两个I/O端口存取实时时钟。RTC和OS时钟之间的关系通常被称作操作系统的时钟运作机制。不同的操作系统,其时钟运作机制也不同。

         在linux中,用全局变量jiffies表示系统自启动以来的时钟节拍数,在这个基础上,linux又提供了符合人民习惯的时间格式:

struct  timespec{                  //高精度

  long tv_sec;                     //秒

  long tv_nsec;                   //纳秒

};

 

struct  timeval{            

 int tv_sec;

 int tv_usec;                         //微秒

};

Linux中时钟中断处理程序的每一次时钟中断的产生都触发下列几个主要操作:

(1)自系统启动以来所花费的时间

(2)更新时间和日期

(3)确定当前进程在CPU上已运行了多长时间,如果已经超过了分配给它的时间,则抢占它

(4)更新资源使用统计数

(5)检查定时器时间间隔是否已到达,如果是,则调用适当的函数

 

2、中断机制核心数据机构

 

中断机制的核心数据结构是 irq_desc, 它完整地描述了一条中断线。以下为程序源码:

typedef  void (*irq_flow_handler_t)(unsigned int irq, struct irq_desc *desc);

struct irq_desc {

    unsigned int  irq;   

    struct timer_rand_state *timer_rand_state;

    unsigned int   *kstat_irqs;

#ifdef CONFIG_INTR_REMAP

    struct irq_2_iommu  *irq_2_iommu;

#endif

    irq_flow_handler_t   handle_irq;

    struct irq_chip      *chip;

    struct msi_desc      *msi_desc;

    void  *handler_data;

    void  *chip_data;

    struct irqaction  *action;  

    unsigned int     status;      

    unsigned int     depth;    

    unsigned int     wake_depth;  

    unsigned int     irq_count;

    unsigned long     last_unhandled;  

    unsigned int      irqs_unhandled;

    spinlock_t    lock;

#ifdef CONFIG_SMP

    cpumask_var_t     affinity;

    unsigned int      node;

#ifdef CONFIG_GENERIC_PENDING_IRQ

    cpumask_var_t     pending_mask;

#endif

#endif

    atomic_t      threads_active;

    wait_queue_head_t   wait_for_threads;

#ifdef CONFIG_PROC_FS

    struct proc_dir_entry    *dir;

#endif

    const char    *name;

} ____cacheline_internodealigned_in_smp;

 

       在linux系统中,每个中断都得先申请,用完释放,这和我们编程调用文件差不错。都存在一个申请释放的过程。Linux中断的申请与释放:在中,实现中断申请接口:

request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,const char *name, void *dev);

函数参数说明

unsigned int irq:所要申请的硬件中断号

irq_handler_t handler:中断服务程序的入口地址,中断发生时,系统调用handler这个函数。

irq_handler_t为自定义类型,其原型为:

typedef irqreturn_t (*irq_handler_t)(int, void *);

 

而irqreturn_t的原型为:typedef enum irqreturn irqreturn_t;

enum irqreturn {

    IRQ_NONE,

    IRQ_HANDLED,

    IRQ_WAKE_THREAD,

};

此枚举类型irqreturn定义在include/linux/irqreturn.h文件中。

unsigned long flags:中断处理的属性。

const char *dev_name:设备描述,表示那一个设备在使用这个中断。

void *dev_id:用作共享中断线的指针。

 

释放中断,函数原型为:

 

void free_irq(unsigned int irq, void *dev_id);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux中断机制Linux操作系统的核心机制之一,它负责处理外部设备或应用程序发送的中断请求。当一个设备或应用程序需要处理时,它会向处理器发送一个中断请求,这个请求会被操作系统捕获并且分配给相应的处理程序来处理。下面是Linux中断机制的详细知识: 1. 中断向量表 Linux内核中有一个中断向量表,它是一个由中断处理程序地址组成的数组。当一个中断请求被捕获时,处理器会根据中断请求的编定位到中断向量表中对应的地址,然后执行相应的中断处理程序。 2. 中断处理程序 Linux内核中有很多中断处理程序,它们负责处理不同类型的中断请求。当一个中断请求被捕获后,处理器会将控制权转移到相应的中断处理程序中,该程序会根据中断请求的类型执行相应的处理操作。 3. 中断控制器 中断控制器是一个硬件设备,它负责将中断请求从外部设备传递到处理器。Linux内核中有很多中断控制器驱动程序,它们负责管理中断控制器并处理中断请求。 4. 中断屏蔽 中断屏蔽是一种机制,它可以暂时屏蔽中断请求的处理。当中断屏蔽被启用时,处理器将会忽略所有的中断请求。这个机制通常被用来处理一些对实时性要求比较高的操作,例如操作系统内部的锁。 5. 中断共享 在Linux中,多个设备或应用程序可能会发送相同的中断请求。为了避免冲突,这些请求可以被共享并由同一个中断处理程序来处理。这个机制可以提高系统的效率并减少资源的浪费。 总之,Linux中断机制Linux操作系统的核心机制之一,它负责处理外部设备或应用程序发送的中断请求。了解中断机制的详细知识可以帮助我们更好地理解Linux操作系统的工作原理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值