gpt4 book ai didi

c - Linux内核有main函数吗?

转载 作者:IT王子 更新时间:2023-10-29 00:25:13 28 4
gpt4 key购买 nike

我正在学习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);

这里我有两个问题:

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

最佳答案

启动内核

关于 4.2,start_kernel from init/main.c是一个相当大的初始化过程,可以与 main 函数进行比较。

它是第一个运行的 arch 独立代码,并设置了内核的很大一部分。与 main 非常相似,start_kernel 之前是一些较低级别的设置代码(在用户空间 main crt* 对象中完成)),之后运行“主要”通用 C 代码。

如何在 x86_64 中调用 start_kernel

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

ENTRY(phys_startup_64)

phys_startup_64 = startup_64 - LOAD_OFFSET;

和:

#define LOAD_OFFSET __START_KERNEL_map

arch/x86/include/asm/page_64_types.h__START_KERNEL_map 定义为:

#define __START_KERNEL_map  _AC(0xffffffff80000000, UL)

这是内核入口地址。 TODO 该地址是如何准确到达的?我必须了解 Linux 向引导加载程序公开的接口(interface)。

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

.text :  AT(ADDR(.text) - LOAD_OFFSET) {
_text = .;
/* bootstrapping code */
HEAD_TEXT

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

#define HEAD_TEXT  *(.head.text)

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

那是第一个运行的东西,因为文件以:

.text
__HEAD
.code64
.globl startup_64

include/linux/init.h__HEAD定义为:

#define __HEAD      .section    ".head.text","ax"

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

最后它调用 x86_64_start_kernellretq 有点笨拙:

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

和:

.balign 8
GLOBAL(initial_code)
.quad x86_64_start_kernel

arch/x86/kernel/head64.c 定义 x86_64_start_kernel 调用 x86_64_start_reservations 调用 start_kernel

arm64 入口点

在 v5.7 未压缩内核上运行的第一个 arm64 定义在 https://github.com/cirosantilli/linux/blob/v5.7/arch/arm64/kernel/head.S#L72所以 add x13, x18, #0x16b stext 取决于 CONFIG_EFI:

    __HEAD
_head:
/*
* DO NOT MODIFY. Image header expected by Linux boot-loaders.
*/
#ifdef CONFIG_EFI
/*
* This add instruction has no meaningful effect except that
* its opcode forms the magic "MZ" signature required by UEFI.
*/
add x13, x18, #0x16
b stext
#else
b stext // branch to kernel start, magic
.long 0 // reserved
#endif
le64sym _kernel_offset_le // Image load offset from start of RAM, little-endian
le64sym _kernel_size_le // Effective size of kernel image, little-endian
le64sym _kernel_flags_le // Informative flags, little-endian
.quad 0 // reserved
.quad 0 // reserved
.quad 0 // reserved
.ascii ARM64_IMAGE_MAGIC // Magic number
#ifdef CONFIG_EFI
.long pe_header - _head // Offset to the PE header.

这也是未压缩内核镜像的第一个字节。

这两种情况都跳转到 stext 开始“真正的” Action 。

如评论中所述,这两条指令是记录在案的 header 的前 64 个字节,描述于:https://github.com/cirosantilli/linux/blob/v5.7/Documentation/arm64/booting.rst#4-call-the-kernel-image

arm64 第一个启用 MMU 的指令:__primary_switched

我认为是__primary_switched in head.S :

/*
* The following fragment of code is executed with the MMU enabled.
*
* x0 = __PHYS_OFFSET
*/
__primary_switched:

此时,内核似乎正在创建页表 + 可能会重新定位自身,以便 PC 地址与 vmlinux ELF 文件的符号相匹配。因此,此时您应该能够在 GDB 中看到有意义的函数名称,而无需额外的魔法。

arm64 辅助 CPU 入口点

secondary_holding_pen 定义于:https://github.com/cirosantilli/linux/blob/v5.7/arch/arm64/kernel/head.S#L691

进入程序进一步描述:https://github.com/cirosantilli/linux/blob/v5.7/arch/arm64/kernel/head.S#L691

关于c - Linux内核有main函数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18266063/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com