8086内存地址变换过程

80x86在从逻辑地址到物理地址变换过程中使用了分段和分页二种机制。

第一阶段使用分段机制将程序的逻辑地址变换成可寻址内存空间的线性地址。

第二阶段用分页机制把线性地址转换成物理地址。

所以可以表示为,这个函数的嵌套关系不能改变。

二级页表的第一级为页目录 ,第二级为页表。

所有的努力最终都指向了进程空间切换。

CS:IP

指令是有长度的,一条指令是由多个字节构成的。指令的执行过程如下:

  • CPU从CS:IP所指向的内存单元读取指令,存放到指令缓冲器中

  • IP = IP + 1,从而指向下一条指令

  • 执行指令缓存器中的内容。回到第一步

需要注意的是,汇编语言没有提供直接修改CS/IP寄存器的指令。换言之,禁止通过MOV指令对CS/IP进行赋值。但是它是通过JMP跳转指令,来实现对CS/IP寄存器内容的修改

IDT

在实模式下,内存最开始的1K字节存储中断向量表。每个表项都有4个字节,前两个字节表示中断服务程序的段基址,后两个字节表示偏移量。

在保护模式下,中断向量表中的表项由8个字节组成,中断向量表也改称中断描述符表(Interrupt Descriptor Table);其中的每个表项称为一个门描述符。

同时,在保护模式下,中断描述符表也不需要在地址为0的地方开始,可以常驻于内存的任何地方。

为查询IDT的起始地址,在CPU中专门设置了一个IDTR——中断描述符表寄存器。

内核在启用中断机制之前,必须把IDT表的起始地址载入IDTR寄存器,并初始化表中的每一个表项。

IDT被初始化两次。第一次是在BIOS程序中,此时CPU还运行在实模式下,IDT被初始化并由bootloader程序使用。

一旦操作系统启动,IDT会被搬运到RAM的受保护区域并被第二次初始化。

各个寄存器的关系为

IDTR(中断寄存器:时间片中断)->TR(任务寄存器)->GDTR(全局段寄存器)->LDTR(局部段寄存器)->CR3(内存分页)

时间片中断一旦开启,操作系统就尘埃落定,各就各位。

时间中断IRQ0

时钟中断 是指每隔一段相同的时间,都会发出一个中断信号(称为一个tick), CPU接受到中断信号后触发内核中相应的中断处理程序。

当 时钟中断 发生时会调用 timer_interrupt() 函数来处理中断,timer_interrupt() 函数源码如下

static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
int count;
write_lock(&xtime_lock);
...
do_timer_interrupt(irq, NULL, regs);
write_unlock(&xtime_lock);
}
static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
...
do_timer(regs);
...
if ((time_status & STA_UNSYNC) == 0 &&
xtime.tv_sec > last_rtc_update + 660 &&
xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 &&xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) {
if (set_rtc_mmss(xtime.tv_sec) == 0)
last_rtc_update = xtime.tv_sec;
else
last_rtc_update = xtime.tv_sec - 600;
}
...
}

cli()与sti()

根据Linux官方文档https://github.com/pengdonglin137/Linux-2.6.11/blob/master/Documentation/cli-sti-removal.txthttps://github.com/pengdonglin137/Linux-2.6.11/blob/master/Documentation/cli-sti-removal.txt

as of 2.5.28, five popular macros have been removed on SMP, and
are being phased out on UP:cli(), sti(), save_flags(flags), save_flags_cli(flags), restore_flags(flags)until now it was possible to protect driver code against interrupt
handlers via a cli(), but from now on other, more lightweight methods
have to be used for synchronization, such as spinlocks or semaphores.

在Linux 2.5.28版本之后,cli()和sti()两个之前版本中常用的关中断和开中断命令将被移除。

取而代之的是自旋锁和信号量等更加轻量级的同步机制。

drivers that want to disable local interrupts (interrupts on the
current CPU), can use the following five macros:local_irq_disable(), local_irq_enable(), local_save_flags(flags),local_irq_save(flags), local_irq_restore(flags)but beware, their meaning and semantics are much simpler, far from
that of the old cli(), sti(), save_flags(flags) and restore_flags(flags)
SMP meaning:local_irq_disable()       => turn local IRQs offlocal_irq_enable()        => turn local IRQs onlocal_save_flags(flags)   => save the current IRQ state into flags. Thestate can be on or off. (on somearchitectures there's even more bits in it.)local_irq_save(flags)     => save the current IRQ state into flags anddisable interrupts.local_irq_restore(flags)  => restore the IRQ state from flags.(local_irq_save can save both irqs on and irqs off state, and
local_irq_restore can restore into both irqs on and irqs off state.)

这些函数在src/Linux/init/main.c中的start_kernel()函数中调用。

