linux 驱动学习笔记03--Linux 内核的引导
如图所示为 X86 PC 上从上电/复位到运行 Linux 用户空间初始进程的流程。在进入与 Linux相关代码之间,会经历如下阶段。

( 1 ) 当系统上电或复位时, CPU 会将 PC 指针赋值为一个特定的地址 0xFFFF0 并执行该地址处的指令。在 PC 机中,该地址位于 BIOS 中,它保存在主板上的 ROM 或 Flash 中。
( 2) BIOS 运行时按照 CMOS 的设置定义的启动设备顺序来搜索处于活动状态并且可以引导的设备。 若从硬盘启动, BIOS 会将硬盘 MBR(主引导记录)中的内容加载到 RAM。MBR 是一个 512 字节大小的扇区,位于磁盘上的第一个扇区中(0 道 0 柱面 1 扇区)。当 MBR 被加载到 RAM中之后, BIOS 就会将控制权交给 MBR。
( 3) 主引导加载程序查找并加载次引导加载程序。它在分区表中查找活动分区,当找到一个活动分区时,扫描分区表中的其他分区,以确保它们都不是活动的。当这个过程验证完成之后,就将活动分区的引导记录从这个设备中读入 RAM 中并执行它。
( 4) 次引导加载程序加载 Linux 内核和可选的初始 RAM 磁盘,将控制权交给 Linux 内核源代码。
( 5) 运行被加载的内核,并启动用户空间应用程序。
嵌入式系统中 Linux 的引导过程与之类似,但一般更加简洁。不论具体以怎样的方式实现,只要具备如下特征就可以称其为 Bootloader。
! 可以在系统上电或复位的时候以某种方式执行,这些方式包括被 BIOS 引导执行、直接在 NOR Flash 中执行、 NAND Flash 中的代码被 MCU 自动拷入内部或外部 RAM 执行等。
! 能将 U 盘、磁盘、光盘、 NOR/NAND Flash、 ROM、 SD 卡等存储介质,甚或网口、串口中的操作系统加载到 RAM 并把控制权交给操作系统源代码执行。
完成上述功能的 Bootloader 的实现方式非常多样化,甚至本身也可以是一个简化版的操作系统。著名的 Linux Bootloader 包括应用于 PC 的 LILO 和 GRUB,应用于嵌入式系统的 U-Boot、RedBoot 等。
相比较于 LILO, GRUB 本身能理解 EXT2、 EXT3 文件系统, 因此可在文件系统中加载 Linux,而 LILO 只能识别" 裸扇区"。U-Boot 的定位为" Universal Bootloader",其功能比较强大,涵盖了包括 PowerPC、
ARM、MIPS 和 X86 在内的绝大部分处理器构架,提供网卡、串口、 Flash 等外设驱动,提供必要的网络协议( BOOTP、 DHCP、 TFTP),能识别多种文件系统( cramfs、 fat、 jffs2 和 registerfs 等),并附带了调试、脚本、引导等工具,应用十分广泛。Redboot 是 Redhat 公司随 eCos 发布的 Bootloader 开源项目,除了包含 U-Boot 类似的强大功能外,它还包含 GDB stub(插桩),因此能通过串口或网口与 GDB 进行通信,调试 GCC 产生的任何程序(包括内核)。我们有必要对上述流程的第 5 个阶段进行更详细的分析,它完成启动内核并运行用户空间的init 进程。当内核映像被加载到 RAM 之后, Bootloader 的控制权被释放,内核阶段就开始了。内核映像并不是完全可直接执行的目标代码,而是一个压缩过的 zImage(小内核)或 bzImage(大内核,bzImage 中的 b 是" big"的意思)。
但是,并非 zImage 和 bzImage 映像中的一切都被压缩了,否则 Bootloader 把控制权交给这个内核映像它就" 傻" 了。实际上,映像中包含未被压缩的部分,这部分中包含解压缩程序,解压缩程序会解压映像中被压缩的部分。
zImage 和 bzImage 都是用 gzip 压缩的,它们不仅是一个压缩文件,而且在这两个文件的开头部分内嵌有 gzip 解压缩代码。
如图所示,当 bzImage(用于 i386 映像)被调用时,它从/arch/i386/boot/head.S 的 start 汇编例程开始执行。这个程序执行一些基本的硬件设置,并调用/arch/i386/boot/compressed/head.S 中的startup_32 例程。 startup_32 程序设置一些基本的运行环境(如堆栈)后,清除 BSS 段,调用/arch/i386/boot/compressed/misc.c 中的 decompress_kernel() C 函数解压内核。内核被解压到内存中之后,会再调用 /arch/i386/kernel/head.S 文件中 的 startup_32 例程,这个新的 startup_32 例程(称为清除程序或进程 0)会初始化页表,并启用内存分页机制,接着为任何可选的浮点单元( FPU)检测
CPU 的类型,并将其存储起来供以后使用。这些都做完之后, /init/main.c 中的 start_kernel()函数被调用,进入与体系结构无关的 Linux 内核部分。start_kernel()会调用一系列初始化函数来设置中断,执行进一步的内存配置。之后, /arch/i386/kernel/process.c 中 kernel_thread()被调用以启动第一个核心线程,该线程执行 init()函数,而原执行序列会调用 cpu_idle()等待调度。作为核心线程的 init()函数完成外设及其驱动程序的加载和初始化,挂接根文件系统。 init()打开/dev/console 设备,重定向 stdin、 stdout 和 stderr 到控制台。之后,它搜索文件系统中的 init程序(也可以由" init=" 命令行参数指定 init 程序),并使用 execve()系统调用执行 init 程序。搜索 init 程序的顺序为: /sbin/init、 /etc/init、 /bin/init 和/bin/sh。在嵌入式系统中,多数情况下,可以给内核传入一个简单的 shell 脚本来启动必需的嵌入式应用程序。至此,漫长的 Linux 内核引导和启动过程就此结束,而 init()对应的这个由 start_kernel()创建的第一个线程也进入用户模式。

