解析操作系统是如何启动起来的?

操作系统被称为“第一个程序”,the first programme,原因很简单,只有当操作系统启动起来后才能运行我们编写的程序,那么你有没有想过这个问题:操作系统是怎样启动起来的呢?实际上这个过程就像发射火箭一样有趣,看完这篇你就明白啦。

操作系统也是普通程序

首先我们必须意识到这样两点:

  1. CPU执行的是机器指令,编译器将程序翻译后成了机器指令
  2. 操作系统本身也是一个程序,这个程序被编译后也会生成一大堆机器指令

现在我们知道了,操作系统本身其实也是一大堆机器指令,既然是机器指令那么它必须得存放在什么地方。存放在哪里呢?想想我们编写的程序,编译后生成的是可执行文件,也就是说是以“文件”的形式存放的,并且存放在硬盘上,而操作系统也没什么不同,编译后生成的机器指令同样是以文件的形式存放的,存放在哪里呢?可以存放在任何能存储数据的介质,像CD、磁盘之类都可以。

我们编写的程序在启动时被加载器——也就是loader,加载到内存,加载器也是一个程序,这是一个加载其它程序的程序;这么说可能有点拗口,但计算机系统中有大量类似的程序,编译器是一个翻译程序的程序、操作系统是一个运行其它程序的程序、链接器是一个链接程序的程序、解释器是一个执行脚本程序的程序等等。

鸡生蛋蛋生鸡的问题

回到我们的主题,我们写的代码是loader加载到内存后运行的,那么操作系统这个程序是也同样的道理,必须得有个什么东西也要把操作系统加载到内存中运行才可以,这个东西不叫loader,而是叫boot loader,其本身也是一个程序,它的任务就是加载一个更大的程序,就像这里的操作系统。

此时这里会出现一个鸡生蛋蛋生鸡的,既然我们的程序是被加载器loader(操作系统的一部分)加载到内存中,而操作系统又是被boot loader这个加载程序加载到内存中的,那么又是什么加载器把boot loader这个加载程序加载到内存中呢?而又又是什么加载器把上一句中的什么加载器加载内存中呢?而又又又是什么。。?

你会发现这个一个没有出口的无穷递归啊有没有,总得有个什么把前一个程序加载到内存,就好比今天的前一天是昨天、昨天的前一天是前天、前天的前一天是大前天,如果一直这样思考下去那么时间到底在哪里开始的呢?时间到底有没有开始(参考时间简史或相对论)?

时间有没有开始这个问题我不清楚,但操作系统启动的这个问题我知道。上述关于加载器以及加载加载器等问题全部指向了内存,让我们好好想一想内存有什么特殊性?

内存断电后是无法保存数据

程序员都知道内存只有在加电的情况下才可以保存数据,那么很显然,当断电后内存中的内容就丢失了,那么又很显然的,当你在按下计算机开关通电时,内存中的内容是未被初始化的,也就是说内存中的内容是无效的,此时的内存里还是一片荒芜,这里没有任何东西可供CPU来执行,这就好比大爆炸之前的宇宙。

但我们的计算机总是能启动起来,CPU必须得执行“一段什么程序”把第一个boot loader加载到内存中,由于此时内存中还什么都没有,那么这段程序一定被保存在了其它地方。保存在了哪里呢?没错,这段程序就被保存在了BIOS的非易失性存储ROM或者flash存储中了,这里的代码在即使断电后也会保存下来,加电后CPU开始执行这里代码,把boot loader加载到内存中,现在你应该明白第一个boot loader是怎样被加载到内存的了吧。

在早期的计算机上甚至专门有一个按钮,让用户自己选择该从哪里,比如打孔纸带、打孔卡片或者硬盘,加载一个更复杂的程序来运行,操作面板上的旋钮可以控制把这些程序加载到内存的什么位置上去:

火箭与操作系统启动

