原文地址:

http://www.manio.org/cn/startup-of-linux-view-of-society.html

其实这才应该是这一系列文章的第一节,因为这篇文章讲的是盘古开天地的事。话说Mr. Process是一个现代人,但是,只要是人,总该有个祖先。人们总想知道自己从哪来,然后才可以估摸算一下自己将去向何方。所以咱也要了解一下Linux的世界里人类的起源。

图1:从上电到BIOS

按下电源开关的那个真实的人就是Linux世界里的上帝,他创造了Linux世界的一切。当他按下机箱上的电源开关时,主板开始供电,CPU上的Reset Pin被拉高,这会引起CPU的一系列动作,这些动作是芯片设计时就决定的。CPU中的一些寄存器被置为固定的值,因为这些寄存器可能在启动的过程中要使用,比如CS(代码段寄存器)和EIP(指针指令寄存器)。这一步完成之后,CPU就可开执行地址为0xfffffff0里的ROM中的程序。这段程序就是BIOS(Basic Input Output System)。

BIOS完成下面的功能:

1.POST(Power-On Self Test):顾名思名,就是查查有什么设备,这些设备是不是正常。要是CPU有Advanced Configuration and Power Interface(ACPI )的支持,也在这个时候进行。ACPI是用来对电源进行管理的,用来节电之类的。

2.初始化设备:确保没有IRQ和IO冲突。

3.寻找OS/Bootloader。这一步后面点再细说

我们在BIOS的设置菜单里能够设置从何处启动,比如软盘,硬盘,光驱…BIOS会按我们设定的顺序搜索OS。

4.把Bootloader复制到RAM里(地址为0x00007c00),然后那个地址开始执行。

什么是Bootloader?

现在,我们只要关心的是:bootloader会找到OS,把OS内核COPY到RAM中。

图2:boot loader的加载

如上图所示,在硬盘的第一个sector,有一个分区表(记录了哪些分区上有操作系统)和一个小版的Bootloader。当这个BIOS被设置为从这里启动时,这个小版的bootloader被复制到RAM的0x00007c00。然后它会把自己又移动到0x00096a00。在这之后,它再把另一段Bootloader从硬盘上复制到0x00096c00,然后从那里开始执行。分作两段的原因是因为现在的bootloader太大了,在MBR上存不完那么多。

Bootloader会把OS的内核映像复制到RAM中。

Bootloader的工作

1. 调用BIOS以显示“Loading Image”的消息。

2. 调用BIOS,把内核映像的前512字节复制到0×00090000,setup()函数在0×00090200。

3. 调用BIOS,把剩下的内核映像加载到0×00010000(小内核zImage)或0×00100000(大内核bzImage)

4. 跳到setup()开始执行。

Setup()的工作

setup()用来初始化设备。虽然BIOS已经做了一些初始化的工作,但是Linux关不依赖于他。setup()会初始化键盘,FPU等设备,并设置一些寄存器。在Setup()的最后,会调用startup_32()。

startup_32()

Linux里有两个startup_32()。

首先会执行的是arch/i386/boot/compressed/head.S里的那个。这个startup_32()的作用主要是解压内核。

第二个startup_32()是在arch/i386/kernel/head.S的。这个startup_32()的工作就是为Linux的第一个进程(就是Mr. Process的祖先)设置生存环境。最后跳到start_kernel()中去。

在Understanding the Linux Kernel 3rd 中的描述如下

  1. Initializes the segmentation registers with their final values.
  2. Fills the bss segment of the kernel (see the section “Program Segments and Process Memory Regions” in Chapter 20) with zeros.
  3. Initializes the provisional kernel Page Tables contained in swapper_pg_dir and pg0 to identically map the linear addresses to the same physical addresses, as explained in the section “Kernel Page Tables” in Chapter 2.
  4. Stores the address of the Page Global Directory in the cr3 register, and enables paging by setting the PG bit in the cr0 register.
  5. Sets up the Kernel Mode stack for process 0 (see the section “Kernel Threads” in Chapter 3).
  6. Once again, the function clears all bits in the eflags register.
  7. Invokes setup_idt( ) to fill the IDT with null interrupt handlers (see the section “Preliminary Initialization of the IDT” in Chapter 4).
  8. Puts the system parameters obtained from the BIOS and the parameters passed to the operating system into the first page frame (see the section “Physical Memory Layout” in Chapter 2).
  9. Identifies the model of the processor.

