最近在网上看到一位网友写得一篇文章,写得很好,加深了对Linux启动的认识,特意贴在这里:

内核编译链接过程是依靠vmlinux.lds文件,以arm为例vmlinux.lds文件位于kernel/arch/arm

/vmlinux.lds,但是该文件是由vmlinux-armv.lds.in生成的,根据编译选项的不同源文件还可以是vmlinux-

armo.lds.in,vmlinux-armv-xip.lds.in。

vmlinux-armv.lds的生成过程在kernel/arch/arm/Makefile中

LDSCRIPT = arch/arm/vmlinux-armv.lds.in

arch/arm/vmlinux.lds: arch/arm/Makefile $(LDSCRIPT) \

$(wildcard include/config/cpu/32.h) \

$(wildcard include/config/cpu/26.h) \

$(wildcard include/config/arch/*.h)

@echo ' Generating

[email=$@%27]$@'[/email]

@sed 's/TEXTADDR/$(TEXTADDR)/;s/DATAADDR/$(DATAADDR)/' $(LDSCRIPT) >$@

vmlinux-armv.lds.in文件的内容:

OUTPUT_ARCH(arm)

ENTRY(stext)

SECTIONS

{

. = TEXTADDR;

.init : { /* Init code and data */

_stext = .;

__init_begin = .;

*(.text.init)

__proc_info_begin = .;

*(.proc.info)

__proc_info_end = .;

__arch_info_begin = .;

*(.arch.info)

__arch_info_end = .;

__tagtable_begin = .;

*(.taglist)

__tagtable_end = .;

*(.data.init)

. = ALIGN(16);

__setup_start = .;

*(.setup.init)

__setup_end = .;

__initcall_start = .;

*(.initcall.init)

__initcall_end = .;

. = ALIGN(4096);

__init_end = .;

}

其中TEXTADDR就是内核启动的虚拟地址,定义在kernel/arch/arm/Makefile中:

ifeq ($(CONFIG_CPU_32),y)

PROCESSOR = armv

TEXTADDR = 0xC0008000

LDSCRIPT = arch/arm/vmlinux-armv.lds.in

endif

需要注意的是这里是虚拟地址而不是物理地址。

一般情况下都在生成vmlinux后,再对内核进行压缩成为zImage,压缩的目录是kernel/arch/arm/boot。

下载到flash中的是压缩后的zImage文件,zImage是由压缩后的vmlinux和解压缩程序组成,如下图所示:

|-----------------|\ |-----------------|

| | \ | |

| | \ | decompress code |

| vmlinux | \ |-----------------| zImage

| | \| |

| | | |

| | | |

| | | |

| | /|-----------------|

| | /

| | /

| | /

|-----------------|/

zImage链接脚本也叫做vmlinux.lds,位于kernel/arch/arm/boot/compressed。

是由同一目录下的vmlinux.lds.in文件生成的,内容如下:

OUTPUT_ARCH(arm)

ENTRY(_start)

SECTIONS

{

. = LOAD_ADDR;

_load_addr = .;

. = TEXT_START;

_text = .;

.text : {

_start = .;

其中LOAD_ADDR就是zImage中解压缩代码的ram偏移地址,TEXT_START是内核ram启动的偏移地址,这个地址是物理地址。

在kernel/arch/arm/boot/Makefile文件中定义了:

ZTEXTADDR =0

ZRELADDR = 0xa0008000

ZTEXTADDR就是解压缩代码的ram偏移地址,ZRELADDR是内核ram启动的偏移地址,这里看到指定ZTEXTADDR的地址为0,

明显是不正确的,因为我的平台上的ram起始地址是0xa0000000,在Makefile文件中看到了对该地址设置的几行注释:

# We now have a PIC decompressor implementation. Decompressors running

# from RAM should not define ZTEXTADDR. Decompressors running directly

# from ROM or Flash must define ZTEXTADDR (preferably via the config)

他的意识是如果是在ram中进行解压缩时,不用指定它在ram中的运行地址,如果是在flash中就必须指定他的地址。所以这里将ZTEXTADDR指定为0,也就是没有真正指定地址。

在kernel/arch/arm/boot/compressed/Makefile文件有一行脚本:

SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/LOAD_ADDR/$(ZRELADDR)/;s/BSS_START/$(ZBSSADDR)/

使得TEXT_START = ZTEXTADDR,LOAD_ADDR = ZRELADDR。

这样vmlinux.lds的生成过程如下:

vmlinux.lds: vmlinux.lds.in Makefile $(TOPDIR)/arch/$(ARCH)/boot/Makefile $(TOPDIR)/.config

@sed "$(SEDFLAGS)" $@

以上就是我对内核启动地址的分析,总结一下内核启动地址的设置:

1、设置kernel/arch/arm/Makefile文件中的

TEXTADDR = 0xC0008000

内核启动的虚拟地址

2、设置kernel/arch/arm/boot/Makefile文件中的

ZRELADDR = 0xa0008000

内核启动的物理地址

如果需要从flash中启动还需要设置

ZTEXTADDR地址。

arm linux 内核启动,Linux(ARM)内核启动地址相关推荐

  1. ARM linux内核启动时几个关键地址【转】

    转自:http://www.cnblogs.com/armlinux/archive/2011/11/06/2396787.html 1.       内核启动地址 1.1.   名词解释 ZTEXT ...

  2. linux指定内核位置,ARM linux内核启动时几个关键地址

    1.       内核启动地址 ZTEXTADDR 解压代码运行的开始地址.没有物理地址和虚拟地址之分,因为此时MMU处于关闭状态.这个地址不一定时RAM的地址,可以是支持读写寻址的flash等存储中 ...

  3. 【内核】linux内核启动流程详细分析【转】

    转自:http://www.cnblogs.com/lcw/p/3337937.html Linux内核启动流程 arch/arm/kernel/head-armv.S 该文件是内核最先执行的一个文件 ...

  4. Linux内核移植之四:内核启动过程

    内容来自 韦东山<嵌入式Linux应用开发完全手册> 与移植U-Boot的过程相似,在移植Linux之前,先了解它的启动过程.Linux的启动过程可以分为两部分:架构/开发板相关的引导过程 ...

  5. Linux内核源码分析--内核启动之(2)Image内核启动(汇编部分)(Linux-3.0 ARMv7) 【转】...

    转自:http://blog.chinaunix.net/uid-25909619-id-4938389.html 在完成了zImage自解压之后,就跳转到了解压后的内核(也就是vmlinux的bin ...

  6. 【内核】linux内核启动流程详细分析

    Linux内核启动流程 arch/arm/kernel/head-armv.S 该文件是内核最先执行的一个文件,包括内核入口ENTRY(stext)到start_kernel间的初始化代码, 主要作用 ...

  7. Linux内核源码分析--内核启动之(4)Image内核启动(setup_arch函数)(Linux-3.0 ARMv7)【转】...

    原文地址:Linux内核源码分析--内核启动之(4)Image内核启动(setup_arch函数)(Linux-3.0 ARMv7) 作者:tekkamanninja 转自:http://blog.c ...

  8. linux运行欧陆风云,Arm linux启动分析(1)

    下周准备做linux启动的技术讲座,在这里我慢慢整理下自己的材料,这次我写的是Image的启动过程,也即使zImage解压缩结束后的启动代码,这时候的代码开始地址仍然是0x30008000,下面我结合 ...

  9. arm-linux启动,linux启动流程arm

    linux启动分析(1)---bootloader启动内核过程 void (*startkernel)(int zero, int arch, unsigned int params_addr) = ...

最新文章

  1. iOS 二进制流转化-项目笔记
  2. [cocos2d-x]图层的旋转缩放效果
  3. 产品 电信nb接口调用_电信NB-IoT云平台数据对接方案——唐山平升电子技术开发有限公司...
  4. 《剑指offer》二叉树的深度
  5. iphone投屏_iPhone投屏电视机/投影仪用这个方法很简单,媲美华为PC模式
  6. 你的公司内卷化了吗?
  7. NIPS’20 Spotlight | 精准建模用户兴趣,广告CTR预估准确率大幅提升!
  8. 牛客21312 神秘餐馆
  9. 杭电1713相遇周期
  10. 思科CCNA考试命令集总结
  11. 网络安全工程师面试题汇总
  12. 必读开发规范之阿里巴巴开发手册(个人整理版)
  13. 数据库中的SCHEMA到底是什么?MySQL
  14. python异常处理时所使用的保留字_【2020年12月计算机二级Python语言考试冲刺题(二)】- 环球网校...
  15. python时间序列分解STL
  16. Linux基线检查( 一)
  17. mysql主从复制-介绍
  18. 压力传感器与数据采集
  19. 扫地机器人充电插座布置_扫地机器人插座离地面多高合适 扫地机器人好不好用...
  20. Vue项目二:设置标题搜索栏,以及图片的轮播。

热门文章

  1. hdu4825 字典树 + 贪心
  2. 【Linux 内核 内存管理】Linux 内核堆内存管理 ① ( 堆内存管理 | 内存描述符 mm_struct 结构体 | mm_struct 结构体中的 start_brk、brk 成员 )
  3. 【Linux 内核 内存管理】Linux 内核内存布局 ② ( x86_64 架构体系内存分布 | 查看 /proc/meminfo 文件 | /proc/meminfo 重要字段解析 )
  4. 【Linux 内核 内存管理】优化内存屏障 ④ ( 处理器内存屏障 | 八种处理器内存屏障 | 通用内存屏障 | 写内存屏障 | 读内存屏障 | 数据依赖屏障 | 强制性内存屏障 |SMP内存屏障 )
  5. 【设计模式】 面向对象六大设计原则
  6. HashMap构造函数有哪些
  7. HTML 自学笔记(HTML框架+表单设计)
  8. 保护ASP.NET 应用免受 CSRF 攻击
  9. POJ 2299 Ultra-QuickSort(树状数组+离散化)
  10. DEDE利用Ajax实现调用当前登录会员的信息简要说明