内核模块编程之入门(三)-模块实用程序简介
在此,我们将编写一个模块,其中有一个中断函数,当内核接收到某个 IRQ 上的一个中断时会调用它。先给出全部代码,读者自己调试,把对该程序的理解跟到本贴后面。
—————————————-
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
static int irq;
static char *interface;
//MODULE_PARM_DESC(interface,”A network interface”); 2.4内核中该宏的用法
molule_parm(interface,charp,0644) //2.6内核中的宏
//MODULE_PARM_DESC(irq,”The IRQ of the network interface”);
module_param(irq,int,0644);
static irqreturn_t myinterrupt(int irq, void *dev_id, struct pt_regs *regs)
{
static int mycount = 0;
if (mycount < 10) {
printk(“Interrupt!\n”);
mycount++;
}
return IRQ_NONE;
}
static int __init myirqtest_init(void)
{
printk (“My module worked!11111\n”);
if (request_irq(irq, &myinterrupt, SA_SHIRQ,interface, &irq)) {
printk(KERN_ERR “myirqtest: cannot register IRQ %d\n”, irq);
return -EIO;
}
printk(“%s Request on IRQ %d succeeded\n”,interface,irq);
return 0;
}
static void __exit myirqtest_exit(void)
{
printk (“Unloading my module.\n”);
free_irq(irq, &irq);
printk(“Freeing IRQ %d\n”, irq);
return;
}
module_init(myirqtest_init);
module_exit(myirqtest_exit);
MODULE_LICENSE(“GPL”);
—————————————-
这里要说明的是,在插入模块时,可以带两个参数,例如
insmod myirq.ko interface=eth0 irq=9
其中 具体网卡 irq的值可以查看 cat /proc/interrupts
动手吧!以此为例,可以设计出各种各样有价值的内核模块,贴出来体验分享的快乐吧。
在上一部分“编写带有参数的中断模块”中,这个看似简单的程序,你调试并运行以后思考了哪些方面的问题?CPU0
0: 10655925 IO-APIC-edge timer
1: 9148 IO-APIC-edge i8042
6: 4 I O-APIC-edge floppy
7: 0 IO-APIC-edge parport0
8: 3 IO-APIC-edge rtc
9: 0 IO-APIC-fasteoi acpi
12: 41970 IO-APIC-edge i8042
15: 106157 IO-APIC-edge ide1
16: 57823 IO-APIC-fasteoi ioc0
17: 8090 IO-APIC-fasteoi eth0
18: 245 IO-APIC-fasteoi uhci_hcd:usb1, Ensoniq AudioPCI, usb
NMI: 0
LOC: 10249542
ERR: 0
MIS: 0然后,在插入模块时,你对每个中断都作为参数试运行一下,看看会出现什么问题?思考一下irq为0,3等值时,为什么插入失败?这就引出中断的共享和非共享问题,从而促使你分析Linux对共享的中断到底如何处理,共享同一个中断号的中断处理程序到底如何执行?
(1)给模块传递参数,使得这个模块的扩展和应用有了空间,例如,在我的机器上查看/proc/interrupts
2. 对于myinterrupt()函数,可以进行怎样的改进,使得这个自定义的中断处理程序变得有实际意义?
static irqreturn_t myinterrupt(int irq, void *dev_id, struct pt_regs *regs)
{
static int mycount = 0;
if (mycount < 10) {
printk(“Interrupt!\n”);
mycount++;
}
return IRQ_NONE;
}
比如,对于网卡中断,在此收集每一次中断发生时,从网卡接收到的数据,把其存入到文件中。以此思路,随你考虑应用场景了。