asmlinkage __visible void __init __no_sanitize_address start_kernel(void)
{char *command_line;char *after_dashes;set_task_stack_end_magic(&init_task);smp_setup_processor_id();debug_objects_early_init();cgroup_init_early();local_irq_disable();early_boot_irqs_disabled = true;......early_boot_irqs_disabled = false;local_irq_enable();
}

多扇区代码加载

由于只有第一扇区是通过硬件中断复制进内存,最后两个字节为0x55aa。其他之后的各个扇区均无此要求。因此可以将第一扇区用于加载后续扇区。后面所有的功能在之后进行设计。

以下是最简代码。

; ==========================================
; pmtest1.asm
; 编译方法:nasm pmtest.asm -o pmtest.bin
; ==========================================
;--------------------------------------------------------------------------------------
;--------------------------------------------------------------------------------------
org 07c00hjmp   LABEL_BEGIN
;--------------------------------------------------------------------------------------
;--------------------------------------------------------------------------------------
[SECTION .s16]
[BITS   16]
LABEL_BEGIN:xor ax,ax      ; 为 DS 置 0 准备mov ds,axmov ah, 0x02;al=1 load sec2;al=2 load sec2-3;al=3 load sec2-4mov al, 2mov ch, 0mov cl, 2mov dh, 0mov bx, sect2mov es, bxxor bx, bxint 0x13jmp sect2:0
data:sect2 equ 0x0500
times   506-($-$$) db 0
dw      0xaa55
;--------------------------------------------------------------------------------------
;--------------------------------------------------------------------------------------
;sect2:mov ax, csmov ds, ax    ; 设置 CS=DS. CS=0x0500, 因此 DS=0x500; 如果变量已经在代码中设置,则要求; 正确地引用其内存地址mov ax, 0xB800mov es, axmov byte [es:(80 * 10 + 0) * 2], 'A'mov byte [es:(80 * 11 + 0) * 2], 'B'mov byte [es:(80 * 12 + 0) * 2], 'C'mov byte [es:(80 * 13 + 0) * 2], 'D'mov byte [es:(80 * 14 + 0) * 2], 'E'mov byte [es:(80 * 15 + 0) * 2], 'F'

二进制文件如下:

