linux中断--内核中断编程

  Linux中断内核编程

  前言

  在前面分析了中断的基本原理后,就可以写一个内核中断程序来体验以下,也可以借此程序继续深入来了解内核中断的执行过程

  一.内核中断程序:

  我们还是来看一看成程序:

  在看程序之前,要熟悉如何进行模块编程,和了解module_pararm()的用法。如果不熟悉的话请大家看,module_param()的学习和Linux内核模块编程,在此不作解释。

  1.程序interrupt.c

  [c-sharp] view plaincopy

  1 /* 2 *file name :interrupt.c

  3 *atuthor : john 4 */

  5 #include 6 #include

  7 #include 8 #include

  9 10 MODULE_LICENSE("GPL");

  11 static int irq; 12 char *interface;

  13 static irqreturn_t myirq_handler(int irq,void *dev); 14

  15 static int __init myirq_init(void) 16 {

  17 printk("the module is working!/n"); 18 printk("the irq is ready for working!/n");

  19 if(request_irq(irq,myirq_handler,IRQF_SHARED,interface,&irq)){ 20 printk(KERN_ERR "%s interrrupt can't register %d IRQ /n",interface,irq);

  21 return -EIO; 22 }

  23 printk("%s request %d IRQ/n",interface,irq); 24 return 0;

  25 } 26 static irqreturn_t myirq_handler(int irq,void *dev)

  27 { 28 printk("%d IRQ is working/n",irq);

  29 return IRQ_NONE; 30 }

  31 static void __exit myirq_exit(void) 32 {

  33 printk("the module is leaving!/n"); 34 printk("the irq is bye bye!/n");

  35 free_irq(irq,&irq); 36 printk("%s interrupt free %d IRQ/n",interface,irq);

  37 38 }

  39 module_init(myirq_init); 0 module_exit(myirq_exit);

  41 module_param(interface,charp,0644); 42 module_param(irq,int,0644);

  43 [c-sharp] view plaincopy

  1 obj-m:=tiger.o 2

  3 CURRENT_PATH:=$(shell pwd) 4 VERSION_NUM:=$(shell uname -r)

  5 LINUX_PATH:=/usr/src/linux-headers-$(VERSION_NUM) 6

  7 8 all :

  9 make -C $(LINUX_PATH) M=$(CURRENT_PATH) modules 10 clean:

  11 make -C $(LINUX_PATH) M=$(CURRENT_PATH) clean [c-sharp] view plaincopy

  /* * These flags used only by the kernel as part of the

  * irq handling routines. *

  * IRQF_DISABLED - keep irqs disabled when calling the action handler * IRQF_SAMPLE_RANDOM - irq is used to feed the random generator

  * IRQF_SHARED - allow sharing the irq among several devices * IRQF_PROBE_SHARED - set by callers when they expect sharing mismatches to occur

  * IRQF_TIMER - Flag to mark this interrupt as timer interrupt * IRQF_PERCPU - Interrupt is per cpu

  * IRQF_NOBALANCING - Flag to exclude this interrupt from irq balancing * IRQF_IRQPOLL - Interrupt is used for polling (only the interrupt that is

  * registered first in an shared interrupt is considered for * performance reasons)

  */ #define IRQF_DISABLED 0x00000020

  #define IRQF_SAMPLE_RANDOM 0x00000040 #define IRQF_SHARED 0x00000080

  #define IRQF_PROBE_SHARED 0x00000100 #define IRQF_TIMER 0x00000200

  #define IRQF_PERCPU 0x00000400 #define IRQF_NOBALANCING 0x00000800

  #define IRQF_IRQPOLL 0x00001000

  [c-sharp] view plaincopy

  113struct irqaction { 114 irq_handler_t handler;

  115 unsigned long flags; 116 const char *name;

  117 void *dev_id; 118 struct irqaction *next;

  119 int irq; 120 struct proc_dir_entry *dir;

  121 irq_handler_t thread_fn; 122 struct task_struct *thread;

  123 unsigned long thread_flags; 124};

  125 [c-sharp] view plaincopy

  175struct irq_desc { 176 unsigned int irq;

  177 struct timer_rand_state *timer_rand_state; 178 unsigned int *kstat_irqs;

  179#ifdef CONFIG_INTR_REMAP 180 struct irq_2_iommu *irq_2_iommu;

  181#endif 182 irq_flow_handler_t handle_irq;

  183 struct irq_chip *chip; 184 struct msi_desc *msi_desc;

  185 void *handler_data; 186 void *chip_data;

  187 struct irqaction *action; /* IRQ action list */ 188 unsigned int status; /* IRQ status */

  189 190 unsigned int depth; /* nested irq disables */

  191 unsigned int wake_depth; /* nested wake enables */ 192 unsigned int irq_count; /* For detecting broken IRQs */

  193 unsigned long last_unhandled; /* Aging timer for unhandled count */ 194 unsigned int irqs_unhandled;

  195 raw_spinlock_t lock; 196#ifdef CONFIG_SMP

  197 cpumask_var_t affinity; 198 const struct cpumask *affinity_hint;

  199 unsigned int node; 200#ifdef CONFIG_GENERIC_PENDING_IRQ

  201 cpumask_var_t pending_mask; 202#endif

  203#endif 204 atomic_t threads_active;

  205 wait_queue_head_t wait_for_threads; 206#ifdef CONFIG_PROC_FS

  207 struct proc_dir_entry *dir; 208#endif

  209 const char *name; 210} ____cacheline_internodealigned_in_smp;

  211 212extern void arch_init_copy_chip_data(struct irq_desc *old_desc,

  213 struct irq_desc *desc, int node); 214extern void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc);

  215 216#ifndef CONFIG_SPARSE_IRQ

  217extern struct irq_desc irq_desc[NR_IRQS]; [c-sharp] view plaincopy

  111struct irq_chip { 112 const char *name;

  113 unsigned int (*startup)(unsigned int irq); 114 void (*shutdown)(unsigned int irq);

  115 void (*enable)(unsigned int irq); 116 void (*disable)(unsigned int irq);

  117 118 void (*ack)(unsigned int irq);

  119 void (*mask)(unsigned int irq); 120 void (*mask_ack)(unsigned int irq);

  121 void (*unmask)(unsigned int irq); 122 void (*eoi)(unsigned int irq);

  123 124 void (*end)(unsigned int irq);

  125 int (*set_affinity)(unsigned int irq, 126 const struct cpumask *dest);

  127 int (*retrigger)(unsigned int irq); 128 int (*set_type)(unsigned int irq, unsigned int flow_type);

  129 int (*set_wake)(unsigned int irq, unsigned int on); 130

  131 void (*bus_lock)(unsigned int irq); 132 void (*bus_sync_unlock)(unsigned int irq);

  133 134 /* Currently used only by UML, might disappear one day.*/

  135#ifdef CONFIG_IRQ_RELEASE_METHOD 136 void (*release)(unsigned int irq, void *dev_id);

  137#endif 138 /*

  139 * For compatibility, ->typename is copied into ->name. 140 * Will disappear.

  141 */ 142 const char *typename;

  143}; 144

  [c-sharp] view plaincopy

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

  137{ 138 return request_threaded_irq(irq, handler, NULL, flags, name, dev);

  139} 140 [c-sharp] view plaincopy

  1006/** 1007 * request_threaded_irq - allocate an interrupt line

  1008 * @irq: Interrupt line to allocate 1009 * @handler: Function to be called when the IRQ occurs.

  1010 * Primary handler for threaded interrupts 1011 * If NULL and thread_fn != NULL the default

  1012 * primary handler is installed 1013 * @thread_fn: Function called from the irq handler thread

  1014 * If NULL, no irq thread is created 1015 * @irqflags: Interrupt type flags

  1016 * @devname: An ascii name for the claiming device 1017 * @dev_id: A cookie passed back to the handler function

  1018 * 1019 * This call allocates interrupt resources and enables the

  1020 * interrupt line and IRQ handling. From the point this 1021 * call is made your handler function may be invoked. Since

  1022 * your handler function must clear any interrupt the board 1023 * raises, you must take care both to initialise your hardware

  1024 * and to set up the interrupt handler in the right order. 1025 *

  1026 * If you want to set up a threaded irq handler for your device 1027 * then you need to supply @handler and @thread_fn. @handler ist

  1028 * still called in hard interrupt context and has to check 1029 * whether the interrupt originates from the device. If yes it

  1030 * needs to disable the interrupt on the device and return 1031 * IRQ_WAKE_THREAD which will wake up the handler thread and run

  1032 * @thread_fn. This split handler design is necessary to support 1033 * shared interrupts.

  1034 * 1035 * Dev_id must be globally unique. Normally the address of the

  1036 * device data structure is used as the cookie. Since the handler 1037 * receives this value it makes sense to use it.

  1038 * 1039 * If your interrupt is shared you must pass a non NULL dev_id

  1040 * as this is required when freeing the interrupt. 1041 *

  1042 * Flags: 1043 *

  1044 * IRQF_SHARED Interrupt is shared 1045 * IRQF_SAMPLE_RANDOM The interrupt can be used for entropy

  1046 * IRQF_TRIGGER_* Specify active edge(s) or level 1047 *

  1048 */ [c-sharp] view plaincopy

  1049int request_threaded_irq(unsigned int irq, irq_handler_t handler, 1050 irq_handler_t thread_fn, unsigned long irqflags,

  1051 const char *devname, void *dev_id) 1052{

  1053 struct irqaction *action; 1054 struct irq_desc *desc;

  1055 int retval; 1056

  1057 /* 1058 * Sanity-check: shared interrupts must pass in a real dev-ID,

  1059 * otherwise we'll have trouble later trying to figure out 1060 * which interrupt is which (messes up the interrupt freeing

  1061 * logic etc). 1062 */

  1063 if ((irqflags & IRQF_SHARED) && !dev_id) 1064 return -EINVAL;

  1065 1066 desc = irq_to_desc(irq);

  1067 if (!desc) 1068 return -EINVAL;

  1069 1070 if (desc->status & IRQ_NOREQUEST)

  1071 return -EINVAL; 1072

  1073 if (!handler) { 1074 if (!thread_fn)

  1075 return -EINVAL; 1076 handler = irq_default_primary_handler;

  1077 } 1078

  1079 action = kzalloc(sizeof(struct irqaction), GFP_KERNEL); 1080 if (!action)

  1081 return -ENOMEM; 1082

  1083 action->handler = handler; 1084 action->thread_fn = thread_fn;

  1085 action->flags = irqflags; 1086 action->name = devname;

  1087 action->dev_id = dev_id; 1088

  1089 chip_bus_lock(irq, desc); 1090 retval = __setup_irq(irq, desc, action);

  1091 chip_bus_sync_unlock(irq, desc); 1092

  1093 if (retval) 1094 kfree(action);

  1095 1096#ifdef CONFIG_DEBUG_SHIRQ

  1097 if (!retval && (irqflags & IRQF_SHARED)) { 1098 /*

  1099 * It's a shared IRQ -- the driver ought to be prepared for it 1100 * to happen immediately, so let's make sure....

  1101 * We disable the irq to make sure that a 'real' IRQ doesn't 1102 * run in parallel with our fake.

  1103 */ 1104 unsigned long flags;

  1105 1106 disable_irq(irq);

  1107 local_irq_save(flags); 1108

  1109 handler(irq, dev_id); 1110

  1111 local_irq_restore(flags); 1112 enable_irq(irq);

  1113 } 1114#endif

  1115 return retval; 1116} [c-sharp] view plaincopy

  993void free_irq(unsigned int irq, void *dev_id) 994{

  995 struct irq_desc *desc = irq_to_desc(irq); 996

  997 if (!desc) 998 return;

  999 1000 chip_bus_lock(irq, desc);

  1001 kfree(__free_irq(irq, dev_id)); 1002 chip_bus_sync_unlock(irq, desc);

  1003}

