Linux操作系统学习——启动


 概要

  Linux操作系统内核是服务端学习的根基,也是提高编程能力、源码阅读能力和进阶知识学习能力的重要部分,本文开始将记录Linux操作系统中的各个部分源码学习历程。

1. 理解代码的组织结构

Linux源码举例,首先你得知道操作系统分为哪几个部分,他们单独做了什么功能,如何进行配合完成更为具体的功能。建立整体的印象有助于后续深入学习的时候方便理解,毕竟代码是用的不是看的,理解他的作用有利于理解为什么要这么做。

2. 深入各个模块学习

模块接口:这里推荐微软的画图工具visio或者思维导图xmind,用其画图可以将各个模块的接口列出,并绘制各个模块之间的关系,通过了解接口可以清楚各个模块之间的关系,即绘制模块组织图

工作流程:通过上面一步得到各模块间的关系,然后实际用断点或log等方式看一看整体的工作流程,在模块组织图的基础上绘制程序流程图

模块粘合层:我们的代码有很多都是用来粘合代码的,比如中间件(middleware)、Promises 模式、回调(Callback)、代理委托、依赖注入等。这些代码模块间的粘合技术是非常重要的,因为它们会把本来平铺直述的代码给分裂开来,让你不容易看明白它们的关系。这些可以作为程序流程图的补充,让其中本来无法顺畅衔接的地方变得通畅无阻。

模块具体实现 :这是最难得地方,涉及到大量具体源码的学习。深入细节容易迷失在细节的海洋里,因此需要有一些重点去关注,将非重点的内容省略。通过学习绘制模块具体架构图和模块的算法时序图,可以帮助你更好的掌握源码的精髓。

3. 需要关注的包括

代码逻辑。代码有两种逻辑,一种是业务逻辑,这种逻辑是真正的业务处理逻辑;另一种是控制逻辑,这种逻辑只是用控制程序流转的,不是业务逻辑。比如:flag 之类的控制变量,多线程处理的代码,异步控制的代码,远程通讯的代码,对象序列化反序列化的代码等。这两种逻辑你要分开,很多代码之所以混乱就是把这两种逻辑混在一起了。

重要的算法。一般来说,我们的代码里会有很多重要的算法,我说的并不一定是什么排序或是搜索算法,可能会是一些其它的核心算法,比如一些索引表的算法,全局唯一 ID 的算法、信息推荐的算法、统计算法、通读算法(如 Gossip)等。这些比较核心的算法可能会非常难读,但它们往往是最有技术含量的部分。

底层交互。有一些代码是和底层系统的交互,一般来说是和操作系统或是 JVM 的交互。因此,读这些代码通常需要一定的底层技术知识,不然,很难读懂。

4. 可以忽略的包括

出错处理。根据二八原则,20% 的代码是正常的逻辑,80% 的代码是在处理各种错误,所以,你在读代码的时候,完全可以把处理错误的代码全部删除掉,这样就会留下比较干净和简单的正常逻辑的代码。排除干扰因素,可以更高效地读代码。

数据处理。只要你认真观察,就会发现,我们好多代码就是在那里倒腾数据。比如 DAODTO,比如 JSONXML,这些代码冗长无聊,不是主要逻辑,可以不理。

忽略过多的实现细节。在第一遍阅读源码时,已弄懂整体流程为主,至于具体的实现细节先简单的理清处过一遍,不用过于纠结。当梳理清楚全部的框架逻辑后,第二遍再深入的学习研究各个模块的实现,此时应该解决第一遍中的疑惑。第三遍可以跳出代码的实现,来看Linux的设计思路、编程艺术和演进之路。

重在实践Linux的代码都是可以调试的,看很多遍也许不如跟着调试走一遍,然后再自己修改修改做一些小测试。

传授知识。当你能将知识讲述给别人听,并让别人听懂时,你已经可以自豪的说洞悉了这些知识。所以不妨从一个小的例子开始自说自话,看能不能自圆其说,甚至写成博客、做成PPT给大家讲解。

  说了一大堆的废话,下面就正式开始操作系统的深入学习记录之旅了。

5. 混沌初开

  本文分析从按下电源键到加载BIOS以及后续bootloader的整个过程。犹如盘古开天辟地一般,该过程将混沌的操作系统世界分为清晰的内核态和用户态,并经历从实模式到保护模式的变化。这里先简单介绍一下名词,便于后续理解。

实模式Real Mode):又名 Real Address Mode,在此模式下地址访问的是真实地内存地址所在位置。在此模式下,可以使用20位(1MB)的地址空间,软件可以不受限制的操作所有地址的空间和IO设备。

保护模式Protected Mode):又名 Protected Virtual Address Mode,采用虚拟内存、页等机制对内存进行了保护,比起实模式更为安全可靠,同时也增加了灵活性和扩展性。

 5.1 从启动电源到BIOS 

当我们按下电源键,主板会发向电源组发出信号,接收到信号后,电源会提供合适的电压给计算机。当主板收到电源正常启动的信号后,主板会启动CPUCPU重置所有寄存器数据,并设置初始化数据,这个初始化数据在X86架构里如下所示:

