内核有主要功能吗?

som*_*one 14 c linux linux-device-driver linux-kernel

我正在学习Device DriverKernel编程.根据Jonathan Corbet的书,我们main()在设备驱动程序中没有功能.

#include <linux/init.h>
#include <linux/module.h>

static int my_init(void)
{
     return  0;
}

static void my_exit(void)
{
     return;
}

module_init(my_init);
module_exit(my_exit);
Run Code Online (Sandbox Code Playgroud)

我有两个问题:

  1. 为什么我们不需要main()设备驱动程序中的功能?
  2. 内核有main()功能吗?

Jac*_*man 11

从根本上说,命名的例程并没有什么特别之处main().如上所述,main()充当可执行加载模块的入口点.但是,您可以为加载模块定义不同的入口点.实际上,您可以定义多个入口点,例如,参考您喜欢的dll.

从操作系统(OS)的角度来看,它真正需要的只是代码的入口点的地址,它将作为设备驱动程序.当需要设备驱动程序对设备执行I/O时,OS会将控制权传递给该入口点.

系统程序员定义(每个OS都有自己的方法)设备,作为设备驱动程序的加载模块和加载模块中入口点的名称之间的连接.

每个操作系统都有自己的内核(显然),有些可能/可能从一开始,main()但我会惊讶地发现一个内核使用的main()只是一个简单的内核,比如UNIX!当您编写内核代码时,您已经超越了将您编写的每个模块命名为的要求main().

希望这可以帮助?

从Unix版本6的内核中找到此代码片段.正如您所看到main()的只是另一个程序,试图开始!

main()
{
     extern schar;
     register i, *p;
     /*
     * zero and free all of core
     */

     updlock = 0;
     i = *ka6 + USIZE;
     UISD->r[0] = 077406;
     for(;;) {
        if(fuibyte(0) < 0) break;
        clearsig(i);
        maxmem++;
        mfree(coremap, 1, i);
         i++;
     }
     if(cputype == 70) 
     for(i=0; i<62; i=+2) {
       UBMAP->r[i] = i<<12;
       UBMAP->r[i+1] = 0;
      }

    // etc. etc. etc.
Run Code Online (Sandbox Code Playgroud)

  • @Krishna,好吧,我可以吃掉我的话!在Unix版本6上找到了一本书,其中列出了Unix的源代码("狮子"一书),并列出了一个名为`main()`的模块,用于初始化Unix控制块.但是,就像我说的命名一个模块`main()`并没有给它任何特殊的状态. (3认同)

Cir*_*四事件 5

start_kernel

在4.2上,start_kernelfrominit/main.c是一个相当大的初始化过程,可以与main函数进行比较。

它是第一个运行的独立于Arch的代码,它建立了内核的很大一部分。就像一样mainstart_kernel在其之前加上一些较低级别的设置代码(crt*在userland 中的对象中完成main),然后运行“主要”通用C代码。

如何start_kernel在x86_64中调用

arch/x86/kernel/vmlinux.lds.S,一个链接描述文件,设置:

ENTRY(phys_startup_64)
Run Code Online (Sandbox Code Playgroud)

phys_startup_64 = startup_64 - LOAD_OFFSET;
Run Code Online (Sandbox Code Playgroud)

和:

#define LOAD_OFFSET __START_KERNEL_map
Run Code Online (Sandbox Code Playgroud)

arch/x86/include/asm/page_64_types.h定义__START_KERNEL_map为:

#define __START_KERNEL_map  _AC(0xffffffff80000000, UL)
Run Code Online (Sandbox Code Playgroud)

这是内核入口地址。TODO该地址如何到达?我必须了解Linux暴露给引导加载程序的接口。

arch/x86/kernel/vmlinux.lds.S 将第一个引导程序部分设置为:

.text :  AT(ADDR(.text) - LOAD_OFFSET) {
    _text = .;
    /* bootstrapping code */
    HEAD_TEXT
Run Code Online (Sandbox Code Playgroud)

include/asm-generic/vmlinux.lds.h定义HEAD_TEXT

#define HEAD_TEXT  *(.head.text)
Run Code Online (Sandbox Code Playgroud)

arch/x86/kernel/head_64.S定义startup_64。那是运行的第一个x86内核代码。它执行许多低级设置,包括分段和分页。

那就是运行的第一件事,因为文件开头是:

.text
__HEAD
.code64
.globl startup_64
Run Code Online (Sandbox Code Playgroud)

include/linux/init.h定义__HEAD为:

#define __HEAD      .section    ".head.text","ax"
Run Code Online (Sandbox Code Playgroud)

因此与链接描述文件的第一件事相同。

最后,它x86_64_start_kernel使用和尴尬地调用lretq

movq    initial_code(%rip),%rax
pushq   $0      # fake return address to stop unwinder
pushq   $__KERNEL_CS    # set correct cs
pushq   %rax        # target address in negative space
lretq
Run Code Online (Sandbox Code Playgroud)

和:

.balign 8
GLOBAL(initial_code)
.quad   x86_64_start_kernel
Run Code Online (Sandbox Code Playgroud)

arch/x86/kernel/head64.c定义x86_64_start_kernel该呼叫x86_64_start_reservations哪个电话start_kernel