【问题标题】:Prototype Kernel and modules原型内核和模块
【发布时间】:2011-09-26 08:59:22
【问题描述】:

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

modules这个词有点含糊,正确的说法是加载库,例如C library的小型实现内核模式 驱动程序或标准的东西,例如 IRQ 0 和 1 上的 PIT键盘。我试图实现的方法有点自我维持;在我的内核将加载的模块方面,将在内核本身中用于进入用户模式

例如,我的内核使用了我自己实现的 C 库中的极少数函数。这些函数本身用于设置我的 GDT、IDT、IRQ、ISR 等。我想将这些函数抽象为内核可以加载和使用的库。这意味着内核本身将需要在第一阶段加载模块,然后再进行任何设置。

现在,我自己想到了几种方法来做到这一点,例如向这个库添加一个结构,其中包含一个函数指针表,这些函数指针分配了库本身中函数的地址。将库编译为 aout-kludge 文件,将库作为​​ void * 加载到内核中(这没关系,因为我有一个工作分配器),然后弄清楚结构的偏移量,如此多地进入 void 指针,并在内核中重新创建结构。这听起来好像行不通,因为需要分配函数指针表,这意味着库本身中需要有一个初始化函数。就算我知道地址怎么称呼?

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

【问题讨论】:

    标签: c module kernel osdev


    【解决方案1】:

    我建议您首先在用户空间中编写一个动态加载器。所需的技术非常相似,您可以稍后将大部分代码调整到内核空间。此外,不要使用 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 中的引导存根执行动态链接。稍后,同样的动态链接器也可用于加载其他驱动程序。

    【讨论】:

      【解决方案2】:

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

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

      CHAR VariableName[20];
      

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

      Symbol: Main.c
      

      例如,在符号表中,即使是 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 手册(了解链接器脚本)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-09-06
        • 1970-01-01
        • 1970-01-01
        • 2023-03-31
        • 2020-08-15
        • 2012-04-11
        • 2013-12-17
        相关资源
        最近更新 更多