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()创建的第一个线程也进入用户模式。

时间: 2024-10-21 19:14:04

linux 驱动学习笔记03--Linux 内核的引导的相关文章

linux 驱动学习笔记01--Linux 内核的编译

由于用的学习材料是<linux设备驱动开发详解(第二版)>,所以linux驱动学习笔记大部分文字描述来自于这本书,学习笔记系列用于自己学习理解的一种查阅和复习方式. #make config(基于文本的最为传统的配置界面,不推荐使用)#make menuconfig(基于文本菜单的配置界面)#make xconfig(要求 QT 被安装)#make gconfig(要求 GTK+被安装)在配置 Linux 2.6 内核所使用的 make config. make menuconfig. mak

linux 驱动学习笔记02--应用实例:在内核中新增驱动代码目录和子目录

下面来看一个综合实例,假设我们要在内核源代码 drivers 目录下为 ARM 体系结构新增如下用于 test driver 的树型目录:| --test  | -- cpu  | -- cpu.c  | -- test.c  | -- test_client.c  | -- test_ioctl.c  | -- test_proc.c  | -- test_queue.c在内核中增加目录和子目录,我们需为相应的新增目录创建 Makefile 和 Kconfig 文件,而新增目录的父目录中的 K

linux 驱动学习笔记04--简单驱动

首先贴代码helloworld.c和Makefile /************************************************************************* > File Name: helloworld.c > Author: hailin.ma > Mail: > Created Time: Wed 15 Jul 2015 02:39:35 PM CST ***************************************

Linux驱动学习之Linux-2.6.20.4内核移植

最近一段时间一直在学习向TQ2440开发板移植内核.移植驱动.真心觉得这方面的知识有很大的难度.但是从另一角度去看,难度越大,能力提升的空间就越大!! 1.解压源码 从网上下载一个Linux 内核,我是用的是Linux-2.6.20.4.然后用命令解压.建议解压到"/home/用户名"目录下.我的内核源码存放在: 2.添加对ARM的支持 因为所用的是TQ2440开发板,属于ARM9.因此要在系统中添加对ARM的支持. 方法:进入内核源码目录, 修改"Makefile"

Linux Kernel学习笔记

转自:http://blog.sina.com.cn/s/blog_55465b470100eb8c.html 这里贴部分内容: Chapter 2. 设备驱动程序开发 在编程思路上,机制表示需要提供什么功能,策略表示如何使用这些功能.区分机制和策略是UNIX设计最重要和最好的思想之一.如X系统就由X服务器和X客户端组成.X服务器实现机制,负责操作硬件,给用户程序提供一个统一的接口.而X客户端实现策略,负责如何使用X服务器提供的功能.设备驱动程序也是机制与策略分离的典型应用.在编写硬件驱动程序时

Linux系统学习笔记:序

Linux系统学习笔记:序 ??Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户.多任务.支持多线程和多CPU的操作系统.它能运行主要的UNIX工具软件.应用程序和网络协议.它支持32位和64位硬件.Linux继承了Unix以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统. 本人使用的Linux为Ubuntu,主要以<APUE>(第3版)为学习蓝本. 1. Unix/Linux 体系结构 如图: 内核的接口被称为系统调用.公用函数库构建在

Linux 操作系统学习笔记

一,unix 1.unix 特点 伸缩性强,开放性好, 2.基本原则 所有对象,硬件都是文件 配置数据以文本形式保存 短小的单目的程序构成 多个程序合作完成复杂任务 3.gnu 基本原则是共享,建立自由开放的unix系统 1984年 richard stallman 发起 基本体系是micro kernel 4.gpl Copyleft 原作者所有权 5.linux起源 Linustorvalds, 自由的类unix操作系统, 遵循gnu和gpl 6.linux 可以实现unix功能 遵循开源许

Linux程序设计学习笔记----网络通信编程API及其示例应用

转载请注明出处, http://blog.csdn.net/suool/article/details/38702855. BSD Socket 网络通信编程 BSD TCP 通信编程流程 图为面向连接的Socket通信的双方执行函数流程.使用TCP协议的通信双方实现数据通信的基本流程如下 建立连接的步骤 1.首先服务器端需要以下工作: (1)调用socket()函数,建立Socket对象,指定通信协议. (2)调用bind()函数,将创建的Socket对象与当前主机的某一个IP地址和TCP端口

Linux 程序设计学习笔记----进程管理与程序开发(下)

转载请注明出处:http://blog.csdn.net/suool/article/details/38419983,谢谢! 进程管理及其控制 创建进程 fork()函数 函数说明具体参见:http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html 返回值:Upon successful completion, fork() shall return 0 to the child process and shall re