注意:我在 FreeBSD 上运行,但我也将 Linux 作为标签包含在内,因为这个问题有些笼统,而且我对 Linux 特定的解决方案很感兴趣。
编辑:只是为了确认问题不是 FreeBSD 特有的,我将该模块移植到 Linux,并且确实得到了完全相同的行为。该模块的 Linux 版本代码如下;它本质上是完全一样的,唯一的主要区别是 IDT 在 Linux 中显然被赋予了只读保护,所以我必须禁用写保护位cr0才能使代码工作。
我正在学习一些有关 x86-64 架构上内核开发的知识,目前正在阅读英特尔开发人员手册中有关中断处理的内容。作为练习,我正在尝试编写一个小内核模块来挂钩 IDT 中的条目,但遇到了问题。我的一般问题是:你如何确保你的钩子的代码(或者你的新 IDT 表的数据,如果你lidt用来改变整个idtrIDT 而不只是覆盖 IDT 的单个条目)总是存在于 RAM 中?我一直遇到的问题是,我将更改 IDT 条目,触发相应的中断,然后由于我的钩子代码未映射到 RAM 中而导致双重错误。一般来说,有没有办法避免这个问题?
对于我的具体情况,以下是我编写的 FreeBSD LKM 的代码,它简单地覆盖 IDT 条目中列出的地址以处理零除数错误,并将其替换为 的地址asm_hook,目前该地址只是无条件jmp返回原始中断处理程序。(将来我当然会添加更多功能。)
#include <sys/types.h>
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/module.h>
#include <sys/sysent.h>
#include <sys/kernel.h>
#include <sys/syscall.h>
#include <sys/sysproto.h>
#include <sys/systm.h>
//idt entry
struct idte_t {
unsigned short offset_0_15;
unsigned short segment_selector; …Run Code Online (Sandbox Code Playgroud)