⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 (ldd) ch09-中断处理(上)(转载).txt

📁 献给ARM初学者
💻 TXT
📖 第 1 页 / 共 4 页
字号:
(LDD) Ch09-中断处理(上)(转载)
       
       
      第9章 中断处理
       
       
             中断是硬件管理的最终资源。众所周知,设备利用中断来通知软件可以对它进行
      操作了。Linux为中断处理提供了很好的接口。事实上中断处理的接口如此之好,以至于
      编写和安装中断处理程序几乎和编写其它核心函数一样容易。但是由于中断处理程序和
      系统的其它部分是异步运行的,使用时要注意一些事项。
       
       
       
             本章的示例代码使用并口来产生中断。因此,如果你想运行测试程序,你必须给
      你的电烙铁接上电源,即使在上一章的例子程序中你拒绝这样做。
       

       
       
       
             我们用上一章的short模块来示范如何使用中断。这个模块的名字,short,实际
      上是指 short int(这是C语言,不是吗?),提醒我们它要对中断(interrupt)进行处理
       
      准备并口
             虽然我在第8章“硬件管理”的“使用并口”一节已经提到,并口很简单,但它
      也会触发中断。打印机就是利用这种能力来通知lp驱动程序它已准备好接收缓冲区中的
      下一个字符。
       
       
       
             在指定接口这样做之前实际上并不会产生中断;并口标准规定设置2号端口的第4
      位(0x37a,0x27a或其它某个地址)时启动中断报告。short模块在初始化时调用outb设置
      该位。
       
       
       
             启动中断报告之后,每当引脚10(所谓的"ACK"位)上的电平从低变高时,并口都
      会产生一个中断。强迫接口(没有把打印机连到端口上)产生中断的最简单方法是将并
      行插座的引脚9和引脚10相连。为此,你需要一个阳性的25针D型插座和一英寸的电缆线

      行插座的引脚9和引脚10相连。为此,你需要一个阳性的25针D型插座和一英寸的电缆线
       
       
       
             引脚9是并行数据字节中最重要的一位。如果你往/dev/short0中写入二进制数据
      ,就可以产生几个中断。然而,往端口中写入ASCII文本将不会产生中断,因为此时不会
      设置这个最重要的位。
       
       
       
             如果你确实想“看看”产生的中断,那么,仅仅往硬件设备中写是不够的;还必
      须在系统中配置一个软件处理程序。目前,Linux-x86和Linux-Alpha只是简单的确认,
      忽略任何在预料之外的中断。
       
      安装中断处理程序
             中断信号线是宝贵并且非常有限的资源,当只有15或16根中断信号线时尤其如此
      。内核维护了一个类似于I/O端口注册表的中断信号线的注册表。一个模块可以申请一个
      中断通道(或中断请求IRQ,即Interrupt ReQuest),并且,处理完以后还可以释放掉
      它。在<linux/sched.h>头文件中申明的下列函数实现了这个接口:
       
       
       

       
      int request_irq(unsigned int irq,
       
      void (*handler)(int, void*, struct pt_regs *),
       
      unsigned long flags,
       
      const char *device, void *dev_id);
       
      void free_irq(unsigned int irq, void *dev_id);
       
       
       
             注意,1.2版定义了不同的原型。相关的移植问题可参见本章稍后的“IRQ处理程
      序的版本相关性”一节。
       
       
       
             通常,申请中断的函数的返回值为0时表示成功,或者返回一个负的错误码。函
      数返回-EBUSY通知另一个设备驱动程序已经使用了要申请的中断信号线的情况并不常见
      。函数参数定义如下:
       
       

       
       
      unsigned int irq
       
      该参数为中断号。有时从Linux中断号到硬件中断号的映射并不是一对一的。例如,在ar
      ch/alpha/kernel/irq.c文件中可以查看到Alpha上的映射。这里,传递给内核函数的参
      数是Linux中断号而不是硬件中断号。
       
       
       
      void (*handler)(int,void *,struct pt_regs *)
       
             指向要安装的中断处理函数的指针。
       
       
       
      unsigned long flags
       
             如你所想,这是一个与中断管理有关的各种选项的字节掩码。
       
       
       
      const char *device

      const char *device
       
      传递给request_irq的字符串,在/proc/interrupts中用于显示中断的拥有者(参见下一
      节)。
       
       
       
      void *dev_id
       
      这个指针用于共享的中断信号线。它是一个唯一的标志符,更象一个ClientDate(C++中
      的this对象)。设备驱动程序可以自由地任意使用dev_id。除非强制使用中断共享,dev
      _id通常被置为NULL。在后面的“实现一个处理程序”一节中,我们将看到一个使用dev_
      id的实际例子。
       
       
       
      在flags中可以设置的位是:
       
       
       
      SA_INTERRUPT
       
      如果设置该位,就指示这是一个“快速”中断处理程序;如果清除这位,那么它就是一

      如果设置该位,就指示这是一个“快速”中断处理程序;如果清除这位,那么它就是一
      个“慢速”中断处理程序。快速中断处理程序和慢速中断处理程序的概念在下面的“快
      速和慢速处理程序”一节中会谈到。
       
       
       
      SA_SHIRQ
       
             该位表明中断可以在设备间共享。共享的概念在稍后的“中断共享”一节中介绍
       
       
       
      SA_SAMPLE_RANDOM
       
      该位表明产生的中断对/dev/random和/dev/urandom设备要使用的熵池(entropy pool)有
      贡献。读这些设备返回真正的随机数,它们用来帮助应用软件选取用于加密的安全钥匙
      。这些随机数是从一个熵池中取得的,各种随机事件都会对系统的熵池(无序度)有贡献
      。如果你希望设备真正随机地产生中断,你应该置上这个标志。而如果你的中断是可预
      测的(例如,帧捕捉卡的垂直消隐),那就不值得设置这个标志位-它对系统的熵池没有
      任何贡献。更详尽的信息可参见drivers/char/random.c文件中的注释。
       
       

       
       
             中断处理程序可以在驱动程序初始化时或者在设备第一次打开时安装。虽然在in
      it_module函数中安装中断处理程序听起来是个好主意,但实际上并非如此。因为中断信
      号线数量有限,你不会想浪费它们的。你的计算机拥有的设备通常要比中断信号线多。
      如果一个设备模块在初始化就申请了一个中断,会阻碍其它驱动程序使用这个中断,即
      便这个设备根本不使用它占用的这个中断。而在打开设备时申请中断,则允许资源有限
      的共享。
       
       
       
             例如,只要你不同时使用帧捕捉卡和调制解调器这两个设备,它们使用同一个中
      断就是可能的。用户经常在系统启动时装载某个特殊设备的模块,即使这个设备很少使
      用。数据采集卡可以和第二个串口使用同一个中断。尽管在进行数据采集时避免去连你
      的ISP并不是件难事,但在使用调制解调器前不得不先卸载一个模块太令人不愉快了。
       
       
       
             调用request_irq的正确位置是在设备第一次打开,硬件被指示产生中断前的时
      候。而调用free_irq的位置是设备最后关闭,硬件被通知不要再中断处理器后的时候。
      该技术的缺点是你必须为每个设备维护一个记录其打开次数的计数器。而如果你在同一
      个模块中控制两个以上的设备,那么仅仅使用模块计数器那还不够。
       

       
       
       
             尽管我已说了这么多,short却是在装载时申请中断信号线的。我这样做是为了
      使你在运行测试程序时不必运行其它进程来使设备保持打开的状态。因此,short会象真
      正的设备那样,在init_module中而不是short_open中申请中断。
       
       
       
             下面这段代码要申请的中断是short_irq。对这个变量的赋值将在后面再给出,
      因为它与现在的讨论无关。short_base是使用的并口的I/O基地址;写接口的2号寄存器
      打开中断报告。
       
       
       
             if (short_irq >=0 ) {
       
                    result=request_irq(short_irq, short_interrupt, SA_INTERRUPT,
      "short", NULL);
       
                    if (result) {
       
                           printk(KERN_INFO "short: can't get assigned irq 
%i\n",

                           printk(KERN_INFO "short: can't get assigned irq 
%i\n",
      short_irq);
       
                           short_irq=-1;
       
                    }
       
                    else { /*
       
                           outb(0x10, short_base+2);
       
                    }
       
             }
       
       
       
             这段代码显示安装的处理程序是个快速中断处理程序(SA_INTERRUPT),不支持中
      断共享(没有设置SA_SHIRQ),并且对系统熵池无贡献(没有设置SA_SAMPLE_RANDOM)。然
      后调用outb打开并口的中断报告。
       
      /proc接口
             当处理器被硬件中断时,一个内部计数器会被加1,这为检查设备是否正常工作

             当处理器被硬件中断时,一个内部计数器会被加1,这为检查设备是否正常工作
      提供了一个方法。报告的中断显示在文件/proc/interrupts中。下面是我的486启动一个
      半小时(uptime)后该文件的一个快照:
       
       
       
       0:     537598   timer
       
       1:      23070   keyboard
       
       2:          0   cascade
       
       3:       7930 +  serial
       
       5:       4568   NE2000
       
       7:      15920 + short
       
      13:          0   math error
       
      14:      48163 + ide0
       
      15:       1278 + ide1

      15:       1278 + ide1
       
       
       
             第一列是IRQ中断号。你可以从显示中缺少一些中断推知该文件只会显示已经安
      装了驱动程序的那些中断。例如,第一个串口(使用中断号4)没有显示,这表明我现在没
      有使用调制解调器。实际上,即使我在获取这个快照之前使用过调制解调器,它也不会
      出现在这个文件中;串口的行为很良好,当设备关闭时会释放它们的中断处理程序。出
      现在各记录中的加号标志该行中断采用了快速中断处理程序。
       
       
       
             /proc树中还包含了另一个与中断有关的文件,/proc/stat;有时你可能会发现
      一个文件更有用,但有时又更愿意使用另一个。/proc/stat文件记录了关于系统活动的
      一些底层的统计信息,包括(但不仅限于)只系统启动以来接收到的中断次数。stat文件
      的每一行都以一个字符串开始,它是该行的关键字;intr标记正是我们要找的。下面的
      快照是在得到前面那个快照后半分钟获得的:
       
       
       
      intr 947102  540971  23346 0 8795  4907  4568  0  15920  0 0 0 0 0 0  
48317
      1278
       

       

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -