linux longmode启动顺序,arm linux 发动流程之 进入内核

仍是从编译链接生成vmlinux的进程来看吧,由一大堆.o文件链接而成,第一个便是

kernel/arch/arm/kernel/head-armv.o ,并且咱们还看到了

lds链接文件kernel/arch/arm/vmlinux.lds,先把它剖析一下

ENTRY(stext)//进口点是stext应该就在head-armv.s中了

SECTIONS

{

. = 0xC0008000;//基址,是内核开端的虚拟地址

.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 = .;

}

关于虚拟地址和物理地址的:运用MMU后,体系就会运用虚拟地址,经过MMU来指向

实践物理地址而在这儿咱们的0xC0008000实践物理地址便是0x30008000,

详细关于MMU的介绍参阅《ARM体系结构与编程》。

到head-armv.s找到程序的进口

.section “.text.init”,#alloc,#execinstr

.typestext, #function

ENTRY(stext)

movr12, r0

movr0, #F_BIT | I_BIT | MODE_SVC@ make sure svc mode

msrcpsr_c, r0@ and all irqs disabled

bl__lookup_processor_type

teqr10, #0@ invalid processor?

moveqr0, #p@ yes, error p

beq__error

bl__lookup_architecture_type

teqr7, #0@ invalid architecture?

moveqr0, #a@ yes, error a

beq__error

bl__create_page_tables

adrlr, __ret@ return address

addpc, r10, #12@ initialise processor

来看看上一句跳到哪里去了

去寻找r10的值,是在__lookup_processor_type子函数中赋的

__lookup_processor_type:

adrr5, 2f//r5 标号2的地址基址是0x30008000

ldmiar5, {r7, r9, r10}//r7=__proc_info_end r9=__proc_info_begin

subr5, r5, r10//r10 标号2的链接地址 基址是0xc0008000

addr7, r7, r5@ to our address space

addr10, r9, r5//r10 改换为基址是0x30008000的__proc_info_begin

2:.long__proc_info_end

.long__proc_info_begin

.long2b

这样r10中寄存的是__proc_info_begin的地址,由于现在咱们还没有翻开MMU

所以仍是需求把基址改换到0x30008000,接着咱们就去找__proc_info_begin吧

留意到在上面的vmlinux.lds中有这个标号,下来链接的是.proc.info段,

在kernel/arch/arm/mm/proc-arm920.s的最终找到了这个段

.section “.proc.info”, #alloc, #execinstr

.type__arm920_proc_info,#object

__arm920_proc_info:

.long0x41009200

.long0xff00fff0

.long0x00000c1e@ mmuflags

b__arm920_setup

ok,这样咱们就知道addpc, r10, #12跳到哪里去了,由于这个地址刚好放了条跳转句子

留意了b句子用的都是相对地址,所以不需求改换地址,反正是跳到__arm920_setup,并且

上一条句子是adrlr, __ret,设定了__arm920_setup的回来地址是__ret,所以履行完

__arm920_setup后回到head-armv.s的__ret标号持续履行.

__ret:ldrlr, __switch_data

mcrp15, 0, r0, c1, c0//留意这儿了,在这儿翻开了MMU

movr0, r0

movr0, r0

movr0, r0

movpc, lr//跳到__mmap_switched,这儿现已用了虚拟地址了吧

// 这条指令ldrlr, __switch_data加载的__mmap_switched地址便是虚拟地址啊

__switch_data:.long__mmap_switched

从__mmap_switched一路履行下来,就要调到C言语代码中去了

bSYMBOL_NAME(start_kernel)//在kernel/init/main.c中

这个程序不是特别杂乱,细心看看仍是能大约看懂,我也不能去逐个注释

这儿有一个流程图

e5dadc64b815b991f817358e27014084.png

到了C言语中就不是很难理解了

lock_kernel();

printk(linux_banner);

setup_arch(&command_line);

printk(“Kernel command line: %s/n”, saved_command_line);

parse_options(command_line);

trap_init();

init_IRQ();

sched_init();

softirq_init();

time_init();

便是一大堆初始化作业,追着每个函数去看好了

start_kernel最终调用的一个函数

static void rest_init(void)

{

kernel_thread(init, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);

unlock_kernel();

current->need_resched = 1;

cpu_idle();

}

用kernel_thread建立了一个init进程,履行的是main.c中的init函数

lock_kernel();

do_basic_setup();

在do_basic_setup中调用了do_initcalls函数

各种驱动都是在do_initcalls(void)中完结的

static void __init do_initcalls(void)

{

initcall_t *call;

call = &__initcall_start;

do {

(*call)();

call++;

} while (call < &__initcall_end);

flush_scheduled_tasks();

}

__initcall_start也是在vmlinux.lds中赋值的,那就需求找到.initcall.ini这个段

在kernel/include/linux/init.h中能够找到

#define __init_call__attribute__ ((unused,__section__ (“.initcall.init”)))

typedef int (*initcall_t)(void);

#define __initcall(fn)/

static initcall_t __initcall_##fn __init_call = fn

细心研讨下就发现这是把初始化函数的地址放到了.initcall.init段中

这样就能够不断调用驱动的初始化函数了

假如没有界说MODULE,那么#define module_init(x)__initcall(x);

所以假如要把驱动的编译进内核就很简略了吧

init的最终

if (execute_command)

execve(execute_command,argv_init,envp_init);

execute_command与ppcboot传的命令行参数是有关的哦,便是init=/linuxrc

这样就要去履行根目录下的linuxrc脚本,这个脚本会去履行busybox

而busybox又去履行/etc/init.d/rcS脚本,这个脚本又去履行/usr/etc/rc.local

完了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值