linux 驱动学习笔记03--Linux 内核的引导的更多相关文章
- linux 驱动学习笔记01--Linux 内核的编译
由于用的学习材料是<linux设备驱动开发详解(第二版)>,所以linux驱动学习笔记大部分文字描述来自于这本书,学习笔记系列用于自己学习理解的一种查阅和复习方式. #make confi ...
- 小松之LINUX 驱动学习笔记(二)
这两天一直在看字符驱动那块,后来从网上找啦几个例子,自己编译啦下,安装啥的都挺正常,就是用测试程序测试的时候总出问题,现在找到一个能测试的代码,自己先看看和原来的那个代码有啥不同,后面会继续更新,说下 ...
- 小松之LINUX 驱动学习笔记(一)
本篇主要是讲解驱动开发的基础知识以及一些环境配置方面的问题. 下面是一个hello world的简单的模块代码,很简单./*********************** 模块的简单例子* author ...
- linux 驱动学习笔记02--应用实例:在内核中新增驱动代码目录和子目录
下面来看一个综合实例,假设我们要在内核源代码 drivers 目录下为 ARM 体系结构新增如下用于 test driver 的树型目录:| --test | -- cpu | -- cpu.c ...
- Linux 驱动学习笔记05--字符驱动实例,实现一个共享内存设备的驱动
断断续续学驱动,好不容易有空,做了段字符驱动的例子.主要还是跟书上学习在此记录下来,以后说不定能回过头来温故知新. 首先上驱动源码 gmem.c: /************************* ...
- linux 驱动学习笔记04--简单驱动
首先贴代码helloworld.c和Makefile /************************************************************************ ...
- linux驱动学习笔记---实现中断下半部以及驱动编写规范(七)【转】
转自:https://blog.csdn.net/weixin_42471952/article/details/81609141 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协 ...
- 小松之LINUX驱动学习笔记之模块间函数调用通讯
1. 符号导出函数 EXPORT_SYMBOL() EXPORT_SYMBOL标签内定义的函数对全部内核代码公开,不用修改内核代码就可以在您的内核模块中直接调用. EXPORT_SYMBOL_GPL( ...
- Linux驱动学习笔记(6)信号量(semaphore)与互斥量(mutex)【转】
转自:http://blog.chinaunix.net/uid-24943863-id-3193530.html 并发导致竟态,从而导致对共享数据的非控制访问,产生非预期结果,我们要避免竟态的发生. ...
随机推荐
- Keep-Alive 总结
一.简介 Keep-Alive是http请求头信息中的一个配置参数,开启之后俗称保持HTTP长连接,HTTP 1.0和HTTP 1.1都支持,HTTP1.0中该属性默认是关闭的,可在头信息中配置开启( ...
- 无法打开登录所请求的数据库 "xxx"登录失败用户 'NT AUTHORITY\NETWORK SERVICE'
解决:添加用户,选择NT AUTHORITY\SYSTEM登录名,选择当前数据库的架构. 勾选架构 勾选成员身份.如果不勾选,也会报异常:拒绝了对对象 'FW_ORG' (数据库 'ZW_DWSJ', ...
- 挖掘微信Web版通信的全过程 [转]
昨天是周末,在家闲得无聊,于是去weiphone.com逛了一圈,偶然发现有人发了一帖叫<微信 for Mac>, 这勾起了我的好奇心,国内做Mac开发的人确实很少,对于那些能够独自开发一 ...
- Nginx跨域配置方法
配置文件如下,重点在49~52行 #user nobody; worker_processes ; #error_log logs/error.log; #error_log logs/error.l ...
- XE6 & IOS开发之开发者账号、苹果证书(3):关于在XE6中使用苹果证书的简单介绍
网上能找到的关于Delphi XE系列的移动开发的相关文章甚少,本文尽量以详细的图文内容.傻瓜式的表达来告诉你想要的答案. 原创作品,请尊重作者劳动成果,转载请注明出处!!! 1.关于在XE6中使用苹 ...
- MySQL Workbench “Error Code: 1175” 的解决方法
转自:http://www.linuxidc.com/Linux/2012-04/59333.htm 当用MySQL Workbench进行数据库的批量更新时,执行一个语句会碰到以下错误提示: Err ...
- WinCE\Window Mobile程序桌面化总结
1.系统API处理 将桌面.移动API分开处理 2.一份代码,两个工程,分别编译 添加已有文件时,使用添加链接,而不是添加附本 3.桌面窗体出现位置不规律,样式不统一问题 首先,在窗体类成员加入两个成 ...
- Jmeter plugin jp@gc - PerfMon Metrics Collector
Jmeter由于是开源工具,所以目前有很多插件可以供使用,最简单的方法是先把Plugin Manager安装了 下载地址:https://jmeter-plugins.org/wiki/Plugins ...
- 《疯狂Java讲义》(四)---- 面向对象&基于对象
"基于对象"也使用了对象,但是无法利用现有的对象模板产生新的对象类型,继而产生新的对象,也就是说,"基于对象"没有继承的特点,而多态更需要继承,所以" ...
- Use Spring transaction to simplify Hibernate session management
Spring对Hibernate有很好的支持 DataSource ->SessionFactory-> HibernateTranscationManagerHibernate中通 ...