然而现实情况比较复杂,我们刚才提到的boot loader这段小程序功能实在是太弱了,此时其能访问的磁盘地址空间有限,不能把完整的内核全部加载到操作系统中,该怎么办呢?既然boot loader比较弱那么就换一个比较牛的loader程序来,就这样出现了二阶boot loader,second stage loader:

二阶boot loader功能更为丰富,比如对硬件进行检查、给用户提供选项加载哪个操作系统等等,安装多系统的同学应该知道,启动时会给你一个选项到底是启动windows还是linux,这就是二阶boot loader的作用。

最终,操作系统被二阶boot loader加载到内存中开始运行。你会发现这个过程就和发射三级火箭一样,最初一级火箭启动,燃料用尽后二级火箭启动,二级火箭完成使命后三级火箭启动,最终把卫星送到太空,而计算机的启动过程也类似。

最初是CPU运行BIOS中的一段代码把一级boot loader加载到内存中运行,该程序又会把二级boot loader加载到内存运行,而二级boot loader又会把操作系统加载到内存中,此后控制权被转移到操作系统,(所谓控制权是指CPU跳转到操作系统的代码),操作系统开始运行,经过一系列的初始化,比如硬件检测、开启必要的后台进程等等,最终图形界面或者命令行界面呈现出来。

接下来我们把这个过程细化一下。

 资料直通车:Linux内核源码技术学习路线+视频教程内核源码

学习直通车:Linuxc/c++高级开发【直播公开课】

零声白金VIP体验卡:零声白金VIP体验卡(含基础架构/高性能存储/golang/QT/音视频/Linux内核)

更详细的启动过程

你在按下电源的瞬间相当于火箭点火,此时一级发动机开始工作。加电CPU重置后开始在地址0xffff0处开始执行指令,这个地址其实是BIOS ROM的末尾处,该位置其实是一个跳转指令,跳转到ROM的一段启动代码上,该代码会进行必要的自检,Power-on self-test (POST),展示BIOS启动界面等等,最重要的一步是找到启动设备,所谓启动设备就是指从哪里加载操作系统,比如CD-ROM、或者磁盘、甚至U盘等都可以作为启动设备,早些年流行用U盘重新安装系统,其实就是告诉BIOS的这段代码从U盘中加载操作系统。

通常BIOS会把磁盘当做启动设备(大部分情况下),此时BIOS中的这段代码开始将磁盘的第0号块加载到内存中,那么这第0号块中有什么呢?没错,就是第一阶段boot loader程序,这第0号块也被称之为Master Boot Record,MBR,肯定有不少同学听说过。

到这里,火箭的一级发动机燃料用尽,二级发动机开始点火,BIOS中的这段代码把控制权交给加载到内存boot loader,所谓控制权就是跳转到boot loader程序,这样CPU终于开始直接与内存交互了,CPU开始从内存中取出指令然后执行。

MBR中除了包含一段可执行代码之外还有一个分区表,partition table,这个表的中的每一个条目本质上在说:“操作系统是否在我这个分区,我这个分区有多大”,CPU在执行MBR中的代码时会去检查操作系统存在哪个分区中,定位后开始从相应分区的起始位置读取磁盘数据到内存中,这时的磁盘数据中保存的就是二阶boot loader,second-stage boot loader,此时一阶boot loader把控制权转交给二阶boot loader,火箭三级发动机开始工作。

2_boot loader的主要工作将操作系统加载到内存中,此后控制权转交给操作系统,火箭的三级发动机完成使命,到这一时刻,操作系统开始接管计算机,操作系统经过一系列自身的初始化后创建出若干必要进程,至此计算机启动完毕,卫星被成功送到了外太空中。

然而限于篇幅这里依然没有过多涉及细节,操作系统本身的初始化也是一个比较复杂的过程,感兴趣的同学可以去翻阅相关操作系统的资料。

总结与脑洞

