操作系统 真象还原 读书笔记
文章目录
- 环境配置
- 1、虚拟机virtualBox和centos
- 2、最小化虚拟机安装后需要配置的基本软件
- 2、1虚拟机连网
- 2.2 虚拟机软件安装
- 3、共享文件设置
- 3.1安装virtualBox增强工具
- 3.2挂载文件
- 4、bochs安装使用
- 1 实模式下内存布局及BIOS
- bios(base input output system)干了什么事情?
- 2 mbr与loader引导程序
- loader 创建全局描述符表进入保护模式
- loader创建页表进行内存分页管理(虚拟地址核心)
- loader中扫描内存大小 加载内核文件 进行内核文件映象的创建 执行内核文件
- 3 计算机开机过程总结
- 计算机上电
- 执行 bios
- 执行mbr
- 执行loader进入内核程序(操作系统)
- 补充计算机特权级的知识
- 4函数调用的约定
- 4.1 汇编代码和C语言调用
- 5 中断机制
- 中断的分类
- 中断描述符表
- 可编程中断芯片
- 6 内存管理
- 7 线程
- 7.1多线程机制
- 8 锁机制
环境配置
1、虚拟机virtualBox和centos
下载virtualBox 安装centos 这个比较简单,但是安装centos可以选择安装完整版也可以选择安装最小版,安装最小版就需要补充安装其他包
2、最小化虚拟机安装后需要配置的基本软件
2、1虚拟机连网
首先在virtualBox中将网络设置为 NAT
然后到虚拟机中修改虚拟机的网络脚本文件,主要就是将存在于/etc/sysconfig/network-scripts/ifcfg-enp0s3中的ONBOOT改为yes就可以了,不需要其他设置,之前重启虚拟机就可以联网了
可以尝试拼一下百度网站
2.2 虚拟机软件安装
常用软件安装
yum groupinstall "Development Tools" //gcc, gcc-c++等常用软件都会装上gcc –v //正常则会显示gcc 版本
[root@localhost ~]# yum -y install vim*
[root@localhost ~]# yum install ncurses-devel zlib-devel texinfo gtk2-devel qt-devel tcl-devel tk-devel kernel-headers kernel-devel //不装则bochs编译时会出错
[root@localhost ~]# yum install gtk* //前一行的gtk2-dvel已经安装,此行可不执行
[root@localhost ~]# yum install build-essential nasm
图形化软件安装
因为bochs需要在图形界面下才能正常运行,所以需要安装X Windows和Gnome
[root@localhost ~]# yum grouplist |more //察看Gnome安装包的名称
[root@localhost ~]# yum groupinstall "X Window System" // 安装基本的X系统组件
[root@localhost ~]# yum groupinstall "Gnome Desktop " //这一行根据第一行代码查出来的名称确定
[root@localhost ~]# startx //进入Gnome
3、共享文件设置
3.1安装virtualBox增强工具
选择安装曾强工具,虚拟机中会出现一个新的DVD盘,
进入这个vbox中在命令行用
sh ./VBoxLinuxAdditions.run //执行这个工具的安装
第一次安装可能会保存有kernerl headers没有安装,根据提示用yum将缺少的软件包安装后重启,再重新用上面的命令安装增强工具
3.2挂载文件
增强工具安装成功后
在设备中设置共享文件夹就可以了
然后虚拟机中就会出现一个新的文件夹
4、bochs安装使用
第一下载bochs文件,这本书使用的是bochs2.6.2 在bochs官网就可以直接下载,下载tar.gz版本然后解压
利用,进入解压目录设置配置文件
./configure \
--prefix=/root/learnOperaSys/bochs262G \ //这个是bochs软件最终安装的目录
--enable-debugger \
--enable-disasm \
--enable-iodebug \
--enable-x86-debugger \
--with-x \
--with-x11
执行完这一个configure命令之后。会生成一个makefile文件,这个时候需要打开makefile文件,在第92行中加上-lpthread 库
然后执行make 在执行make install
执行完make install
会在configure中指定的目录下生成bochs可执行文件
在安装目录根据书上教程添加bochsrc文件hd60M.img文件 mbr.bin等文件可以测试bochs是否正常,但是bochs报错不会弹出书中的对话框
bochsrc.disk中内容
megs:32
romimage:file=/root/learnOperaSys/bochs262G/share/bochs/BIOS-bochs-latest
vgaromimage:file=/root/learnOperaSys/bochs262G/share/bochs/VGABIOS-lgpl-latest
boot:disk
log:bochs.out
mouse:enabled=0
keyboard_mapping:enabled=1,map=/root/learnOperaSys/bochs262G/share/bochs/keymaps/x11-pc-us.map
ata0:enabled=1,ioaddr1=0x1f0,ioaddr2=0x3f0,irq=14
ata0-master: type=disk, path="hd60M.img", mode=flat, cylinders=121, heads=16, spt=63
注意按下C仿真程序才会执行
1 实模式下内存布局及BIOS
书中采用intel8086系列讲解,实模式下内存大小为1MB,分为ROM(只读内存)和RAM(随机存储)。BIOS存在于ROM中,并且所处的位置也是固定的在F000-fffff中,但是计算机开机最开始cs:ip指令指向的确实F0000:FFFF0,是因为这一行存储的是一个跳转指令,程序会跳转到bios中的起点出,为什么这么设计呢?我觉得就是因为这个地址设计是靠硬件设计的,不好改,但是bios的大小可能会变,所以bios的起始地址可能会变,所以需要用一条跳转指令来间接的确定bios的起始地址。
bios(base input output system)干了什么事情?
第1件事情: 检测基本硬件
第2件事情: 初始化中断向量表,中断向量表存在最低地址处,中断向量表指向的中断程序存在于bios中
第3键事情最重要: 加载mbr引导程序,(这个是一个基础引导程序,(会引导loader加载器程序)),并且跳转执行这个引导程序,加载mbr的时候就把它加载到0x7000这个位置,跳转页跳转到这个位置执行程序。
2 mbr与loader引导程序
mbr最主要的工作就是加载loader引导程序,loader程序做了很多工作,
loader 创建全局描述符表进入保护模式
其中最关键之一就是将系统从实模式转变为了保护模式。
实模式转变为保护模式中起到关键作用的就是全局描述符表GDT(存在去内存中),全局描述符表中记录的是段描述符,段描述符中记录了一个段的属性(这是保护模式的精髓):有段基址,内存段类型,段界限,特权级,段是否存在于内存中。也就是说访问一个地址时,需要通过这个全局描述符表找到对应的段。怎么找段描述符呢?这个时候段寄存器中存着的就是选择子(选择子中0-1位表示特权级(将这里的特权级和段描述符中的特权级比较就可以实现一个权限等级的保护) 第2位表示在全局描述符表还是局部描述符表中查找段描述符),通过选择子作为索引在全局描述符表中查找段描述符。全局描述符表通过全局描述符表指针GDTR找到,GDTR通过lgdt指令完成初始化,lgdt可以在实模式和保护模式实用。
进入保护模式还需要其他工作配合:比如打开控制寄存器CR0的PE标志位,汇编程序中用bit[32]来标记。
loader创建页表进行内存分页管理(虚拟地址核心)
首先页式管理和段式管理的不同在于,段式管理是将执行文件分成不同的段,但是每一个段中地址必须是连续的,在物理地址上和逻辑地址都是相同的,但是页式管理实现了逻辑地址式连续的但是物理地址是不连续的,程序执行的时候首先是获取了逻辑地址(线性地址),经过页部件的转化为物理地址后,给相应的寄存器去寻址。具体来说:分页就是将段按照4kb大小来进行分页,然后每一个逻辑页对应一个物理页。当每次获取一个逻辑地址(32位),前面20位相当于页索引,后面12位相当于页内偏移。这20位索引又可以分为两个10位的索引,形成页目录和页表两级索引。页表项中内容:4字节:20位页地址,12位属性。
loader中扫描内存大小 加载内核文件 进行内核文件映象的创建 执行内核文件
loader程序首相创建全局描述符表,进入保护模式,然后检查系统最大内存,将内核文件加载到内存中,创建页表,进入分页模式,将内核文件按照编译地址完成内核映射,形成内核映像,然后跳转到内核映像中执行内核内容。
在这本书中当编译内核文件时需要修改一下编译命令,不然gcc编译出来的时elf64的头文件而不是elf32的头文件
gcc -m32 -c -o main.o main.c
ld -m elf_i386 main.o -Ttext 0xc0001500 -e main -o kernel.bin
3 计算机开机过程总结
计算机上电
计算机上电后,cpu的指令地址寄存器被初始化为0xF000:0xFFF0,这个地址指向一段物理内存区域(ROM区域),然后获取一个跳转指令转到bios代码的执行处,执行bios代码,完成硬件自检的任务。注意这一段代码载rom中,只可读不可改。
执行 bios
bios执行最后会从磁盘(硬盘)中加载主引导程序MBR,
执行mbr
MBR主要用来初始化CPU各种寄存器的值,然后从硬盘中读取loader内核加载程序。
执行loader进入内核程序(操作系统)
内核加载程序需要完成比较多的事情,最主要的是内核加载程序中实现了从实模式到保护模式的变换,以及虚拟地址的使用。在加载器中需要初始化全部描述符表GDT,全局描述符表主要用来在虚拟地址中通过选择子(段寄存器中的内容)查找段基址,以及通过描述段的属性,来判定命令是否违规,这里涉及到特权级的表示。加载器完成了这些负载工作后就可以加载真正的内核程序了,加载内核程序后创建页表 ,开启分页管理模式,完成内核映像,进入内核程序执行。
补充计算机特权级的知识
计算机中将程序按照权限分为不同的级别0 1 2 3四个级别,级别数子越小权限越大。每一个段描述符中都有一个权限描述(DPL),然后访问者也就是段寄存器中的属性(除了选择器,还有一个CPL访问者权限),只有CPL <= DPL访问才可以进行。程序的执行的权限可以改变,通过各种门结构。比如用户程序变为内核程序的时候CPL就会改变。
除了CPL DPL还有RPL,就是用户程序的请求指令通过门变换为内核程序等更高权限的指令时候,用RPL来记录这条指令真正的背后发起者所拥有的权限。
权限检查发生在利用选择子去全局描述符表中查找段的时候。
4函数调用的约定
函数调用的核心就是参数传递,CS:IP地址指针的保存。参数传递利用栈来实现,参数就是压栈,调用者先把参数按照某个顺序(从右到左)压栈,然后被调用者按照顺序取出参数。最后由调用者或者被调用者重置栈指针的值(相当于清空栈)。
4.1 汇编代码和C语言调用
因为C代码也会被编译成汇编代码,所以C代码可以和汇编代码相互调用,只要遵守相当的调用约定。
5 中断机制
中断的分类
可以分为内中断和外中断,内中断是由内部软件驱动了,外中断是由硬件驱动
中断是否可屏蔽,有的中断不可屏蔽(比如外部断电等紧急外中断,运行时错误等内部中断),有的中断可屏蔽。
中断描述符表
中断描述符表中的每一条数据是八个字节,记录了中断处理程序的地址以及其他属性,中断发生时通过中断描述符表找到对应的中断处理程序进行处理。
可编程中断芯片
给外设用的,用于将外部中断统一管理,可编程体现在中断向量号可以分配,优先级等其他属性可以设置。
6 内存管理
内存管理真正管理的是物理内存,内存管理是通过位图来管理的,用一位来管理4kb的内存(bitmap)。具体来说,将内存分为物理内核内存区,物理用户内存区,虚拟内核内存区,虚拟用户内存区。内存管理就是当发现虚拟地址所表示的空间不在物理内存中,就要向操作系统申请空间,分配内存。
7 线程
进程是一个程序执行的完整描述,包含完整的地址空间,完整的资源控制。线程只是一段执行流,包含执行代码段以及执行的上下文环境(寄存器环境)。一个进程中可以有多个线程,多个线程共享进程的资源(锁机制),
7.1多线程机制
多线程机制的核心在于需要线程表(记录所有线程,这个线程表可以是链表),一个调度器,适时的调度不同的线程上处理器,并且为线程的调度创建或者保护上下文环境。
多线程可以在用户级实现,比如C++中提供的poxis多线程机制,也可以在内核级实现。用户级实现的多线程在操作系统层面不可见,操作系统依然以为只是一个进程一个线程在运行,但是内核级的多线程机制,在操作系统层面也对应多个任务,这样同一个进程就可以占用更多的处理器资源。
操作系统层面的多线程需要借助PCB这种进程线程的的文件格式进行管理。
在操作系统中线程切换需要三步:时钟中断处理,调度器调度,任务切换函数。
8 锁机制
加锁释放锁本质上也是很多操作的集合,怎么保证加锁释放锁的原子性呢?这就是通过关中断实现锁操作的原子性(所以开关中断是实现锁的最底层技术)。
临界区:多线程进程对共享资源的竞争代码
阻塞是一个线程或者进程的主动行为,自己将自己移动到阻塞队列中
唤醒:是当前线程将锁上等待的其他线程从阻塞队列中救出来放到就绪队列首部
操作系统 真象还原 读书笔记相关推荐
- [操作系统] 操作系统真相还原读书笔记三:MBR加载loader到内存并跳转到loader执行
为什么要有loader程序? 通过操作系统真相还原读书笔记二:编写MBR主引导记录我们已经能够正常运行MBR主引导记录(有些书籍也叫做boot)程序了,但该程序什么也没做.我们的MBR 受限于 512 ...
- [操作系统真象还原3]cpu的8086实模式、显卡、硬盘
本文为读书笔记,是对书中自己认为重要的点进行简要摘录和总结,如需要更进一步了解,还是推荐看原书,作者讲的非常详细. 原书:郑钢 操作系统真象还原 文章目录 1:cpu8086实模式 1.1:cpu工作 ...
- 《操作系统真象还原》——0.7 内存访问为什么要分段
本节书摘来自异步社区<操作系统真象还原>一书中的第0章,第0.7节,作者:郑钢著,更多章节内容可以访问云栖社区"异步社区"公众号查看 0.7 内存访问为什么要分段 按理 ...
- 《操作系统真象还原》——0.23 操作系统是如何识别文件系统的
本节书摘来自异步社区<操作系统真象还原>一书中的第0章,第0.23节,作者:郑钢著,更多章节内容可以访问云栖社区"异步社区"公众号查看 0.23 操作系统是如何识别文件 ...
- 《操作系统真象还原》第九章 ---- 终进入线程动斧开刀 豁然开朗拨云见日 还需解决同步机制才能长舒气
文章目录 专栏博客链接 相关查阅博客链接 本书中错误勘误 进程 线程的自我小理解 线程 进程的状态 内核级线程 & 用户级线程 初步实现内核级线程 浪费两三个小时调试的辛酸史 编写thread ...
- 《操作系统真象还原》第十四章 ---- 实现文件系统 任务繁多 饭得一口口吃路得一步步走啊(上一)
文章目录 专栏博客链接 相关查阅博客链接 本书中错误勘误 部分缩写熟知 闲聊时刻 实现文件系统的原理 inode构建原理 目录构建原理 超级块构建思路 创建文件系统 编写完的super_block.h ...
- 《操作系统真象还原》第十四章 ---- 实现文件系统 任务繁多 饭得一口口吃路得一步步走啊(上二)
文章目录 专栏博客链接 相关查阅博客链接 本书中错误勘误 闲聊时刻 部分缩写熟知 实现文件描述符的原理 文件描述符的介绍 文件描述符与inode的介绍 文件描述符与PCB的描述符数组的介绍 实现文件操 ...
- 《操作系统真象还原》第十三章 ---- 编写硬盘驱动软件 行百里者半九十终成时喜悦溢于言表
文章目录 专栏博客链接 相关查阅博客链接 本书中错误勘误 部分缩写熟知 闲聊时刻 提前需要准备编写的函数 实现printk 实现sprintf函数 创建从盘 创建从盘的步骤 修改后的bochsrc.d ...
- 《操作系统真象还原》第十四章 ---- 实现文件系统 任务繁多 饭得一口口吃路得一步步走啊(总结篇)
文章目录 专栏博客链接 闲聊时刻 第十四章代码总览 编写完的fs.c(fs/fs.c) 编写完的fs.h(fs/fs.h) 编写完的dir.c(fs/dir.c) 编写完的dir.h(fs/dir.h ...
最新文章
- Django之路——6 Django的模型层(一)
- vue click事件冒泡,默认行为
- 修建道路 贪心,思维(女赛)
- latex中算法命令_比较Java 8中的命令式和功能性算法
- 2018华工计算机应用基础作业,计算机应用基础平时作业2019
- 软件测试几个概念 --dev sit uat
- canvas 判断哪个元素被点击_监听 Canvas 内部元素点击事件的三种方法
- Flex 4 NativeWindow 中添加Flex组件(问题很多,尚不完善)
- idea mvn命令
- 图解 Python 编程(6) | 条件控制与if语句(附要点速查表·完结)
- Excel实战之单元格合并与拆分
- Springboot中temlates和static
- JFreeChart常用图表使用
- 众智日照服务器无响应,众智日照分析常见问题解释
- 基于三星ARM9(S3C2410)的交通违章抓拍系统的开发
- 没错,Linux需要更多的憎恨者
- Logstash Grok详解
- Java太密来福_这篇文章就是要让你入门java多线程【多线程入门】-Go语言中文社区...
- DTW 算法的实时语音识别——命令词识别(Python 实现)
- Kali aircrack-ng 暴破wifi