10.  Loads the gdtr and idtr registers with the addresses of the GDT and IDT tables.

11.  Jumps to the start_kernel( ) function.

start_kernel()的工作

完成所有组件的初始化工作。

Understanding the Linux Kernel对这一段工作的描述如下:

¨    The scheduler is initialized by invoking the sched_init( ) function (see Chapter 7).

¨    The memory zones are initialized by invoking the build_all_zonelists( ) function (see the section “Memory Zones” in Chapter 8).

¨    The Buddy system allocators are initialized by invoking the page_alloc_init( ) and mem_init( ) functions (see the section “The Buddy System Algorithm” in Chapter 8).

¨    The final initialization of the IDT is performed by invoking trap_init( ) (see the section “Exception Handling” in Chapter 4) and init_IRQ( ) (see the section “IRQ data structures” in Chapter 4).

¨    The TASKLET_SOFTIRQ and HI_SOFTIRQ are initialized by invoking the softirq_init( ) function (see the section “Softirqs” in Chapter 4).

¨    The system date and time are initialized by the time_init( ) function (see the section “The Linux Timekeeping Architecture” in Chapter 6).

¨    The slab allocator is initialized by the kmem_cache_init( ) function (see the section “General and Specific Caches” in Chapter 8).

¨    The speed of the CPU clock is determined by invoking the calibrate_delay( ) function (see the section “Delay Functions” in Chapter 6).

¨    The kernel thread for process 1 is created by invoking the kernel_thread( ) function. In turn, this kernel thread creates the other kernel threads and executes the /sbin/init program, as described in the section “Kernel Threads” in Chapter 3.

以上几个函数的执行过程如下图:

图3:启动函数的执行过程

第二个startup_32()和start_kernel()揭示了Linux一生的真谛。从这里面咱看到了Mr. Process(一个普通的进程)所拥有的一切是怎么得到的。弄清楚了这些,也就弄清楚了Linux。Really清楚。

BTW,我做的图怎么那么好看~美感天生在那里,你挡都挡不住,怎么搞怎么好看加专业!

