一、中断嵌套
   当系统正在执行某中断处理函数时,又产生了一个新的中断,这就叫做中断嵌套。当中断为慢速中断时,新的中断会取代当前中断,即当前中断没有执行完就结束
了;当中断为快速中断时,新的终端就不会产生。这两种情况都是我们不愿意看到的情况,所以就有了今天的题目——中断分层。

二、中断分层
  中断分层是将中断处理函数分为上下两个部分。上半部是与硬件相关的,下半部是与硬件无关的。与硬件无关的内容我们就可以将它分离出中断处理函数,交给内核在系统空闲的时候处理,这样就缩短了中断处理的时间,从而减小了中断丢失的几率。
  分层方式:
    1、软中断
    2、tasklet
    3、工作队列
三、工作队列处理方式
  将中断下半部分的工作挂载到工作队列中去,在内核空闲的时候将工作调用。Linux内核使用struct    workqueue_struct来描述一个工作队列,用struct    work_struct来描述一个工作项。

struct workqueue_struct {
unsigned int flags; /* I: WQ_* flags */
union {
struct cpu_workqueue_struct __percpu *pcpu;
struct cpu_workqueue_struct *single;
unsigned long v;
} cpu_wq; /* I: cwq's */
struct list_head list; /* W: list of all workqueues */ struct mutex flush_mutex; /* protects wq flushing */
int work_color; /* F: current work color */
int flush_color; /* F: current flush color */
atomic_t nr_cwqs_to_flush; /* flush in progress */
struct wq_flusher *first_flusher; /* F: first flusher */
struct list_head flusher_queue; /* F: flush waiters */
struct list_head flusher_overflow; /* F: flush overflow list */ mayday_mask_t mayday_mask; /* cpus requesting rescue */
struct worker *rescuer; /* I: rescue worker */ int saved_max_active; /* W: saved cwq max_active */
const char *name; /* I: workqueue name */
};

  

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

  1、创建工作队列
  create_workqueue(name)
  参数:name为const char *类型,创建工作队列的名字
  返回值:struct    workqueue_struct*型指针
  2、创建工作
  INIT_WORK(_work, _func)
  参数:

    work:创建好工作项变量的地址
    func:工作项中的成员func的名字
  无返回值
  3、提交工作
  即将工作项挂载到工作队列中去。
  int    queue_work(struct workqueue_struct *wq, struct work_struct *work)
  参数:

    wq:工作队列变量的地址
    work:工作项变量的地址

  

  其实Linux内核已创建好了一个默认的工作队列供用户使用,keventd_wq,这样我们就不用再去进行创建工作队列的工作。提交工作项到默认工作队列的函数为
  int    schedule_work(struct work_struct *work)
  参数:要提交工作项的地址

工作队列应用代码:

#include <linux/module.h>
#include <linux/init.h> struct work_struct *work1,*work2; void work1_func()
{
printk("this is work1\n");
} void work2_func()
{
printk("this is work2\n");
} int que_init()
{
/*创建工作*/
work1 = kmalloc(sizeof(struct work_struct),GFP_KERNEL); INIT_WORK(work1, work1_func); /*挂载工作到工作队列*/
schedule_work(work1); /*创建工作*/
work2 = kmalloc(sizeof(struct work_struct),GFP_KERNEL); INIT_WORK(work2, work2_func); /*挂载工作到工作队列*/
schedule_work(work2); return ;
} void que_exit()
{ } MODULE_LICENSE("GPL");
module_init(que_init);
module_exit(que_exit);

将中断分层应用到键盘中断驱动程序中:

#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/interrupt.h>
#include <linux/io.h> #define GPGCON 0x56000060 /*定义工作队列*/
struct work_struct *work1; void work1_func()
{
printk("press key down\n");
}
int que_init()
{
/*创建工作*/
work1 = kmalloc(sizeof(struct work_struct),GFP_KERNEL); INIT_WORK(work1, work1_func);
} /*中断处理函数*/
irqreturn_t key_int(int irq, void *dev_id)
{
/*1、检测设备是否产生中断*/ /*2、清除中断产生标志*/ /*3、提交下半部分工作*/
schedule_work(work1); return ;
} void key_hw_init()
{
unsigned int data;
unsigned int *gpio_config; gpio_config = ioremap(GPGCON,);
data = readw(gpio_config);
data &= (()|(<<)|(<<)|(<<)|(<<)|(<<));//~(0b11);
data |= (|(<<)|(<<)|(<<)|(<<)|(<<));//0b10;
writew(data,gpio_config);
} int key_open(struct inode *node, struct file *filp)
{
return ;
} struct file_operations key_fops =
{
.open = key_open,
//.unlocked_ioctl = key_ioctl,
}; struct miscdevice key_miscdev =
{
.minor = ,
.name = "key",
.fops = &key_fops,
}; static int key_init()
{
/*注册设备*/
misc_register(&key_miscdev); /*硬件初始化*/
key_hw_init(); /*注册中断*/
request_irq(IRQ_EINT8,key_int,IRQF_TRIGGER_FALLING ,"key", );
request_irq(IRQ_EINT11,key_int,IRQF_TRIGGER_FALLING ,"key", );
request_irq(IRQ_EINT13,key_int,IRQF_TRIGGER_FALLING ,"key", );
request_irq(IRQ_EINT14,key_int,IRQF_TRIGGER_FALLING ,"key", );
request_irq(IRQ_EINT15,key_int,IRQF_TRIGGER_FALLING ,"key", );
request_irq(IRQ_EINT19,key_int,IRQF_TRIGGER_FALLING ,"key", ); que_init();
printk("key.ko is ready\n");
return ;
} static void key_exit()
{
/*注销设备*/
misc_deregister(&key_miscdev);
/*注销中断*/
free_irq(IRQ_EINT8, );
} MODULE_LICENSE("GPL");
module_init(key_init);
module_exit(key_exit);