计算机的启动是一个多阶段的过程,当然在一些嵌入式设备等这个过程会简化,但总体上也需要经过类似过程,只不过阶段数会少一些。回到最开始的那个问题,也就是时间有没有开始,其实这个问题一些物理大牛已经回答过了,但我很想在这里开一个脑洞,当上帝在为自己创建的宇宙(计算机)加电的那一刻——也就是宇宙大爆炸时,时间开始了,时间这个概念是和宇宙(计算机)相伴相生的,如果没有宇宙(计算机),时间这个概念其实是没有意义的,就好比如果没有计算机,加载这个概念其实是没有意义的,你思考时间到底有没有起点这个问题就好比计算机中的程序在思考到底是谁把自己加载到内存的、又是谁把操作系统加载到内存中的等等。。好啦,脑洞就开到这里。

原文作者:码农的荒岛求生

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

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

相关文章

kuboard如何部署redis?

在K8S上部署redis 如 在K8S上部署mysql 所述,auth-server、user-center、api-gateway 都需要使用 redis 服务,本文描述如何使用 Kuboard 在 Kubernetes 上部署 redis。 本文将使用 redis官方镜像 进行部署。 部署redis 在 Kuboard 界面进入名称空间 …

Leetcode—2477.到达首都的最少油耗【中等】

2023每日刷题&#xff08;五十&#xff09; Leetcode—2477.到达首都的最少油耗 算法思想 参考自灵茶山艾府 实现代码 class Solution { public:long long minimumFuelCost(vector<vector<int>>& roads, int seats) {int n roads.size() 1;vector<i…

iNet Network Scanner for Mac:简洁高效的WiFi网络扫描软件

随着无线网络的普及&#xff0c;WiFi网络已经成为我们日常生活中必不可少的一部分。无线网络的稳定性和速度对我们的工作和娱乐体验至关重要。因此&#xff0c;一款功能强大、简洁高效的WiFi网络扫描软件非常重要。今天&#xff0c;我们向大家推荐一款优秀的Mac平台WiFi网络扫描…

【软件测试】技术精选:Jmeter常见的几种报错

1、Java.net.UnknownHostException 这个错的含义是 没有连接到服务器地址&#xff0c;因此很可能是 内部网络中断导致。 2、502 Bad gateway 这个和本地的线程数无关 可能原因是网络抖动不稳定导致 3、java.net.SocketException: Socket closed 强制停止线程&#xff0c;连接…

Python绘图坐标轴数字要求三位分节的处理方法

比如说1000&#xff0c;用三位分节法的写法就是1 000&#xff0c;咱们操作的时候可以先式化字符串&#xff0c;用千位分隔符表示数字就是1,000&#xff0c;再把逗号换成空格。 import matplotlib.pyplot as plt import matplotlib.ticker as ticker# 示例数据 x [1000, 2000, …

vue 过滤器 (filters) ,实际开发中的使用

在实际开发中要判断不同的状态,要写很多重复的代码, 类似这样: 这样学麻烦, 不方便维护, 这时候可以用 filters 过滤器 在页面这样写就可以了

PET(Point-Query Quadtree for Crowd Counting, Localization, and More)

PET&#xff08;Point-Query Quadtree for Crowd Counting, Localization, and More&#xff09; 介绍实验记录训练阶段推断阶段 介绍 论文&#xff1a;Point-Query Quadtree for Crowd Counting, Localization, and More 实验记录 训练阶段 TODO 推断阶段 下面是以一张输…

4.8 构建onnx结构模型-Less

前言 构建onnx方式通常有两种&#xff1a; 1、通过代码转换成onnx结构&#xff0c;比如pytorch —> onnx 2、通过onnx 自定义结点&#xff0c;图&#xff0c;生成onnx结构 本文主要是简单学习和使用两种不同onnx结构&#xff0c; 下面以 Less 结点进行分析 方式 方法一&a…

Openfire CVE-2023-32315(metasploit版)

step1&#xff1a;用docker搭建环境 Step2&#xff1a;docker查看映射端口 Step3&#xff1a;打开mysql和apache2&#xff0c;访问特定端口&#xff0c;然后靶标应用。 Step4&#xff1a;用metasploit进行攻击&#xff1a; 首先&#xff0c;打开metasploit&#xff0c;然…

Python-条件判断(if语句详解)