时间: 2024-11-09 00:17:28

linux中断--内核中断编程的相关文章

Linux中断内核编程

转自:http://blog.csdn.net/tigerjb/article/details/6069516 在前面分析了中断的基本原理后,就可以写一个内核中断程序来体验以下,也可以借此程序继续深入来了解内核中断的执行过程 一.内核中断程序 : 我们还是来看一看成程序: 在看程序之前,要熟悉如何进行模块编程,和了解module_pararm()的用法.如果不熟悉的话请大家看,module_param()的学习 和Linux内核模块编程,在此不作解释. 1.程序interrupt.c [c-sh

Linux内核中断和异常分析(中)

在linux内核中,每一个能够发出中断请求的硬件设备控制器都有一条名为IRQ的输出线.所有现在存在的IRQ线都与一个名为可编程中断控制器的硬件电路的输入引脚相连,上次讲到单片机的时候,我就讲到了单片机中断的一些概念.我们现在来看一幅图,更好说明一个问题:      这下面的这幅图是51单片机的一个关于矩阵键盘的学习的一个proteus的仿真电路图. 其中P3.2和P3.3为外部中断引脚,当可编程控制器(51MCU)收到外部中断响应的时候,会执行一些特定的操作,当然这需要开发者去编写一个中断初始化

Linux 内核中断内幕【转】

