kernel.lds 链接脚本

解析 kernel.lds 链接脚本

kernel.lds 是一个 链接脚本(Linker Script),用于告诉链接器(GNU ld)如何组织内核的内存布局,定义 各个代码段、数据段的地址及排列方式


1. 链接脚本的作用

  • 控制内核加载地址
  • 定义内核的段布局(.text.data.bss
  • 对齐段地址
  • 特殊段的存放(如 first_task 进程)
  • 提供符号(PROVIDE())给 C 代码使用

2. 关键解析

(1) 设置 kernel_base

PROVIDE(kernel_base = 0x0);
  • PROVIDE(symbol = value); 用于定义一个全局符号,供 C 代码使用。
  • kernel_base = 0x0 表示 内核的基地址,即内核被加载到物理内存的 0x0 地址处(可能用于 Bootloader 处理)。

(2) 设置 .text(代码段)

. = 0x00010000;

PROVIDE(s_text = .);
.text : {
    *(EXCLUDE_FILE(*first_task* *lib_syscall*) .text)
}
PROVIDE(e_text = .);
  • .= 0x00010000:设置链接地址,内核从 0x10000(64KB)开始加载
  • s_text / e_text:提供 text 段的起始和结束地址
  • .text
    • 存放 内核代码,排除 first_tasklib_syscall 相关的 .text 代码。

(3) .rodata(只读数据段)

.rodata : {
    *(EXCLUDE_FILE(*first_task* *lib_syscall*) .rodata)
}
  • 存放 只读数据(如字符串常量、全局 const 变量)
  • 依然排除了 first_tasklib_syscall 相关的数据

(4) .data & .bss(数据段 & 未初始化数据段)

. = ALIGN(4096);
PROVIDE(s_data = .);
.data : {
    *(EXCLUDE_FILE(*first_task* *lib_syscall*) .data)
}
.bss : {
    *(EXCLUDE_FILE(*first_task* *lib_syscall*) .bss)
}
e_data = .;
  • 对齐到 4KBALIGN(4096),保证 .data 页对齐,方便页表管理。
  • .data:存放已初始化的全局变量。
  • .bss:存放未初始化的全局变量,初始化为 0

(5) first_task(初始进程)

. = 0x80000000;

PROVIDE(s_first_task = LOADADDR(.first_task));
.first_task : AT(e_data) {
    *first_task_entry*(.text .data .rodata .data)
    *first_task*(.text .data .rodata .data)
    *lib_syscall*(.text .data .bss)
}
PROVIDE(e_first_task = LOADADDR(.first_task) + SIZEOF(.first_task));
  • . = 0x80000000;first_task 进程在高地址 0x80000000 运行
  • AT(e_data):表示 first_task 在低端 e_data 处存储,但运行时会搬运到 0x80000000
  • LOADADDR(.first_task):获取 first_task 在文件中的加载地址。
  • SIZEOF(.first_task):获取 first_task 占用的大小。
📌 first_task 作用
  • 操作系统启动时的第一个用户态进程,可能是 init 进程。
  • 存放在低地址 e_data,运行时会搬运到高地址 0x80000000

(6) 计算空闲内存的起始地址

PROVIDE(mem_free_start = e_first_task);
  • mem_free_start 指示可用内存的起始地址,即 first_task 之后的内存可用于动态分配。

3. 这份 kernel.lds 的整体布局

地址内容
kernel_base0x0提供 kernel_base 符号
.text0x00010000内核代码
.rodata代码段后只读数据(字符串、常量)
.data4KB 对齐已初始化的全局变量
.bss.data 之后未初始化的全局变量
e_data结束地址记录 .data.bss 结束地址
.first_task加载在 e_data 但运行时搬运到 0x80000000第一个用户态进程
mem_free_starte_first_task可用内存的起始地址

4. 结论

  • 这个 kernel.lds 用于内核的内存布局,管理 代码段、数据段、进程加载
  • first_task 初始进程先存放在低端内存,运行时移动到高端 0x80000000
  • mem_free_start 标记内核使用的内存结束处,以便操作系统后续进行内存管理

🚀 这份 kernel.lds 主要控制
内核加载地址0x10000 开始)。
内核各段(.text.data.bss)的内存布局
初始用户进程 first_task 的存放和运行地址
空闲内存的计算,供后续内存管理使用

📌 这是一份用于 内核启动 的链接脚本,确保内核和第一个进程能正确加载和运行! 🎯

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值