条件判断 python代码执行从上到下&#xff0c;默认没有main函数 如果 否则 写法一&#xff1a;if if expression: do_something1 do_something2 ... next_something#一定会执行&#xff0c;和判断条件无关 if a > b:#执行语句1#执行语句2#执行语句3#... #执行语…

java第三十课

电商项目&#xff08;前台&#xff09;&#xff1a; 登录接口 注册接口后台&#xff1a; 注册审核&#xff1a;建一个线程类 注意程序中的一个问题。 这里是 5 条记录&#xff0c;2 条记录显示应该是 3 页&#xff0c;实际操作过程 有审核机制&#xff0c;出现了数据记录动态变…

【从删库到跑路 | MySQL数据库总结篇】JDBC编程

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【MySQL学习专栏】&#x1f388; 本专栏旨在分享学习MySQL的一点学习心得&#xff0c;欢迎大家在评论区讨论&#x1f48c; 目录 一、前言…

共建共创 | 紫光展锐-中国电信“终端测试与创新联合实验室”正式成立

近日&#xff0c;紫光展锐携手中国电信正式成立“终端测试与创新联合实验室”&#xff0c;这标志着紫光展锐在功能、协议、互操作性等测试方面的创新能力和持续发展能力获得认可&#xff0c;为进一步提升通信技术&#xff0c;助推终端厂商产品加速上市奠定了坚实的基础。 2023年…

网络之路26:STP生成树协议

正文共&#xff1a;2222 字 19 图&#xff0c;预估阅读时间&#xff1a;3 分钟 目录 网络之路第一章&#xff1a;Windows系统中的网络 0、序言 1、Windows系统中的网络1.1、桌面中的网卡1.2、命令行中的网卡1.3、路由表1.4、家用路由器 网络之路第二章&#xff1a;认识企业设备…

农产品加工行业分析:我国产业总产值共计7.17万亿元

农产品加工是用物理、化学和生物学的方法&#xff0c;将农业的主、副产品制成各种食品或其他用品的一种生产活动。是农产品由生产领域进入消费领域的一个重要环节。主要包括粮食加工、饲料加工、榨油、酿造、制糖、制茶、烤烟、纤维加工以及果品、蔬菜、畜产品、水产品等的加工…

Windows创建服务(.NET8)

windows服务 Windows服务是一种在Windows操作系统中运行的后台程序&#xff0c;用于在系统启动时启动并在系统关闭时关闭。这些服务可以是Microsoft自己的服务&#xff0c;也可以是第三方软件的服务。它们在后台运行&#xff0c;通常不需要交互式用户界面。 Windows服务通常用…

Windows(Microsoft)win电脑装Xcode方法

你想在你的Windows电脑上体验和使用苹果的Xcode进行应用打包。遗憾的是&#xff0c;Xcode官方只支持macOS操作系统&#xff0c;但别担心&#xff0c;我们有替代方案可以让你在Windows环境下进行iOS应用的开发和打包。接下来我将指导你如何实现这一目标。 图片来源&#xff1a;W…

Linux中的网络配置

本章主要介绍网络配置的方法 网络基础知识查看网络信息图形化界面修改通过配置文件修改 1.1 网络基础知识 一台主机需要配置必要的网络信息&#xff0c;才可以连接到互联网。需要的配置网络信息包括IP、 子网掩码、网关和 DNS 1.1.1 IP地址 在计算机中对IP的标记使用的是3…

协议栈的内部结构

上层会向下层逐层委派工作。 最上面的部分是网络应用程序&#xff0c;它们会将收发数据等工作委派给下层的部分来完成。尽管不同的应用程序收发的数据内容不同&#xff0c;但收发数据的操作是共通的。 应用程序的下面是Socket库&#xff0c;其中包括解析器&#xff0c;解析器…

Java画爱心

Java画爱心代码&#xff0c;每个人都可以被需要 效果图 源代码 package com.example.test; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Image; import java.awt.Toolkit; import javax.swing.JFrame; class Cardioid extend…