- 博客(31)
- 收藏
- 关注
原创 C++ 原子操作
在 ARM 等使用LL/SC(加载链接 / 存储条件) 架构的 CPU 上,CAS 通过 LDREX/STREX 指令对实现。即使内存值和期望值相等,LL/SC 也可能因为中断、其他线程的内存访问等原因失败,这就是伪失败:ARM 把原子操作拆成两条独立指令,硬件只做一件事:给地址打一个「独占标记」,但是独占标记极其脆弱,只要发生任何干扰,硬件会直接清除独占标记,不关心内存值有没有变:LDREX:读取内存值 → 硬件给该内存地址打上「本核独占标记」
2026-05-05 21:36:29
425
原创 C++模板元编程
模板元编程(Template Metaprogramming, TMP) 是一种利用 C++ 模板机制 在编译期执行计算和生成代码的编程范式。它的核心思想是将编译器当作“解释器”,在编译阶段完成类型推导、数值计算、代码生成等工作,从而实现 零运行时开销。
2026-04-27 19:45:58
362
原创 C++ 移动语义
移动语义是C++11 引入的核心特性,也是现代 C++ 性能优化的基石。它的核心思想极其简单:不复制资源,而是转移资源的所有权。用过户的成本(仅交换指针 / 整数)替代昂贵的深拷贝,彻底解决 C++98 中临时对象的冗余开销问题。在 C++11 之前,对象的资源管理只有一种方式:拷贝。对于管理堆内存、文件句柄等资源的类,拷贝必须做「深拷贝」—— 重新分配内存、复制全部数据,这会带来极大的性能浪费。这就暴露了问题:一次函数返回,触发了2 次内存分配、2 次内存释放,其中拷贝构造的分配完全是冗余的。
2026-04-27 19:45:36
396
原创 x86操作系统27——PCIe与NVMe硬盘驱动
NVMe 是专为非易失性存储器(如 NAND Flash)设计的高速传输协议,基于 PCIe 总线实现,它和传统 IDE/AHCI相比,NVMe 大幅降低了存储 IO 的延迟,提升了并行处理能力 —— 这得益于其基于队列的命令交互模型,而单命令模型。这套模型天生适合并发,延迟也低。
2026-03-10 16:51:07
422
原创 x86操作系统26——MMIO与APIC
传统 I/O 交互采用端口映射,外设端口与内存地址空间独立,而 MMIO 采用统一编址思想:将外设寄存器的物理地址纳入 CPU 的物理地址空间,CPU 可像读写普通内存一样操作外设寄存器。这样要求该设备必须在CPU的视角中像内存一样可寻址。这种方式即为内存映射I/O。MMIO设备可以是寄存器、内存缓冲区,或是键盘、鼠标等外设控制器,CPU通过访问特定的内存地址,实现对它们的读写与控制。
2026-03-10 16:50:49
421
原创 x86操作系统25——虚拟设备与设备树
设备树(Device Tree Source,DTS)是描述硬件设备拓扑和属性的文本格式文件(device.dts),dts文件最终会被编译为二进制的 DTB 文件供内核解析。/dts-v1/;/ {#address/ {// 设备别名 aliases {// 系统标准输入输出设备路径 chosen {// VGA 文本模式控制台 vga_console : console@ 3 d4 {
2026-01-23 20:07:15
1003
原创 x86操作系统24——硬盘驱动
IDE(Integrated Drive Electronics)是将硬盘控制器集成到硬盘本身的接口标准,而 ATA(Advanced Technology Attachment)是 IDE 接口遵循的底层通信协议。我们常说的 IDE 硬盘,本质是遵循 ATA 协议的存储设备。
2026-01-21 15:31:56
791
原创 x86操作系统23——进程相关系统调用
brk系统调用的作用是修改堆内存的上限。我们的操作系统从8M ~ 128M 是用户进程的内存空间。我们会把进程的ELF文件映射到 8M 开始的位置, 有text段、data段、bss段。这些段结束后就是堆内存。堆内存使用了多少就需要使用brk来标记。brk系统调用是 malloc/free 函数的基础。访问尚未映射的虚拟页会触发 page fault:内核在 page_fault_handler 中读取 CR2、解析错误码。若地址在允许范围并且是“页面不存在”的情况,走按需分配分支。
2026-01-12 22:31:10
999
原创 x86操作系统22——进程用户栈
在本系统中,我们采用按需映射的方式为用户态栈分配物理页。具体思路是:把用户栈的虚拟顶端固定在 128MB(0x08000000),栈向下增长,当用户程序首次触发对栈页的访问时由缺页异常(page fault)捕获并在异常处理里分配物理页,然后把该虚拟页映射到新分配的物理页上。这样可以节省物理内存并支持按需增长。0x80000000x200000说明:把栈顶放在较高地址(128MB)有两个好处:一是与内核低地址空间分离,二是给用户空间预留了一个可控的栈区间(最多 2MB),当访问超出时可以视为栈溢出并处理。
2026-01-12 19:35:10
803
原创 x86操作系统21——内核堆内存管理与用户内存映射
前面我们已经实现了分配回收内核的内存,但是分配的内存是以页为单位的,一次分配4k,对于小内存块的分配会产生大量内存碎片,因此需要实现一种小内存的分配器,首先定义两个结构::描述一种块规格:块大小(从 16 字节开始,每级翻倍):一页可切出的块数量():当前规格下的空闲块链表:描述真实页(或多页)小块场景: 指向规格描述符; 为剩余块数;大块场景:, 为页数;都有 用于一致性校验:用 表示一个块,直接以块起始地址作为链表节点存储。初始化()循环填充 7 种规格(1
2025-12-24 21:59:12
669
原创 x86操作系统20——用户态切换与printf
用一页内核栈造一帧伪中断现场再iret,就能把线程送进 CPL=3 运行;当前实现能跑,但为了简单没有做页级隔离,安全性不足,等待后续完善。
2025-12-15 09:09:04
587
原创 x86操作系统19——键盘驱动
通过一个枚举类型定义键盘所有的扫描码。通过结构体keymap定义扫描码对应的字符,其中数组的第三个元素判断shift是否被按下,第四元素代表扩展按键是否被按下。0// 不可见字符0xB7KEY_NONE,KEY_ESC,KEY_1,...// 以下为自定义按键,为和 keymap 索引匹配} KEY;/* 扫描码 未与 shift 组合 与 shift 组合 以及相关状态 */....// 大写锁定// 滚动锁定// 数字锁定// 扩展码状态。
2025-12-12 20:23:00
398
原创 x86操作系统18——grub引导
Multiboot2 是一套针对 x86 架构设计的引导接口标准,核心目的是解决不同内核与引导加载器之间的适配碎片化问题。它定义了内核必须遵循的统一规范:比如内核二进制文件中需嵌入包含固定魔数(0xE85250D6)、校验和、结束 Tag 等的标准化头部,同时规定了引导加载器向内核传递硬件信息(如内存布局、外设信息)、加载内核到指定内存地址的交互规则。
2025-12-12 18:57:09
633
原创 x86操作系统17——互斥、信号量与锁
在并发编程领域,竞态条件是永远绕不开的话题,当多个执行流同时访问共享资源时,若缺乏有效的同步机制,最终结果会依赖于执行流的调度顺序,导致程序行为不可预测。而互斥是解决竞态条件的核心思想,即保证同一时间只有一个执行流能访问临界区。操作系统内核、需要管理 CPU、内存、外设等核心共享资源,其并发场景更复杂,因此内核必须实现高效、安全的同步原语。
2025-12-09 21:27:20
865
原创 x86操作系统16——任务状态管理与核心进程解析
在操作系统中,任务(进程 / 线程)的状态管理是核心功能之一。一个任务从创建到终止,会在多种状态间切换,这些状态包括就绪、运行、阻塞、睡眠等。
2025-12-08 16:08:12
796
原创 x86操作系统15——内核级线程与系统调用
用户态触发:用户程序将系统调用号存入 eax,参数存入 ebx/ecx/edx 等寄存器,执行int 0x80;特权级切换:CPU 根据 IDT 中 0x80 号中断门,切换到内核态,跳转到syscall_handler;汇编层处理:- 调用syscall_check验证调用号;- 保存用户态上下文,传递参数;- 根据 eax 中的调用号,调用syscall_table中的对应函数;C 层函数执行:执行syscall_test(调用号 0)等处理函数,返回值存入 eax;
2025-12-04 16:36:16
859
原创 x86操作系统14——内存管理
这段来自https://www.cnblogs.com/flashsun/p/12234807.html首先,什么是内存分页?我们可以类比段转换:实模式下,地址格式是 ,保护模式下通过段选择子查询段描述符表,取出段基址与段内偏移拼接,得到最终地址。分页转换的核心逻辑与段转换类似,但针对大内存管理做了分层优化:开启分页后,段转换的结果不再是最终物理地址,而是虚拟地址(也常称逻辑地址) 。该虚拟地址被拆分为 “高部分 + 中部分 + 低部分”,高部分用于查找一级页表(页目录表),中部分查找二级页表(页表),低部
2025-11-28 19:39:01
1289
原创 x86操作系统13——计数器与时钟
PIT 计数器 0 按 10ms 周期产生信号,触发 IRQ0;主 PIC 接收 IRQ0,将其映射为中断向量 0x20 发送给 CPU;CPU 查找 handler_table[0x20],执行注册的 clock_handler 函数;函数内累计 jiffies,完成一次时间滴答的计数。// CMOS 端口定义0x70// CMOS 地址寄存器(写入要访问的寄存器地址)0x71// CMOS 数据寄存器(读取/写入数据)0x80// 屏蔽 NMI 标志(访问 CMOS 时必须设置)
2025-11-26 20:12:59
935
原创 x86操作系统12——中断
想象你正在写代码(CPU 执行指令),突然电话响了(外设请求),你停下代码(暂停当前任务),接电话(处理请求),挂电话后继续写代码(恢复原任务)—— 这个过程就是中断。当然,中断还是多任务的基础,比如通过定时器中断定期 “打断” 当前任务,实现进程切换。
2025-11-20 14:39:35
1003
原创 x86操作系统11——任务及上下文
/ 任务结构体:描述一个任务的核心属性(此处仅需栈指针)u32 *stack;// 任务栈指针,指向栈顶(保存上下文的位置)} task_t;// 任务栈帧:保存任务切换时需要保存的寄存器状态(上下文)u32 edi;// 寄存器edi,u32 esi;// 寄存器esi,常用于字符串操作或数组遍历,esi 指向源数据,edi 指向目的地址。u32 ebx;// 寄存器ebx,常用于存放全局变量或数组的基地址,或作为临时变量的持久存储:值在多个函数调用中保持不变。u32 ebp;
2025-11-20 14:36:57
680
原创 x86操作系统10——断言
断言是编程中用于验证程序内部假设的调试机制,核心作用是在开发 / 测试阶段快速捕捉逻辑错误。如果断言的条件不成立,程序会立即终止并抛出明确的错误信息,帮助开发者定位问题。
2025-11-18 14:28:31
1009
原创 x86操作系统09——内核打印函数printk
这部分是格式化逻辑的规则基础,通过宏定义固化格式化控制规则,避免硬编码。0x01// 用0填充空白位(如%04d)0x02// 处理有符号数(如%d/%i)0x04// 强制显示符号(如+123)0x08// 正数前加空格(如 123)0x10// 左对齐(如%-5d)0x20// 特殊格式(八进制加0、十六进制加0x)0x40// 十六进制用小写字母(如%x)0x80。
2025-11-18 14:28:10
569
原创 x86操作系统08——可变参数原理
可变参数指函数能接收数量不固定的参数(如printf(“%d, %s”, 123, “abc”)),其底层原理依赖函数调用约定和栈帧结构,通过指针遍历栈中参数实现。
2025-11-17 15:11:09
931
原创 x86操作系统07——简单VGA显卡驱动
VGA有很多寄存器,但我们只用到以下几种,如果想扩展其他功能,可以参考以下网址:0x3D4// CRT(6845)索引寄存器0x3D5// CRT(6845)数据寄存器0xC// 显示内存起始位置 - 高位0xD// 显示内存起始位置 - 低位0xE// 光标位置 - 高位0xF。
2025-11-17 15:10:47
626
原创 x86操作系统06——端口 I/O 操作
在计算机中,CPU 需要与各种硬件设备(如显卡、键盘、硬盘控制器、定时器等)通信(发送控制指令、读取状态、传输数据)。x86 架构提供了两种主流通信方式:内存映射 I/O和端口 I/O(Port I/O)。端口 I/O的核心特点是:为硬件设备分配独立的 “端口地址空间”(与内存地址空间完全分离),端口号是 16 位整数(范围 0~65535),每个端口对应设备的一个寄存器(控制寄存器、数据寄存器等)。例如:键盘控制器的状态寄存器端口是0x64,CPU 通过读取键盘是否有数据输入;
2025-11-16 23:49:15
326
原创 x86操作系统04——进入保护模式
可以看出进入保护模式的操作是很简单的,但提前要做好准备工作,最重要的就是 gdt(Global Descriptor Table 全局描述表)的准备。
2025-11-14 14:54:24
650
原创 x86操作系统03——硬盘读取
MBR 是硬盘第一个扇区(0 磁头 0 柱面 1 扇区)的 512 字节数据块,是电脑上电后 BIOS/UEFI 首先读取的硬盘区域。BIOS 读取 MBR 后,会执行这段程序它的唯一任务是找到存储操作系统的分区,然后交给该分区里的 Loader 继续工作。Loader 先从 MBR 接收系统启动控制权,再从指定分区读取操作系统内核文件并加载到内存,之后将 CPU 从实模式切换到保护模式(或长模式(64位))以支持大内存和多任务,最后完成环境准备后退出,将控制权正式移交给操作系统内核,由内核接管系统运行。
2025-11-14 14:53:52
634
原创 x86操作系统02——计算机的启动过程
电脑启动过程详解:从BIOS到操作系统加载 当按下开机键后,电脑经历了精密的启动流程。首先,CPU初始化后从固定地址0xFFFF0开始执行,跳转到BIOS程序。BIOS负责硬件检测、建立中断向量表,并按启动顺序读取存储设备的MBR(主引导记录)到内存0x7c00处。MBR仅512字节,其最后两字节必须为0x55和0xAA作为有效标志。这个微型程序的核心任务是加载更大的引导加载程序(Loader),由Loader继续加载操作系统内核到内存。整个过程涉及CPU从16位实模式(直接访问1MB物理内存)到32位保护
2025-11-13 18:26:31
1067
原创 x86操作系统01——环境配置
本文介绍了操作系统开发环境的搭建过程,主要包括Bochs模拟器的安装配置和使用方法。首先说明了开发环境的系统要求(Ubuntu 22.04)和工具集合(Bochs、QEMU等)。详细讲解了Bochs的安装步骤,包括依赖安装、源码编译和配置过程。然后演示了一个简单的引导程序(boot.asm)编写、编译和镜像生成流程。特别说明了Bochs配置文件(bochsrc)的关键修改点和Makefile的编写方法。最后提到了GDB调试功能的配置注意事项,指出其与内置调试器的冲突问题。整个过程涵盖了从环境搭建到简单操作系
2025-11-13 18:25:09
447
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