Linux kernel启动过程
0. 声明
kernel版本号3.10.53
1. 链接脚本
arch/arm/kernel/vmlinux.lds.S ==>vmlinux.lds
生成的链接脚本(vmlinux.lds)中的重点内容如下:
OUTPUT_ARCH(arm)
ENTRY(stext)
······
根据链接脚本可知kernel执行入口为stext,搜索stext即可得到入口函数的定义。
2. 入口函数(stext)实现
函数stext是一个汇编函数,其定义在arch/arm/kernel/head.S中,stext函数主要做了以下几件事:
(1) 关闭irq和fiq,设置svc管理模式
(2) 判断是或支持这个CPU
(3) 判断是否支持这个单板(通过uboot传入的机器ID判断)
(4) 创建页表,为后面的MMU做准备
(5) 使能MMU并跳到__switch_data处,复制数据段,清除bss段,设置栈,调用start_kernel第一个C函数
简化后的代码如下:
ENTRY(stext)
ldr r13, =__mmap_switched @将__mmap_switched函数地址存放到r13寄存器
1: b __enable_mmu
ENDPROC(stext)
--------------------------------------------------------------------------__enable_mmu:
b __turn_mmu_onENDPROC(__enable_mmu)
--------------------------------------------------------------------------
ENTRY(__turn_mmu_on)
mov r3, r13 @将r13寄存器中的值存放到r3寄存器
mov pc, r3 @将PC指针指向r3寄存器中存放的地址
ENDPROC(__turn_mmu_on)
-------------------------------------------------------------------------__mmap_switched: @ arch/arm/kernel/head-common.Sb start_kernel
ENDPROC(__mmap_switched)//调用流程总结:stext--->__enable_mmu--->__turn_mmu_on--->__mmap_switched--->start_kernel
3.start_kernel函数
函数start_kernel是kernel启动过程中调用的第一个C函数,其定义在 init/main.c 中;在start_kernel函数中执行了大量的初始化工作,以下是挑选出来的一小部分常见和常用的初始化内容:
asmlinkage void __init start_kernel(void)
{/*打印以下linux版本信息: “Linux version 2.6.22.6(gcc version 3.4.5) #1 Fri Jun 16 00:55:53 CST 2017” */printk(linux_banner);//系结构相关的内核初始化过程,处理uboot传递进来的atag参数 setup_arch(&command_line);/* 进程调度器初始化 */sched_init(); /* 禁止内核抢占 */ preempt_disable();/* 打印Linux启动命令行参数 */ printk(KERN_NOTICE "Kernel command line: %s/n", boot_command_line);//初始化定时器Timer相关的数据结构 init_timers(); //软中断初始化 softirq_init(); //初始化时钟源 timekeeping_init()//初始化控制台以显示printk的内容,在此之前调用的printk,只是把数据存到缓冲区里, //只有在这个函数调用后,才会在控制台打印出内容 //该函数执行后可调用printk()函数将log_buf中符合打印级别要求的系统信息打印到控制台上。 console_init(); /* 虚拟文件系统的初始化 */vfs_caches_init_early(); //测试CPU的各种缺陷,记录检测到的缺陷,以便于内核的其他部分以后可以使用他们工作。 check_bugs(); //电源相关的初始化 //http://blogold.chinaunix.net/u/548/showart.php?id=377952 acpi_early_init(); /* before LAPIC and SMP init */ //接着进入rest_init()创建init进程,创建根文件系统,启动应用程序rest_init();
}static noinline void __init_refok rest_init(void)
{//启动init进程,然后进入kernel_init中启动应用程序kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
}static int __ref kernel_init(void *unused)
{if (execute_command) { //解析并挂载根文件系统if (!run_init_process(execute_command))return 0;pr_err("Failed to execute %s. Attempting defaults...\n",execute_command);}if (!run_init_process("/sbin/init") || //执行应用程序!run_init_process("/etc/init") || //执行应用程序!run_init_process("/bin/init") || //执行应用程序!run_init_process("/bin/sh")) //执行应用程序return 0
}
4. 小发现
在分析第二步的时候调用了head-common.S文件中的__mmap_switched函数,但是head-common.S却并没有被编译为.o文件???
验证步骤:
4.1 执行命令 grep -nr "head-common" *,发现head.S文件末尾有如下包含语句
#include "head-common.S"
4.2 执行反汇编命令将head.o反汇编
arm-linux-androideabi-objdump -d head.o > head.txt
4.3 打开反汇编文件head.txt可以发现其中有__mmap_switched函数的定义
0000005c <__mmap_switched>:5c: e28f3044 add r3, pc, #68 ; 0x4460: e8b300f0 ldm r3!, {r4, r5, r6, r7}64: e1540005 cmp r4, r568: 11550006 cmpne r5, r66c: 1494b004 ldrne fp, [r4], #470: 1485b004 strne fp, [r5], #474: 1afffffb bne 68 <__mmap_switched+0xc>78: e3a0b000 mov fp, #07c: e1560007 cmp r6, r780: 3486b004 strcc fp, [r6], #484: 3afffffc bcc 7c <__mmap_switched+0x20>88: e89320f0 ldm r3, {r4, r5, r6, r7, sp}8c: e5849000 str r9, [r4]90: e5851000 str r1, [r5]94: e5862000 str r2, [r6]98: e3570000 cmp r7, #09c: 13c04002 bicne r4, r0, #2a0: 18870011 stmne r7, {r0, r4}a4: eafffffe b 0 <start_kernel>
000000a8 <__mmap_switched_data>:
4.4 总结:head.o 中好像只包含了head-common.S文件中的部分函数
Linux kernel启动过程相关推荐
- arm linux内核启动过程,ARM64的启动过程之(一):内核第一个脚印
ARM64的启动过程之(一):内核第一个脚印 作者:linuxer 发布于:2015-10-10 15:06 分类:ARMv8A Arch 一.前言 kernel的整个启动过程涉及的内容很多,不可能每 ...
- Linux开启动过程详解
Linux开启动过程详解 Linux启动过程 前言: Linux是一种自由和开放源代码的类UNIX操作系统.该操作系统的内核由林纳斯·托瓦兹在1991年10月5日首次发布.在加上用户空间的应用程序之后 ...
- linux文件系统启动流程,linux 内核启动过程以及挂载android 根文件系统的过程
转载 作者:汕头大学-黄珠唐 时间:2009 年10 月29 日 主要介绍linux 内核启动过程以及挂载android 根文件系统的过程,以及介绍android 源代码中文件系统部分的浅析. 主要源 ...
- Linux内核启动过程概述
Hi!大家好,我是CrazyCatJack.今天给大家带来的是Linux内核启动过程概述.希望能够帮助大家更好的理解Linux内核的启动,并且创造出自己的内核^_^ Linux的启动代码真的挺大,从汇 ...
- linux 打开上一级目录,linux开机启动过程、PATH、过滤一级目录、cd的参数、ls -lrt、命令切割日志...
第二波命令正向我方来袭 :开机启动过程.PATH.过滤一级目录.cd的参数.ls -lrt.命令切割日志 1.1 linux开机启动过程 1.1.1 开机自检(BIOS)-- MBR引导-- GRUB ...
- 简述arm linux内核启动流程,Linux内核启动过程和Bootloader(总述)
1.Linux内核启动过程概述 一个嵌入式 Linux 系统从软件角度看可以分为四个部分:引导加载程序(Bootloader),Linux 内核,文件系统,应用程序.其中 Bootloader是系统启 ...
- linux内核启动过程5:启动用户空间
上一篇<<linux内核启动过程4:内核运行时>>分析到了内核进入运行时状态(不退出),本篇分析用户空间(用户层)的加载过程. 启动应用空间 进入kernel_init函数,在 ...
- linux内核启动过程4:内核运行时
上一篇<<linux内核启动过程3:内核初始化阶段>>分析到了start_kernel执行流程,本篇继续内核切换到运行时状态. 内核运行时状态 内核初始化流程已经分析完成,如何 ...
- Linux内核启动过程和Bootloader(总述)
1.Linux内核启动过程概述 一个嵌入式 Linux 系统从软件角度看可以分为四个部分:引导加载程序(Bootloader),Linux 内核,文件系统,应用程序.其中 Bootloader ...
最新文章
- 学会Python后能找到什么工作,待遇如何?
- PHP的抽象类的一段简单代码示例
- Linux自动备份文件(linux计划任务)
- python数值型转换字符型_2.6 字符型常量
- MathType公式保存后为什么字体会变化
- 我爱的人,你知道我一直在
- 用php打出前一天的时间格式,[php]用PHP打印出前一天的时间格式
- 第一次使用 Blog
- Linux SElinux
- C语言变量声明问题——变量定义一定要放在所有执行语句/语句块的最前面吗?
- 2-7 hash(2)
- matlab如何仿真递推型dft算法,并联型有源滤波器的设计与仿真
- IDEA 思维导图 ,类UML 图工具插件 plantUML integration
- 运算放大器分析----虚短和虚断简单计算
- 电商一定是一元化结构
- 【解决方案】“博物馆热”背后,如何建设安防视频监控体系保障文物安全?
- 你一定要这么多功能么?——献给希望创业的兄弟们
- Linux 磁盘管理-配额管理-配置用户对磁盘进行指定大小或者文件数量的使用权限
- PLM,是一个英文缩写,有2个含义,一是表示产品生命周期管理(product lifecycle management,PLM),...
- vue封装上拉菜单组件_Vue的灵活的lil上下文菜单组件