1IP          0xfff02CS selector 0xf0003CS base     0xffff00004IP/EIP (Instruction Pointer) : 指令指针寄存器,记录将要执行的指令在代码段内的偏移地址5CS(Code Segment Register):代码段寄存器,指向CPU当前执行代码在内存中的区域(定义了存放代码的存储器的起始地址)

实模式采取内存段来管理 0 - 0xFFFFF的这1M内存空间,但是由于只有16位寄存器,所以最大地址只能表示为0xFFFFF64KB),因此不得不采取将内存按段划分为64KB的方式来充分利用1M空间。也就是上所示的,采取段选择子 + 偏移量的表示法。这种方法在保护模式中对于页的设计上也沿用了下来,可谓祖传的智慧了。具体的计算公式如下所示:

1PhysicalAddress = Segment Selector * 16 + Offset

  该部分由硬件完成,通过计算访问0XFFFF0,如果该位置没有可执行代码则计算机无法启动。如果有,则执行该部分代码,这里也就是我们故事的开始,BIOS程序了。

 5.2 BIOS到BootLoader 

  BIOS执行程序存储在ROM中,起始位置为0XFFFF0,当CS:IP指向该位置时,BIOS开始执行。BIOS主要包括以下内存映射:

 10x00000000 - 0x000003FF - Real Mode Interrupt Vector Table20x00000400 - 0x000004FF - BIOS Data Area30x00000500 - 0x00007BFF - Unused40x00007C00 - 0x00007DFF - Our Bootloader50x00007E00 - 0x0009FFFF - Unused60x000A0000 - 0x000BFFFF - Video RAM (VRAM) Memory70x000B0000 - 0x000B7777 - Monochrome Video Memory80x000B8000 - 0x000BFFFF - Color Video Memory90x000C0000 - 0x000C7FFF - Video ROM BIOS100x000C8000 - 0x000EFFFF - BIOS Shadow Area110x000F0000 - 0x000FFFFF - System BIOS12

其中最重要的莫过于中断向量表和中断服务程序。BIOS程序在内存最开始的位置(0x00000)用1 KB的内存空间(0x000000x003FF)构建中断向量表,在紧挨着它的位置用256字节的内存空间构建BIOS数据区(0x004000x004FF),并在大约57 KB以后的位置(0x0E05B)加载了8 KB左右的与中断向量表相应的若干中断服务程序。中断向量表中有256个中断向量,每个中断向量占4字节,其中两个字节是CS的值,两个字节是IP的值。每个中断向量都指向一个具体的中断服务程序。

 BIOS程序会选择一个启动设备,并将控制权转交给启动扇区中的代码。主要工作即使用中断向量和中断服务程序完成BootLoader的加载,最终将boot.img加载至0X7C00的位置启动。Linux内核通过Boot Protocol定义如何实现该引导程序,有如GRUB 2syslinux等具体实现方式,这里仅介绍GRUB2

5.3 BootLoader的工作

  boot.imgboot.S编译而成,512字节,安装在启动盘的第一个扇区,即MBR。由于空间有限,其代码十分简单,仅仅是起到一个引导的作用,指向后续的核心镜像文件,即core.imgcore.img包括很多重要的部分,如lzma_decompress.imgdiskboot.imgkernel.img等,结构如下图。

 整个流程如下:

1boot.img加载core.img的第一个扇区,即diskboot.img,对应代码为diskboot.S

2、diskboot.img加载core.img的其他部分模块,先是解压缩程序 lzma_decompress.img,再往下是 kernel.img,最后是各个模块 module 对应的映像。这里需要注意,它不是 Linux 的内核,而是 grub 的内核。注意,lzma_decompress.img 对应的代码是 startup_raw.S,本来 kernel.img 是压缩过的,现在执行的时候,需要解压缩。

3、加载完core之后,启动grub_main函数。

4、grub_main函数初始化控制台,计算模块基地址,设置 root 设备,读取 grub 配置文件,加载模块。最后,将 GRUB 置于 normal 模式,在这个模式中,grub_normal_execute (from grub-core/normal/main.c) 将被调用以完成最后的准备工作,然后显示一个菜单列出所用可用的操作系统。当某个操作系统被选择之后,grub_menu_execute_entry 开始执行,它将调用 GRUB boot 命令,来引导被选中的操作系统。

       在这之前,我们所有遇到过的程序都非常非常小,完全可以在实模式下运行,但是随着我们加载的东西越来越大,实模式这 1M 的地址空间实在放不下了,所以在真正的解压缩之前,lzma_decompress.img 做了一个重要的决定,就是调用 real_to_prot,切换到保护模式,这样就能在更大的寻址空间里面,加载更多的东西。

  开机时的16位实模式与内核启动的main函数执行需要的32位保护模式之间有很大的差距,这个差距谁来填补?head.S做的就是这项工作。就像 kernel boot protocol 所描述的,引导程序必须填充 kernel setup header (位于 kernel setup code 偏移 0x01f1 处) 的必要字段,这些均在head.S中定义。在这期间,head程序打开A20,打开pepg,废弃旧的、16位的中断响应机制,建立新的32位的IDT……这些工作都做完了,计算机已经处在32位的保护模式状态了,调用32位内核的一切条件已经准备完毕,这时顺理成章地调用main函数。后面的操作就可以用32位编译的main函数完成,从而正式启动内核,进入波澜壮阔的Linux内核操作系统之中。

 6. 总结 

  本文介绍了从按下电源开关至加载完毕BootLoader的整个过程,后续将继续分析从实模式进入保护模式,从而启动内核创建0号、1号、2号进程的整个过程。