as@as-virtual-machine:~/osdir/chapter3F$ hexdump -Cv boot
00000000  e9 01 00 00 31 c0 8e d8  b4 02 b0 02 b5 00 b1 02  |....1...........|
00000010  b6 00 bb 00 05 8e c3 31  db cd 13 ea 00 00 00 05  |.......1........|
00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000060  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000070  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000080  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000090  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000000a0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000000b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000000c0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000000d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000000e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000000f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000100  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000110  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000120  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000130  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000140  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000150  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000160  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000170  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000180  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000190  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000001a0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000001b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000001c0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000001d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000001e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
00000200  8c c8 8e d8 b8 00 b8 8e  c0 26 c6 06 40 06 41 26  |.........&..@.A&|
00000210  c6 06 e0 06 42 26 c6 06  80 07 43 26 c6 06 20 08  |....B&....C&.. .|
00000220  44 26 c6 06 c0 08 45 26  c6 06 60 09 46           |D&....E&..`.F|
0000022d

运行效果如下

怠速

操作系统一旦实现怠速,则意味着系统与用户的交互接口已准备完毕。

页表

页表是进程内存与物理实际存储之间的桥梁。

在开启分页机制后,CPU拿到这个地址,会根据CR3寄存器中存储的页目录表地址来进行寻址,最终得到的物理地址才是CPU真正去访问的地址。

无论是几级页表,标准页的尺寸都是 4KB,所以 4GB 线性地址空间最多有 1M 个标准页。

一级页表是将这 1M 个标准页放置到一张页表中,二级页表是将这 1M 个标准页平均放置 1K 个页表中,每个页表中包含有 1K 个页表项。

页表项是 4 字节大小,页表包含 1K 个页表项,故页表大小为4KB,这恰恰是一个标准页的大小。

打开分页之后,每一个进程只管用平坦连续地址空间,并在进程当地的页表中记录MMU反馈的实际上用到的是哪几个物理页中即可。

如:

加载的进程1实际使用的页为第235,238页,则其进程当地页表中记录的就是{235,238}

加载的进程2实际使用的页为第29页,则其进程当地页表中记录的就是{29};

VPN(虚拟地址)总是连续的,是根据进程需要形成的平坦连续空间;

PPN(物理地址)总是不连续的,是MMU根据请求,将实际物理地址分页后查找到的实际可用的页面的编号返回给进程,进行记录。用于切换现场的保存、换出及重加载。

【日拱一卒行而不辍20220924】自制操作系统相关推荐

  1. 【日拱一卒行而不辍20220926】自制操作系统

    分页原理 在汇编文件chapter3/f/pmtest6.asm中,关于分页设置的代码如下. 此时还未开启多进程,仅有的一个进程中这个表有什么作用吗?页表需要进行切换吗? 每一个进程都会形成这样一个完 ...

  2. 【日拱一卒行而不辍20220921】自制操作系统

    8086内存安排 8086实模式的寻址范围只有1MB.其中: 系统硬件使用的存储器地址被安排在高端,地址从0xA0000H(684KB)开始的384KB中,其中有用于显示的视频缓冲区: 内存低端安排了 ...

  3. 【日拱一卒行而不辍20220925】自制操作系统

    下面这段系统联调的代码始终没有调通.需要进一步排查. 在汇编层面,下述代码已经进入了综合的深水区. ; ========================================== ; pmt ...

  4. 【日拱一卒行而不辍20221010】自制操作系统

    多进程 修改后的如下chapter6E的Makefile如下所示如下 ######################### # Makefile for Orange'S # ############# ...

  5. 日拱一卒,功不唐捐 | 每日思考俱乐部 专栏更新通知

    缘起 在 2019 年七月份,我写了一篇文章<我为什么要写反思录>.文中提到了我做记录和思考的初衷,起初写在了自己的私密仓库中,也就是其他人都看不到. 持续了一段时间后,我发现,没有分享的 ...

  6. 日拱一卒,“功不唐捐

    据说,世界上只有两种动物能够登上金字塔顶,一种是老鹰,一种是蜗牛.他们是如此不同,老鹰矫健,敏捷,蜗牛弱小,迟钝,可是蜗牛仍然与老鹰一样能达到金字塔顶端.它凭的就是永不停息的执着精神. "日 ...

  7. 社区人物志|李昊鹏:日拱一卒,功不唐捐

    「社区人物志」是 Apache Doris 社区推出的系列专栏,我们关注每一个对 Doris 做出过贡献的 Contributor ,会定期从对 Doris 做出突出贡献的小伙伴中选出一位「社区之星」 ...

  8. #研发解决方案#大数据协作平台魔盒——日拱一卒,功不唐捐

    郑昀 创建于2017/6/29 最后更新于2017/6/30 关键词:大数据,Spark,SparkSQL,HBase,HDFS,工作流,任务,Flow,Job,监控报警 提纲: 为什么要大数据协作? ...

  9. 日拱一卒,集小胜为大胜; 学以致用,在战争中学习战争;

    项目,证明自己的学习能力: 短期掌握尽可能多的知识,并且连线总结成为网络 : 日拱一卒,集小胜为大胜: 学以致用,在战争中学习战争: 投入足够的时间: 学习中的总结,理解 ,应用,等编程套路: 目的性 ...

最新文章

  1. 优秀!广州“土博士”刚毕业,即获海外名校终身教职!
  2. uva1504(模拟+暴力)
  3. com 组件调用不起来_一文读懂Eureka,Feign,Ribbon,Hystrix,Zuul核心组件间的关系...
  4. 【Envi风暴】基于ENVI平台提取ASTER DEM完整操作步骤(附案例数据)
  5. linux 那些事儿之我是 u 盘,《Linux那些事儿之我是USB》.PDF
  6. (七)深入浅出TCPIP之深入浅出TCPIP之TCP重传机制
  7. ipv6网络使用scp,并解决No route to host与no matches found报错
  8. 通过SQL语句来备份,还原数据库
  9. 改变函数this指向
  10. 海量数据挖掘MMDS week6: 决策树Decision Trees
  11. solaris常用命令总结
  12. oci8 php,PHP_试用php中oci8扩展,给大家分享个php操作Oracle的操 - phpStudy
  13. c语言程序运行的单词翻译,c语言常见英语词汇带翻译
  14. 一篇搞懂Git 和 SVN 的区别
  15. 2 资源关系 | 到底什么是”局“-- 清华宁向东的管理学课总结
  16. 原创,PHP简单的查询火车时刻表程序
  17. python vba 审计_审计工作中有哪些 Excel VBA 的应用?
  18. C# #region简单使用
  19. java IO编程详解
  20. 实训三:文件系统命令及vi编辑

热门文章

  1. mac删除core文件并关闭core文件以节约磁盘
  2. Navigation的基本使用
  3. mysql 索引 using temporary场景
  4. Java核心技术 卷1-总结-11
  5. 嫦娥二号没有拍到美国登月痕迹
  6. 35搜索插入位置之Leecode—《数组篇》(二分法)
  7. LOGO的主要作用是什么?logo设计都有着哪些设计规则?
  8. 深度产教融合的“山东经验”
  9. (七)JMockit 的MockUp+@Mock--基础篇
  10. 使用php创建WebSocket服务