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}

(0)

相关推荐

  • Linux下的多线程编程和fork()函数详解

     一.fork()函数 在操作系统的基本概念中进程是程序的一次执行,且是拥有资源的最小单位和调度单位(在引入线程的操作系统中,线程是最小的调度单位).在Linux系统中 创建进程有两种方式:一是由操作 ...

  • Linux编译内核

    Linux编译内核 - 准备工作 通常要运行的第一个命令是: #cd /usr/src/linux;make mrproper 该命令确保源代码目录下没有不正确的.o文件以及文件的互相依赖 配置 ?? ...

  • 详解Debian系统中安装Linux新内核的流程

    一直对Linux内核很有兴趣,但苦于入门不易,认真看了ldd前5章突然就来感觉了,光看不练不顶用,首先就需要环境搭建.使用的是Debian 5.0,内核2.6.26,欲安装的新内核为2.6.28,这里 ...

  • linux中断--中断嵌套&中断请求丢失

    关于中断嵌套: 在linux内核里,如果驱动在申请注册中断的时候没有特别的指定,do_irq在做中断响应的时候,是开启中断的,如果在驱动的中断处理函数正在执行的过程中,出现同一设备的中断或者不同设备的 ...

  • linux中断--中断嵌套&中断请求丢失

    关于中断嵌套: 在linux内核里,如果驱动在申请注册中断的时候没有特别的指定,do_irq在做中断响应的时候,是开启中断的,如果在驱动的中断处理函数正在执行的过程中,出现同一设备的中断或者不同设备的 ...

  • 在西门子PLC编程中使用中断应该注意的问题

    操作方法 01 西门子PLC编程中使用中断应该注意的问题,下面我就开门见山的说了 1.中断程序中可以调用子程序 累加器和逻辑堆栈式的存蓄器在中断程序和被调用的子程序中都是共用的 2.中断程序和主程序下 ...

  • linux内核驱动-内核初涉

    一、为什么要学习内核? 有些人要学习内核,而有些人则可以不学习它。你如果以后要从事系统研发或驱动开发的话,就要学习内核。 刚刚接触内核,主要学习内核的接口函数。不要深入的去读内核,因为你读也读不懂,内 ...

  • Linux内核的文件预读详解

    Linux文件预读算法磁盘I/O性能的发展远远滞后于CPU和内存,因而成为现代计算机系统的一个主要瓶颈。预读可以有效的减少磁盘的寻道次数和应用程序的I/O等待时间,是改进磁盘读I/O性能的重要优化手段 ...

  • LINUX和WINDOWS的内核区别

    原文链接:        https://www.cnblogs.com/xiaolincoding/p/14419269.html作者:小林codingWindows 和 Linux 可以说是我们比 ...