Linux操作系统学习——启动

这篇具有很好参考价值的文章主要介绍了Linux操作系统学习——启动。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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等,结构如下图。

Linux操作系统学习——启动

 整个流程如下:

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号进程的整个过程。

欢迎转发点赞评论,感谢!文章来源地址https://www.toymoban.com/news/detail-486279.html

到了这里,关于Linux操作系统学习——启动的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 深入学习 Linux 操作系统的存储 IO 堆栈

    当使用 read() 和 write() 系统调用向内核提交读写 I/O 请求操作时需要经历的步骤: 1)首先,请求经过虚拟文件系统,虚拟文件系统提供了统一的文件和文件系统的相关接口,屏蔽了不同文件系统的差异和操作细节; 2)其次,适配当前磁盘分区的文件系统,常见文件系统有

    2024年02月08日
    浏览(38)
  • win11启动“适用于Linux的windows的子系统“多次无法打开,重启电脑时总是撤销操作的可能解决方法

    【若本文对您有用请让作者知晓( •̀ ω •́ )y ,如若有疑问可于评论区留言】  目录 前言: 我的问题: 解决方法: 以下是一些具体情况、可能解决方法及原理 避免VMware和WSL的冲突 避免VMware和Hyper-V的冲突 禁用“Accelerate 3D graphics”选项 禁用步骤 卸载VMware 如果卸载完后还

    2024年02月20日
    浏览(68)
  • 【Linux操作系统】多线程抢票逻辑——学习互斥量(锁)函数接口

    临界资源 : 多线程执行流共享的资源就叫做临界资源 。 临界区 :每个线程内部, 访问临界资源的代码,就叫做临界区 。 互斥 :任何时刻, 互斥保证有且只有一个执行流进入临界区,访问临界资源,通常对临界资源起保护作用 。 原子性 :不会被任何调度机制打断的操作

    2024年02月16日
    浏览(42)
  • 安装Linux-CentOS7.9操作系统虚拟机环境(适用于学习、测试环境)

    具体名称以及路径根据自己的实际情况在个人pc或者其他的设备上进行创建。 阿里云开源镜像站地址 https://developer.aliyun.com/mirror/ 清华大学开源镜像站地址 https://mirrors.tuna.tsinghua.edu.cn/ 有需要的朋友可以自行下载 VMware Workstation pro下载链接,许可证可自行浏览器搜索获取 http

    2024年02月03日
    浏览(46)
  • 从零学习Linux操作系统 第二十二部分 企业域名解析服务的部署及安全优化

    关于dns的名词解释:dns: domain name service(域名解析服务) 关于客户端: /etc/resolv.conf dns指向文件 A记录 ##ip地址叫做域名的Address 记录 SOA ##授权起始主机 关于服务端 bind 安装包 named 服务名称 /etc/named.conf 主配置文件 /var/named 数据目录 端口 53 关于报错信息: 1.no servers could be reach

    2024年02月22日
    浏览(45)
  • 探索操作系统:内核、启动和系统调用的奥秘

    首先,对于有科班背景的读者,可以跳过本系列文章。这些文章的主要目的是通过简单易懂的汇总,帮助非科班出身的读者理解底层知识,进一步了解为什么在面试中会涉及这些底层问题。否则,某些概念将始终无法理解。这些计算机基础文章将为你打通知识的任督二脉,祝

    2024年02月11日
    浏览(56)
  • 操作系统权限维持(三)之Windows系统-启动项维持后门

    系列文章 操作系统权限维持(一)之Windows系统-粘贴键后门 操作系统权限维持(二)之Windows系统-克隆账号维持后门 启动项,操作系统在启动的时候,自动加载了很多程序。会在前台或者后台运行,进程表中出现了很多的进程。也许有病毒或木马在自启动行列。 添加启动项

    2023年04月09日
    浏览(51)
  • 【操作系统】半小时写一个微型操作系统-写一个启动扇区并且导入到软盘镜像中

            我们使用软盘来启动操作系统时,系统首先就是从软盘的第一个扇区中开始读取数据,也就是第0面,0磁道的第0个扇区,软盘的每个扇区为512个字节的大小,如果最后两个字节为0xaa55(当BIOS看到这两个字节时,就认为是引导扇区的结束标志),则代表该两个字节

    2023年04月15日
    浏览(67)
  • 如何在 Ubuntu 操作系统上重新启动 Nginx?

    Nginx 是一个常用的开源的高性能 Web 服务器和反向代理服务器。在使用 Nginx 时,有时需要重新启动该服务,以应用配置更改或解决某些问题。本文将详细介绍在 Ubuntu 操作系统上重新启动 Nginx 的不同方法和技巧。 systemctl 命令是在 Ubuntu 上管理系统服务的标准工具。要重新启动

    2024年02月07日
    浏览(46)
  • 银河麒麟服务器操作系统设置网卡自启动

    操作环境:虚拟机 系统版本:Kylin-Server-10-SP2-x86-Release-Build09-20210524 问题现象 新安装的银河麒麟服务器操作系统,开机网卡不自启动,需要手动点击一下,才能启动网卡 现象图如下所示 解决方案 注:网卡名需要提前确认好,可以点击网络图标查看自己使用的是哪块网卡,以

    2024年02月06日
    浏览(213)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包