转自:https://www.ibm.com/developerworks/cn/linux/l-cn-linuxkernelint/index.html 本文对中断系统进行了全面的分析与探讨,主要包括中断控制器.中断分类.中断亲和力.中断线程化与 SMP 中的中断迁徙等.首先对中断工作原理进行了简要分析,接着详细探讨了中断亲和力的实现原理,最后对中断线程化与非线程化中断之间的实现机理进行了对比分析. 3评论 苏 春艳, 在读研究生 杨 小华 (normalnotebook@126.com),

linux内核分析笔记----中断和中断处理程序【转】

转自:http://www.cnblogs.com/hanyan225/archive/2011/07/17/2108609.html 中断还是中断,我讲了很多次的中断了,今天还是要讲中断,为啥呢?因为在操作系统中,中断是必须要讲的..        那么什么叫中断呢, 中断还是打断,这样一说你就不明白了.唉,中断还真是有点像打断.我们知道linux管理所有的硬件设备,要做的第一件事先是通信.然后,我们天天在说一句话:处理器的速度跟外围硬件设备的速度往往不在一个数量级上,甚至几个数量级的差别,这

linux驱动开发--中断:按键中断

1.中断定义 中断是指cpu在执行过程中,出现了某些突发事件时cpu必须暂停执行当前的程序,转去处理突发事件,处理完毕后cpu又返回原程序被中断的位置并继续执行. 2.中断分类 3.Linux中断处理程序结构 a.在Linux系统中,中断处理程序分解为两个半部:顶半部(TopHalf)和底半部(BottomHalt). b.顶半部:完成尽可能少的比较紧急的功能,往往只是简单的读取寄存器中的中断状态并清除中断标志后就进行"登记中断"的工作,也就是将底半部处理程序挂到该设备的底半部执行队列

