在 ARM Linux 内核中,小任务分为高优先级的小任务和低优先级的小任务,它们是基于软中断 实现的。本次实验需要完成如下任务: 1. 编写内核模块,对 31 号中断注册一个中断处理函数,打印出其调用的次数。 2. 把加载、卸载内核模块以 install/uninstall 写入 Makefile 文件中。
时间: 2023-06-10 20:07:46 浏览: 178
linux内核知识系列:软中断
好的,下面是具体的步骤:
1. 编写中断处理函数
在内核模块中,我们需要注册一个中断处理函数来处理 31 号中断。首先在代码中包含头文件 `linux/interrupt.h`,然后定义中断处理函数如下:
```
static irqreturn_t my_isr(int irq, void *dev_id)
{
static int count = 0;
printk(KERN_INFO "Interrupt called %d times\n", ++count);
return IRQ_HANDLED;
}
```
这个中断处理函数会在每次中断发生时被调用。它会打印一条信息,说明中断已经被调用了多少次。注意,我们在中断处理函数中使用了 `printk` 函数来输出信息,而不是使用普通的 `printf` 函数。这是因为在内核模块中,我们不能使用标准 C 库函数,而必须使用内核提供的函数。
2. 注册中断处理函数
在 `init_module` 函数中,我们需要注册我们的中断处理函数。具体来说,我们需要调用 `request_irq` 函数,它接受三个参数:中断号、中断处理函数的指针、以及中断标志。我们可以像下面这样注册 31 号中断:
```
int irq = 31;
int flags = IRQF_SHARED | IRQF_TRIGGER_RISING;
if (request_irq(irq, my_isr, flags, "my_module", &my_isr)) {
printk(KERN_ERR "Failed to register IRQ %d\n", irq);
return -EBUSY;
}
```
这里的 `flags` 参数指定了中断的标志,我们使用了 `IRQF_SHARED` 和 `IRQF_TRIGGER_RISING` 标志。`IRQF_SHARED` 表示多个设备可以共享这个中断,而 `IRQF_TRIGGER_RISING` 表示中断信号是上升沿触发的。
注意,我们在注册中断处理函数时,将 `my_isr` 传递给了 `dev_id` 参数。这个参数可以用于标识中断处理函数的上下文,我们将中断处理函数自身的指针传递进去,以便在以后卸载模块时可以正确地释放中断。
3. 卸载中断处理函数
在 `cleanup_module` 函数中,我们需要卸载中断处理函数。具体来说,我们需要调用 `free_irq` 函数来释放中断。我们可以像下面这样卸载 31 号中断:
```
free_irq(31, &my_isr);
```
这里的第一个参数是中断号,第二个参数是我们在注册中断处理函数时传递的 `dev_id` 参数。
4. 编写 Makefile
最后,我们需要编写一个 Makefile 文件来编译和加载内核模块。下面是一个简单的 Makefile 文件:
```
obj-m := my_module.o
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
install:
insmod my_module.ko
uninstall:
rmmod my_module.ko
clean:
$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
```
这个 Makefile 文件定义了一个名为 `my_module` 的内核模块,并包含了编译、加载和卸载模块的规则。在编译模块时,我们需要指定内核源代码的路径,这里使用了一个变量 `KERNELDIR` 来表示。
5. 编译和加载模块
现在我们可以编译和加载模块了。首先运行 `make` 命令来编译模块,然后使用 `insmod` 命令来加载模块:
```
$ make
$ sudo insmod my_module.ko
```
模块加载后,我们可以使用 `dmesg` 命令来查看模块的输出:
```
$ dmesg | tail
```
每次中断发生时,我们都应该能够看到一个类似于下面的消息:
```
Interrupt called X times
```
6. 卸载模块
当我们不再需要模块时,可以使用 `rmmod` 命令来卸载它:
```
$ sudo rmmod my_module
```
这将释放中断,并从内核中卸载模块。
阅读全文