Mr. Process的一生-Linux内核的社会视角 (2)启动相关推荐

  1. linux 内核load addr,linux2.4启动分析(1)---内核启动地址的确定 vmlinux LOAD_ADDR ZRELADDR...

    http://blog.chinaunix.net/u/31100/showart_244622.html ================================ Author: taoyu ...

  2. 十天学Linux内核之第七天---电源开和关时都发生了什么

    十天学Linux内核之第七天---电源开和关时都发生了什么 原文:十天学Linux内核之第七天---电源开和关时都发生了什么 说实话感觉自己快写不下去了,其一是有些勉强跟不上来,其二是感觉自己越写越差 ...

  3. linux内核线程优先级设置,Linux c 线程属性,线程优先级的修改

    Linux c 线程属性,线程优先级的修改 发布时间:2018-07-19 10:24, 浏览次数:1290 , 标签: Linux 线程属性的设置,网上找的文章总感觉不够全面,还是结合man手册查看 ...

  4. linux内核 cpu_die,解密“内核”,和“cpu”又有啥关系?

    感谢大家对天才疯子的阅读与支持! 天才疯子每天与你不见不散,带你装逼带你飞! 核心(Die)又称为内核,是CPU最重要的组成部分.CPU中心那块隆起的芯片就是核心,是由单晶硅以一定的生产工艺制造出来的 ...

  5. 详解神秘Linux内核

    在开始步入Linux设备驱动程序的神秘世界之前,让我们从驱动程序开发人员的角度看几个内核构成要素,熟悉一些基本的内核概念. 我们将学习内核定时器.同步机制以及内存分配方法.不过,我们还是得从头开始这次 ...

  6. linux 0.11根文件系统,linux内核与根文件系统之间的关联的理解

    学者 于 2011-10-19 12:46:08发表: 哦,原来还有一个initrd镜像,后缀名为".img",我一直以为只有一个内核镜像呢: 还有引导程序的路径表示与系统不同啊! ...

  7. Linux内核的Nand驱动流程分析

    最近在做Linux内核移植,总体的感觉是这样的,想要彻底的阅读Linux内核代码几乎是不可能的,至少这还不是嵌入式学期初期的重要任务.内核代码解压后有250M左右,据统计,有400多万行,而且涉及到了 ...

  8. 《Linux内核剖析》(Yanlz+VR云游戏+Unity+SteamVR+云技术+5G+AI+Makefile+块设备驱动+字符设备驱动+数学协处理器+文件系统+内存管理+GDB+立钻哥哥+==)

    <Linux内核剖析> <Linux内核剖析> 版本 作者 参与者 完成日期 备注 YanlzLinux_Kernel0.12_V01_1.0 严立钻 2020.02.06 # ...

  9. Linux内核块设备总结(一)

    前言 在分析块设备驱动之前,整体规划如下: 1. 介绍qemu使Linux内核挂载块设备.2. 介绍块设备驱动挂载过程.3. 介绍块设备驱动运行过程. 本章先重点介绍使用qemu使Linux内核和根文 ...

最新文章

  1. Weblogic禁用SSLv3和RC4算法教程
  2. can收发器 rx_CANOpen系列教程03 _CAN收发器功能、原理及作用
  3. 数据结构入门之链表(C语言实现)
  4. c# c均值聚类及DBSCAN聚类
  5. ai进入轮廓模式怎么退出_五大容易过劳死的职业 怎么避免进入过劳死模式?
  6. 【HamonyOS嵌入式】BearPi-HM_Nano控制DS18B20温度传感器(注释版)
  7. HNU JAVA 导弹防御系统
  8. 火影智能AI伪原创插件伪原创源码
  9. app软件小程序开发
  10. Modbus RS485 设备的串口调试
  11. 解决error:torch has an invalid wheel,.dist -info directory not fount
  12. java swing实训项目(图书管理系统)
  13. Navicat对数据库进行简单的单表查询语句
  14. 斗破苍穹文字页游php_《斗破苍穹》在网文中的地位到底怎么样?
  15. 预见未来 | 图像识别的未来:机遇与挑战并存
  16. Object转换成json的JS代码
  17. 如何看待2019年初多闪、马桶MT和聊天宝这三款社交APP同时发布
  18. 小米十年,难凉热血。回看雷军在演讲中没说的人和事
  19. 使用决策树(decision-tree)预测隐形眼镜类型(标签二值化(LabelBinarizer)复原输出)
  20. 2021-11-18《MySQ必知必会》第四章到第七章整理

热门文章

  1. 华三h3c交换机最详细的配置实例手册_华为/思科/华三基本命令对比
  2. mysql 当前id前后几个,使用mysql选择id前后的行
  3. jenkins android sdk,Jenkins为什么找不到Android SDK?
  4. 【C++】多线程(链式、循环队列)实现生产者消费者模式
  5. Linux网络编程实例分析
  6. 使用Python和OpenCV对轮廓进行排序(从左到右,自上而下)
  7. windows/linux计算文件 MD5值
  8. 实现计时、时钟,实时获取当前年月日时分秒,记录时间(获取当前的时间,开始计时,计时过程相当于你的电脑时钟)0000年00月00日 00:00:00
  9. 【进阶玩法】Angular用emit()实现类似Vue.js的v-model双向绑定[(ngModel)]功能
  10. CentOS需要安装的JAVA环境的相关软件