Linux的IRQ中断子系统分析

本文以Linux中断子系统架构为视角,旨在提供一个对Linux中断系统的全局认识,不涉及具体实现细节. 一.Linux中断子系统架构 在Linux中断子系统(generic irq)出现之前,内核使用__do_IRQ处理所有的中断,这意味着__do_IRQ中要处理各种类型的中断,这会导致软件的复杂性增加,层次不分明,而且代码的可重用性也不好.通用中断子系统的原型最初出现于ARM体系中,一开始内核的开发者们把3种中断类型区分出来(电平中断.边缘中断.简易中断),后来又针对某些需要回应eoi(end

手把手教你写Linux设备驱动---中断(一)(基于友善之臂4412开发板)

今天,我们要来实现一个基于tiny4412开发板上的最简本的按键中断驱动程序,那么,写这个程序之前,我们先来了解下Linux中断的基本知识. 在Linux内核中,每一个能够发出中断请求的硬件设备控制器都有一条名为IRQ的输出线.所有现在存在的IRQ线都与一个名为可编程中断控制器的硬件电路的输入引脚相连,我们可以来看下4412上与板子上相连的按键. 下面这张电路图,也就是4412板子上按键的电路图和CPU的连接关系图: 我们明显可以看到,4个按键分别接在GPX3这几个引脚上,对应着引脚,接下来我们

非常好!!!Linux源代码阅读——中断【转】

Linux源代码阅读--中断 转自:http://home.ustc.edu.cn/~boj/courses/linux_kernel/2_int.html 目录 为什么要有中断 中断的作用 中断的处理原则 Linux 中断机制 中断控制器 中断描述符 中断数据结构 中断的初始化 内核接口 中断处理过程 CPU 的中断处理流程 保存中断信息 处理中断 从中断中返回 编写中断处理程序 软中断.tasklet与工作队列 上半部与下半部 软中断 tasklet 工作队列 1 为什么要有中断 1.1 中

手把手教你写Linux设备驱动---中断(二)--tasklet实现(基于友善之臂4412开发板)

上节:http://blog.csdn.net/morixinguan/article/details/68958185 在上一节博文中,教会了大家如何来写一个Linux设备的中断程序,实现也非常简单,我们来回顾一下具体的操作流程,只要遵循以下几个步骤即可实现最简单的中断处理程序: 使用中断相关的API和定义时要包含以下头文件: #include <linux/interrupt.h> 然后写中断需要以下步骤 1.申请中断号 使用gpio_to_irq函数,可以从返回值获取到对应的中断号 2.