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          0xfff0

2CS selector 0xf000

3CS base     0xffff0000

4IP/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 Table

 20x00000400 - 0x000004FF - BIOS Data Area

 30x00000500 - 0x00007BFF - Unused

 40x00007C00 - 0x00007DFF - Our Bootloader

 50x00007E00 - 0x0009FFFF - Unused

 60x000A0000 - 0x000BFFFF - Video RAM (VRAM) Memory

 70x000B0000 - 0x000B7777 - Monochrome Video Memory

 80x000B8000 - 0x000BFFFF - Color Video Memory

 90x000C0000 - 0x000C7FFF - Video ROM BIOS

100x000C8000 - 0x000EFFFF - BIOS Shadow Area

110x000F0000 - 0x000FFFFF - System BIOS

12

其中最重要的莫过于中断向量表和中断服务程序。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号进程的整个过程。

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【SpringCloud入门】-- 初识Eureka注册中心

目录 1.SpringCloudEureka简介 2.什么是CAP原则? 3.注册中心的概念? 4.SpringCloud其他注册中心 5.搭建Eureka注册中心 6.eureka的配置(主要是server,instance,client) 7.eureka集群概念 8.eureka集群搭建 1.SpringCloudE…

基于R语言的物种气候生态位动态量化与分布特征模拟

目录 专题一 引言 专题二 数据获取与处理方法 专题三 组合物种分布模型(Ensemble Species Distribution Model)的原理与使用 专题四 拓展研究 专题五 结果分析与论文写作 专题六 案例分析 专题七 总结和展望 利用R语言进行物种气候生态位动态量化…

【蓝桥杯算法题】用java遍写税收计算

【蓝桥杯算法题】用java遍写税收计算 题目&#xff1a;劳务报酬税收计算&#xff1a;输入 m &#xff0c;输出税后收入。如果 m <800&#xff0c;不扣税&#xff0c; 如果800< m <4000&#xff0e;则 m 减去800后的金额扣除20&#xff05;所得税。如果 m >4000&…

【计算机网络详解】——运输层(学习笔记)

&#x1f4d6; 前言&#xff1a;两台主机的通信&#xff0c;实际上两台主机中的应用进程进行通信&#xff0c;而在一台计算机中&#xff0c;用不同的端口号标识不同的应用进程。本节将介绍传输层的相关内容&#xff0c;包括端口号的分配方法、端口号的复用与分用、以及传输层的…

编译tolua——3、以pbc为例子,添加第三方库

目录 1、编译工具和环境说明 2、基础编译tolua 3、以pbc为例子&#xff0c;添加第三方库 4、更新luaJit 大家好&#xff0c;我是阿赵。 之前分享过怎样正常编译基础版本的tolua。这次用添加pbc为例&#xff0c;看看怎样往tolua里面添加其他的第三方库。知道了方法之后&#xf…

本地项目托管到 Gitee

本地项目托管到 Gitee 1、创建远程仓库2、Git Bash Here第一步&#xff1a;初始化本地仓库 git init第二步&#xff1a;建立链接git remote add origin xxx第三步&#xff1a;将远程仓库中的文件推送至本地仓库中git pull --rebase origin master第四步&#xff1a;将本地项目放…

【利用AI让知识体系化】简要了解网络七层协议

文章目录 一、前言引言目的和意义 二、网络七层协议简介OSI参考模型七层协议分层结构和各层协议简介 三、物理层 - Layer 1物理层概述物理层的作用物理层标准和协议 四、数据链路层 - Layer 2数据链路层概述常见的协议 五、网络层 - Layer 3网络层概述网络层的作用IP地址的作用…

cool-admin框架后端使用-node版本,线上宝塔部署

版本6.x 宝塔新建一个文件夹和创建好数据库&#xff0c;记录账号和密码&#xff0c;自行创建&#xff0c;不做说明 特别注意&#xff0c;如果用宝塔node管理那里运行&#xff0c;如果按照到有pm2的&#xff0c;要先卸载&#xff0c;不可以共存&#xff0c;会有冲突 cool-vue前端…

爬虫数据采集需要什么样的代理ip以及遇到的反爬措施

随着互联网的快速发展&#xff0c;数据已经成为许多行业中的重要资源。网络爬虫作为一种数据采集工具&#xff0c;在许多领域中得到了广泛应用。但是现在很多网站都有非常多的限制&#xff0c;所以在爬取数据的时候&#xff0c;还需要借助代理ip来助力&#xff0c;才能更好的完…

谁说不可兼得,用scrcpy实现手机免流播放bilibili投屏电脑

