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 mus