实现功能:

  当按下一个按键,在串口中打印出对应的信息。

此代码适用mini2440开发板,不同型号开发板IO口和中断号不同。如果有疑问或建议,欢迎指出。

Linux中断分层技术的更多相关文章

  1. Linux中断分层--软中断和tasklet

    1. Linux中断分层 (1)上半部:当中断发生时,它进行相应的硬件读写,并“登记”该中断.通常由中断处理程序充当上半部.(一般情况下,上半部不可被打断) (2)下半部:在系统空闲的时候,对上半部“ ...

  2. Linux中断分层--工作队列

    1. 工作队列是一种将任务推后执行的方式,它把推后的任务交由一个内核线程去执行.这样中断的下半部会在进程上下文执行,他允许重新调度甚至睡眠.每个被推后的任务叫做“工作”,由这些工作组成的队列称为工作队 ...

  3. Linux设备驱动之中断支持及中断分层

    快速中断:在开启快速中断时,其他中断不会打断快速中断. 多个中断共享一个中断号. 中断行为受到限制: 1.不能使用可能引起阻塞的函数 2.不能使用可能引起调度的函数 中断注册:request_irq( ...

  4. Linux中断管理 (1)Linux中断管理机制

    目录: <Linux中断管理> <Linux中断管理 (1)Linux中断管理机制> <Linux中断管理 (2)软中断和tasklet> <Linux中断管 ...

  5. Linux中断管理 (3)workqueue工作队列

    目录: <Linux中断管理> <Linux中断管理 (1)Linux中断管理机制> <Linux中断管理 (2)软中断和tasklet> <Linux中断管 ...

  6. Linux kprobe调试技术使用

    kprobe调试技术是为了便于跟踪内核函数执行状态所设计的一种轻量级内核调试技术. 利用kprobe技术,可以在内核绝大多数函数中动态插入探测点,收集调试状态所需信息而基本不影响原有执行流程. kpr ...

  7. Linux中断概述

    中断和异常 1.1中断的由来及实质 Linux内核要管理计算机上的硬件设备,首先要和他们通信.而处理器的速度跟外围硬件设备的速度往往不在一个数量级上,因此,如果内核采取让处理器向硬件发出一个请求,然后 ...

  8. Linux内核调试技术——jprobe使用与实现

    前一篇博文介绍了kprobes的原理与kprobe的使用与实现方式,本文介绍kprobes中的另外一种探測技术jprobe.它基于kprobe实现,不能在函数的任何位置插入探測点,仅仅能在函数的入口处 ...

  9. Linux中断管理 (3)workqueue工作队列【转】

    转自:https://www.cnblogs.com/arnoldlu/p/8659988.html 目录: <Linux中断管理> <Linux中断管理 (1)Linux中断管理机 ...

随机推荐

  1. Firefox中firebug和xpath checker工具的使用

    一直想把自己这段时间做的东西整理下,确迟迟没有动手,现在信息抽取工作已经做的差不多,把自己感觉很好用的两个工具介绍给大家吧!    Firefox真是一个好东西,它许多插件.本人是很讨厌插件的,每次电 ...

  2. SKPhysicsBody类

    继承自 NSObject 符合 NSCodingNSCopyingNSObject(NSObject) 框架  /System/Library/Frameworks/SpriteKit.framewo ...

  3. linux经常使用命令

    linux经常使用命令 pwd 查看当前工作文件夹的绝对路径 cat input.txt 查看input.txt文件的内容 ls 显示当前文件夹下全部的文件及子文件夹 rm recommender-d ...

  4. ios开发应用内实现多语言自由切换

    需求描述:应用内部有一按钮,点击切换语言(如中英文切换).说起来这个是好久以前做的一个功能点了,刚开始也是没有头绪,后来解决了发现很简单,把方法分享一下.1.原理.查看NSLocalizedStrin ...

  5. WIN32读写INI文件方法

      在程序中经常要用到设置或者其他少量数据的存盘,以便程序在下一次执行的时候可以使用,比如说保存本次程序执行时窗口的位置.大小.一些用户设置的 数据等等,在 Dos 下编程的时候,我们一般自己产生一个 ...

  6. Array.asList:数组转list时你一定要知道的“陷阱”!

    最近开发中,业务上处理,经常用到asList方法,这让我不经想起了它的很多容易让人犯错的地方或者误解的地方,所以就想抽出时间来,整理一下,和大家分享出来,深夜了,话不多说,主要以代码为主,简易的代码, ...

  7. 修改用户的home路径

    1.直接修改/etc/passwd文件 2.usermod -d /hadoop -u 1531 附:usermod详细参数 语 法:usermod [-LU][-c <备注>][-d & ...

  8. Python字典--笔记

    <Python3程序开发指南> 映射:键-值数据项的组合 Python3支持两种无序的映射类型:内置的dict类型.标准库中的collections.defaultdict类型. Pyth ...

  9. 面试题 HashMap 数据结构 实现原理

    数据结构 HashMap的数据结构 数据结构中有数组和链表来实现对数据的存储,但这两者基本上是两个极端. 数组:数组存储区间是连续的,占用内存严重,故空间复杂的很大.但数组的二分查找时间复杂度小,为O ...

  10. java的final变量理解

    java的final变量理解 final基本类型是数值不能改变 final对象是引用不能改变,对象其自身是可以被修改的.