目前的手机大额流量卡都是支持设备免流的&#xff0c;但是如何将这个流量用在其他设备&#xff0c;就相当麻烦。于是我查找了些相关Android投屏技术资料&#xff0c;发现了一个简单的USB投屏工具——scrcpy。 安装说明 Office&#xff1a;https://github.com/Genymobile/scrcp…

深度学习之卷积神经网络(CNN)

大家好&#xff0c;我是带我去滑雪&#xff01; 卷积神经网络&#xff08;Convolutional Neural Network&#xff0c;CNN&#xff09;是一种基于深度学习的前馈神经网络&#xff0c;主要用于图像和视频识别、分类、分割和标注等计算机视觉任务。它主要由卷积层、池化层、全连接…

手机技巧:安卓微信 8.0.38 内测版本功能一览

2023年6月14号安卓版本的微信8.0.38又开始内测了&#xff0c;今天就赶紧下载体验一下&#xff0c;下面就来给大家一一介绍&#xff0c;本次安卓微信内测版本功能更新&#xff0c;感兴趣的朋友可以文末下载体验一下&#xff01; 首先看一下官方的更新内容&#xff1a; 本次更新…

网络安全实验室|网络信息安全攻防学习平台(脚本关1-6)

传送门&#xff1a; http://hackinglab.cn/ 1. key又又不见了 点击此处开启抓包&#xff0c;send ti repeater 模块 yougotit_script_now2. 快速口算 脚本来源&#xff1a; https://blog.csdn.net/hzxtjx/article/details/125692349 import requests,re# 自动处理cookies&a…

Java+Swing+mysql仿QQ聊天工具

JavaSwingmysql仿QQ聊天工具 一、系统介绍二、功能展示1.用户登陆2.好友列表3.好友聊天4.服务器日志 三、系统实现四、其它1.其他系统实现2.获取源码 一、系统介绍 系统主要功能&#xff1a;用户登陆、好友列表、好友聊天、服务器日志 二、功能展示 1.用户登陆 2.好友列表 3…

Ubuntu远程装载硬盘Mount and unmount disk

小虎本来以为Ubuntu&#xff08;Linux系统&#xff09;不能够远程装载硬盘&#xff0c;每次重开机都要线下重新装载硬盘。但是苦于工作站不在身边&#xff0c;跑来跑去太麻烦&#xff0c;所以想远程装载一下。 解决方法 遍历搜索所有硬盘。找到对应名字。 lsblk创建一个文件…

Unity中Camera参数—Culling Mask详解

Culling Mask 如下图所示&#xff1a; 显示层级如下&#xff1a; 应用&#xff1a; Culling Mask &#xff1a;主要是相机针对不同层级的物体进行渲染的操作&#xff08;想让相机渲染哪个层就勾选哪个层&#xff09; 层级介绍&#xff1a; unity中的层前7个被unity锁定&#…

RISC-V体系结构的U-Boot引导过程 第一阶段

RISC-V体系结构的U-Boot引导过程 第一阶段 flyfish .globl _start _start:.globl使符号对链接器可见相当于C语言中的Extern&#xff0c;声明此变量&#xff0c;并且告诉链接器此变量是全局变量&#xff0c;外部可以访问.u-boot.lds里的ENTRY(_start)也是这里的_start。 即指定…

儿童遗留监测成为「加分项」,多种技术路线「争夺战」一触即发

儿童遗留密闭车内&#xff0c;温度可以在短短15分钟内达到临界水平&#xff0c;从而可能导致中暑和死亡&#xff0c;尤其是当汽车在太阳底下暴晒。 按照Euro NCAP给出的指引&#xff0c;与车祸相比&#xff0c;儿童因车辆中暑而死亡的情况较少&#xff0c;但却是完全可以避免的…

基于改进MRAS算法的永磁同步电机参数辨识

基于改进MRAS算法的永磁同步电机参数辨识 摘 要永磁同步点电机参数辨识算法介绍永磁同步电机数学模型改进MRAS参数辨识算法递推最小二乘法辨识原理递推最小二乘法结合MRAS算法原理仿真结果分析总结 摘 要 在永磁同步电机运行时&#xff0c;电机的电气参数会受到温度以及磁链饱…

【使用指导】wifi蓝牙二合一模块LCS2028与服务器的数据收发功能测试指导

在物联网智能家居、智能照明、智能楼宇、智慧工厂、智能制造等领域的数据透传、智能控制应用中&#xff0c;支持UART串口通信的低功耗WiFi蓝牙二合一模块应用极为广泛。模块性能测试环节中会测试模块与服务器的数据收发功能&#xff0c;确保功能性能够满足项目应用需求。本篇就…