C 原型内核和模块

C 原型内核和模块,c,module,kernel,osdev,C,Module,Kernel,Osdev,最近,我拿起一个旧项目,重新启动它,几乎是从头开始。 我已经病了一段时间了,所以我有时间来严厉打击并实现大量的功能。然而,我觉得实现模块加载是一个好主意。我想在内核模式下动态加载模块 模块这个词有点模棱两可,正确的术语应该是加载库,例如内核模式驱动程序的C库的小型实现,或者PIT和键盘等标准的东西,它们都在IRQ 0&1上。我试图实现的方法有点自我维持;在内核将加载的模块方面,将在内核本身中使用,以进入用户模式 作为一个例子,我的内核使用了C库中很少的函数,这是我自己实现的。这些函数本身用于设置

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

模块这个词有点模棱两可,正确的术语应该是加载库,例如内核模式驱动程序的C库的小型实现,或者PIT键盘等标准的东西,它们都在IRQ 0&1上。我试图实现的方法有点自我维持;在内核将加载的模块方面,将在内核本身中使用,以进入用户模式

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

现在,我自己也想到了一些方法,比如在这个库中添加一个结构,其中包含一个函数指针表,这些指针被分配给库中函数的地址。将库编译为一个aout kludge文件,将库作为void*加载到内核中(这是可以的,因为我有一个工作的分配器),然后计算出结构的偏移量,将void指针移到那么多,然后在内核中重新创建结构。这听起来好像不可行,因为需要分配函数指针表,这意味着库本身需要有一个初始化函数。即使我知道地址,那怎么称呼呢


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

我建议您首先在用户空间中编写一个动态加载程序。所需的技术非常相似,您可以在以后将大部分代码调整到内核空间。此外,不要使用.out,也不要自行编制“函数指针表”——使用更现代的格式,如。编译时工具已经存在,因此这将为您节省大量工作;您只需编写一个适当的链接器脚本并直接从LinuxGCC构建即可


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

实现内核模块不是一件小事。这有点复杂,您需要阅读ELF文档进行编码。在这里,我将尝试为您提供一些见解-

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

CHAR VariableName[20];
例如,在上述代码中,将创建一个名为“VariableName”的数据符号。在“发明”动态/共享库之后,必须加载符号表(二进制符号集),以解析库中可执行文件的引用。但符号表中存在大量调试符号和无用符号

Symbol: Main.c
例如,在symbol表中,即使是C源文件的符号也会出现以进行调试。但在运行时解析引用并不需要这样做。在这里,动态符号的概念出现在游戏中

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

现在,在作为可执行文件的内核内核中,共享库(内核模块)中没有引用。但是共享库在可执行文件中引用。因此,可执行文件必须包含用于解析内核模块中引用的动态符号。这与用户空间中的情况相反。因此,如果您使用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节已经存在&:kernel已添加到节描述符的末尾

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