原型内核和模块

时间:2011-06-30 22:25:25

标签: c module kernel osdev

最近我选择了一个旧项目并重新启动它,几乎从头开始。 我已经病了一段时间,所以我有时间严厉打击并实施大量的功能。然而,我认为实现的一个好主意是模块加载。我想做内核模式动态加载模块。

单词 modules 有点含糊不清,正确的术语只是加载库,例如 C库的miniture实现内核模式 IRQ 0&上的驱动程序或标准内容,例如 PIT 键盘 1 即可。我想要实现的方法有点自我维持;在我的内核将加载的模块方面,将在内核中使用进入用户模式

作为一个例子,我的内核使用了很少的C库函数,我自己实现了。这些函数本身用于设置我的 GDT,IDT,IRQ,ISR 等等。我想将这些函数抽象到内核可以加载和使用的库中。这意味着在设置任何内容之前,内核本身将需要在第一阶段加载模块。

现在,我已经想到了一些自己做的方法,例如使用一个函数指针表向这个库添加一个结构,这些函数指针分配了库本身中函数的地址。将库编译为 aout-kludge 文件,将库作为​​ void * 加载到内核中(由于我有一个工作分配器,这是可以的),然后搞清楚结构的偏移量,踩到void指针那么多,并重新创建内核中的结构。这听起来不像它可以工作,因为需要分配函数指针表,这意味着库本身需要一个初始化函数。即使我知道地址,怎么会被召唤?

我对如何实现这样的加载器毫无头绪,是否值得呢?我想尽可能抽象,我的内核采用模块化设计。我也希望用这种方法加载驱动程序和其他东西,我只是不确定如何实现它。我已经尝试了各种方法,但都失败了。我该怎么办?

2 个答案:

答案 0 :(得分:2)

我建议您先在用户空间中编写动态加载程序。所需的技术非常相似,您可以在以后将大部分代码调整到内核空间。另外,不要使用a.out并且不要构成自己的“函数指针表” - 使用更现代的格式,例如ELF。编译时工具已经存在,因此这将为您节省大量精力;您可以编写适当的链接描述文件并直接从Linux GCC构建。

实际上,Windows内核的功能与您所说的非常相似 - Windows内核(ntoskrnl.exe)是一个PE可执行文件,链接在各种DLL的例程中(PSHED.dll,HAL.dll,KDCOM.dll) ,我的系统上的CLFS.sys和Cl.dll)。在这种情况下,NTLDR程序将ntoskrnl.exe所需的所有文件加载到内存中,然后ntoskrnl.exe中的引导存根执行动态链接。稍后,同样的动态链接器也可用于加载其他驱动程序。

答案 1 :(得分:0)

实现内核模块并非易事。这有点复杂,您需要阅读ELF文档以进行编码。我将尽力为您提供一些见解 -

在用户空间中,可执行文件需要共享库来实现其某些功能或代码。因此,可执行文件中的代码将引用共享库中的代码。这导致了符号的发展。符号表示指向数据/函数/其他&的指针。有一个名字。

CHAR VariableName[20];

例如,在上面的代码中,将使用名称' VariableName'创建数据符号。发明之后'对于动态/共享库,必须加载符号表(二进制中的符号集)以解析库中可执行文件的引用。但是很多调试符号和符号表中存在无用的符号。

Symbol: Main.c

例如,在符号表中,即使是C源文件的符号也将出现用于调试。但这不是在运行时解析引用所必需的。在这里,动态符号的概念出现在游戏中。

动态链接是指解析二进制文件之间的引用。动态链接器将使用动态符号表(必须加载&' normal'符号表不必)来解析可执行文件在库中的引用。

现在,在作为可执行文件的内核核心中,共享库(内核模块)中没有引用。但是可执行文件中的共享库引用。因此,可执行文件必须包含用于解析内核模块中的引用的动态符号。这与用户空间中的情况相反。因此,如果您使用的是ld,

-pie -T LinkerScript.ld

选项应该用于在内核可执行文件中创建动态符号表。

你应该创建一个LinkerScript.ld文件 -

/* File: LinkerScript.ld */
PHDRS {
  kernel PT_LOAD FILEHDR;/* This declares a segment in which your code/data is.*/
  dynamic PT_DYNAMIC;/* Segment containing the dynamic table (not DST). */
}

SECTIONS {
    /* text, data, bss sections must be implemented already */
    .dynamic ALIGN(0x1000) : AT(ADDR(.dynamic) - KERNEL_OFFSET)
    { 
       *(.dynamic) 
    } :dynamic/* add :kernel to text, data, bss*/
}

具有上述结构。确保你的.text,.data& .bss部分已经存在& :内核被添加到节描述符的末尾。

有关更多信息,请阅读ELF文档& LD手册(用于链接器脚本洞察)。