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

本文详细介绍了8086处理器的内存地址变换过程,包括分段和分页机制,以及线性地址到物理地址的转换。讨论了中断处理,如IDT(中断描述符表)在实模式和保护模式下的区别,以及如何通过IDTR寄存器管理和初始化。此外,文章还提到了在Linux中CLI和STI指令的移除,引入了更轻量级的同步机制。最后,简述了多扇区代码加载的概念,以及页表在进程内存管理和物理地址映射中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

8086内存地址变换过程

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

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

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

所以可以表示为Paging(Segmentation(seg:offset)),这个函数的嵌套关系不能改变。

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

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

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 off

    local_irq_enable()        => turn local IRQs on

    local_save_flags(flags)   => save the current IRQ state into flags. The
                                 state can be on or off. (on some
                                 architectures there's even more bits in it.)

    local_irq_save(flags)     => save the current IRQ state into flags and
                                 disable 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	07c00h
	jmp	LABEL_BEGIN
;--------------------------------------------------------------------------------------
;--------------------------------------------------------------------------------------
[SECTION .s16]
[BITS	16]
LABEL_BEGIN:

        xor ax,ax      ; 为 DS 置 0 准备
        mov ds,ax
        mov ah, 0x02
        ;al=1 load sec2
        ;al=2 load sec2-3
        ;al=3 load sec2-4
        mov al, 2
        mov ch, 0
        mov cl, 2
        mov dh, 0
        mov bx, sect2
        mov es, bx
        xor bx, bx
        int 0x13
        jmp sect2:0
data:
        sect2 equ 0x0500
times   506-($-$$) db 0
dw      0xaa55
;--------------------------------------------------------------------------------------
;--------------------------------------------------------------------------------------
;sect2:
	mov ax, cs
	mov ds, ax    ; 设置 CS=DS. CS=0x0500, 因此 DS=0x500
                      ; 如果变量已经在代码中设置,则要求
                      ; 正确地引用其内存地址
	mov ax, 0xB800
	mov es, ax
	mov 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根据请求,将实际物理地址分页后查找到的实际可用的页面的编号返回给进程,进行记录。用于切换现场的保存、换出及重加载。

无人机协同侦察任务航迹规划是一项复杂而关键的技术,在军事、科研及商业应用等领域都具有重要价值。这种规划需要综合考虑飞行效率、能量消耗、通信稳定性、目标覆盖度以及潜在风险等因素,通常采用数学建模、算法优化以及智能决策等手段进行。 ### 航迹规划的基本步骤: #### 1. 目标识别与区域划分 首先,明确侦察任务的目标,如地面特定区域内的敌方活动、重要资源分布等。接着,基于地图数据将作业区域划分为若干小块,每个小块由一台或无人机负责侦察。 #### 2. 初始路径规划 利用图论、最短路径算法(如Dijkstra算法、A*搜索算法)、或者更高级的优化技术(遗传算法、粒子群优化等),对每架无人机生成一条从起飞点到目的地的初步航线。此过程需考虑到地形限制、速度限制、安全距离等约束条件。 #### 3. 协同策略制定 通过网络理论或博弈论,设计无人机之间的协作策略。例如,可以设置“领航”机制,让一架无人机作为先导,其他无人机跟随,以减少迷路的可能性;或是实施动态调度,根据实时信息调整无人机任务分配,提高整体效能。 #### 4. 避障与自适应调整 构建障碍物检测模型,并结合环境感知技术(如激光雷达、热成像系统),实现实时避障。同时,利用机器学习算法不断学习和优化航迹,针对可能出现的新情况自动调整路线,保证任务完成的同时降低能源消耗。 #### 5. 通信与同步控制 确保各无人机间有稳定的通信链路,便于共享情报、调整计划。利用分布式控制系统或中央指挥平台进行协调管理,处理复杂的决策问题,如紧急避险、任务优先级调整等。 #### 6. 模拟与验证 通过仿真技术模拟实际操作场景,评估航迹规划方案的有效性和鲁棒性。基于反馈结果,持续迭代优化规划算法,提升任务成功率和无人机系统的整体性能。 ### 实现无人机协同侦察任务航迹规划的关键技术包括但不限于: - **自主导航与定位**:利用GPS、惯性测量单元(IMU)、视觉传感器等种设备进行高精度定位和导航。 - **无线通信技术**:选择低延迟、抗干扰性强的通信协议,确保数据传输的可靠性和安全性。 - **人工智能与大数据分析**:运用深度学习、强化学习等AI技术预测环境变化,优化飞行策略,提高任务执行效率和应对突发事件的能力。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值