欢迎转发点赞评论,感谢!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/2923.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Django框架之邮件系统,涉及HTML、富文本、附件邮件发送

参考 (892条消息) Django框架之邮件系统,涉及HTML、富文本、附件邮件发送_django邮件系统_李恩泽的技术博客的博客-CSDN博客https://blog.csdn.net/heroiclee/article/details/121406488 发送设置(settings.py) EMAIL_USE_SSL True # Sec…

Qt关闭主窗口后,退出所有异步线程

目录 1.要知道主窗口什么时候关闭2.关闭异步线程 1.要知道主窗口什么时候关闭 在widget.h新增下面的函数 private slots:void closeEvent(QCloseEvent *event);在widget.cpp新增 void Widget::closeEvent(QCloseEvent *event) {qDebug() << "关闭主窗口了&#x…

机器学习复习6

机器学习复习 1 - 在机器学习的背景下&#xff0c;什么是诊断(diagnostic)&#xff1f; A. 这指的是衡量一个学习算法在测试集(算法没有被训练过的数据)上表现如何的过程 B. 迅速尝试尽可能多的不同方法来改进算法&#xff0c;从而看看什么方法有效 C. 机器学习在医疗领域的应用…

基于Java+Swing+Mysql物流跟踪管理系统

基于JavaSwingMysql物流跟踪管理系统 一、系统介绍二、功能展示1.主页2.新增物流信息3.删除物流信息 三、数据库四、其他系统实现五、获取源码 一、系统介绍 该系统实现了查看物流列表、新增物流信息、删除物流信息 运行环境&#xff1a;eclipse、idea、jdk1.8 二、功能展示…

satellite: 利用TLE动态计算并实时显示多颗卫星的位置及轨迹

本示例的目的是介绍演示如何在vue+satellite项目中利用两行根数动态地计算,并显示多个卫星的位置及轨迹。每秒钟更新一下卫星的位置和角度,加载当前时间到固定时间(如720分钟后)的一段轨迹。 直接复制下面的 vue+openlayers源示例代码,操作2分钟即可运行实现效果 文章目…

怎么去除视频里的背景音乐?其实非常简单!

如何去除视频背景音乐&#xff1f;在视频处理中&#xff0c;有时我们需要从视频中提取声音并进行处理&#xff0c;而不仅仅是简单地去除整个背景音乐。我们可能需要有选择性地去除人声或背景音乐。这个处理过程对于选用合适的工具至关重要。在本文中&#xff0c;我将分享两种可…

深度学习图像分类、目标检测、图像分割源码小项目

​demo仓库和视频演示&#xff1a; 银色子弹zg的个人空间-银色子弹zg个人主页-哔哩哔哩视频 卷积网路CNN分类的模型一般使用包括alexnet、DenseNet、DLA、GoogleNet、Mobilenet、ResNet、ResNeXt、ShuffleNet、VGG、EfficientNet和Swin transformer等10多种模型 目标检测包括…

基于Python热门旅游景点数据分析系统设计与实现

博主介绍&#xff1a; ✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精彩专…

【MySql】基本查询

文章目录 插入操作insert查询操作selectselect查询where条件判断order by排序limit筛选分页结果 更新操作update删除操作delete插入查询结果 CRUD : Create(创建), Retrieve(读取)&#xff0c;Update(更新)&#xff0c;Delete&#xff08;删除&#xff09; 先创建提供一张表&am…

【CentOS】VirtualBox yum 无法使用

【CentOS】VirtualBox yum 无法使用 yum install net-tools -y出现如下错误&#xff1a; cannot find a valid baseurl for repo: base/7/x86_64或无法ping 解决如下&#xff1a; 进入系统&#xff0c;修改网卡信息。 执行修改命令&#xff0c;ifcfg-xxx 后面的xxx就是上面…

【从删库到跑路】MySQL系列——详细讲解SQL的DDL,DML,DQL,DCL语句

&#x1f38a;专栏【MySQL】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【如愿】 大一同学小吉&#xff0c;欢迎并且感谢大家指出我的问题&#x1f970; 文章目录 &#x1f354;关系型数据库⭐概念⭐特点 &#x1f354;MySQL数…

PACS/RIS医学影像管理系统源码 提供先进图像处理和算法

PACS&#xff08;医学影像存档与通信系统&#xff09;主要应用于医学影像的存储、传输和显示。它可以使医生突破胶片的局限&#xff0c;对病人的影像进行全方位的处理和观察&#xff0c;以便得出更准确的诊断。同时&#xff0c;PACS可以节省大量的胶片&#xff0c;降低成本。医…