《操作系统》实验手记 | 从逻辑地址到共享内存:一次完整的内存管理实践
1. 实验目标与核心概念第一次打开Bochs调试器时看到黑屏上闪烁的光标和满屏的十六进制数字我意识到这将是一次深入操作系统内核的探险。这次实验要完成两个关键任务一是手动追踪变量i0x12345678从逻辑地址到物理地址的完整翻译过程二是在Linux 0.11上实现共享内存机制。这两个目标看似独立实则共同构成了理解现代操作系统内存管理的完整拼图。地址映射就像城市快递系统当你在电商平台下单逻辑地址快递员需要根据配送区域分段机制找到对应的物流中心线性地址再根据具体楼栋导航分页机制最终将包裹送到你家门口物理地址。IA-32架构采用的就是这种分段分页的二级寻址机制而Linux 0.11在x86平台上完美展现了这一设计。共享内存则像是公司里的公共白板不同部门的同事进程无需传递纸条进程间通信开销可以直接在白板共享内存区域上读写信息。实现这个机制需要解决三个关键问题如何找到空闲物理页面、如何建立地址映射、如何管理虚拟地址空间。在Linux 0.11中这些功能分别由get_free_page()、put_page()和change_ldt()等函数协作完成。2. 地址映射实战解析2.1 实验环境搭建在Ubuntu下准备好test.c后我通过以下命令将其移植到Linux 0.11环境sudo ./mount-hdc cp ./exp_07/test.c ./hdc/usr/root/ sudo umount hdc这个简单的C程序会在无限循环中打印变量i的逻辑地址#include stdio.h int i 0x12345678; int main(void) { printf(The logical/virtual address of i is 0x%08x, i); while(i); return 0; }启动Bochs调试器时./dbg-asm命令会进入汇编级调试模式。当看到终端显示Next at t0时我直接输入c命令让系统继续运行直到Linux 0.11完成启动。这个过程中有个关键细节如果CtrlC暂停时显示的是0008而非000f说明中断发生在内核态需要继续执行直到进入用户态。2.2 段表寻址过程当程序暂停在cmp指令时使用sreg命令查看段寄存器状态ds:s0x0017, dl0x00003fff, dh0x10c0f300, valid3 ldtr:s0x0068, dl0xc2d00068, dh0x000082f9, valid1 gdtr:base0x00005cc8, limit0x7ff这里的ds值0x0017是段选择子拆解其二进制0000000000010111TI1表示查找LDT表索引值2对应LDT表中第3个描述符从0开始计数通过gdtr找到GDT基地址0x00005cc8LDT在GDT的第13项0x0068313使用xp /2w 0x00005cc813*8查看得到LDT描述符0xc2d00068 0x000082f9组合后得到LDT物理地址0x00f9c2d0。2.3 线性地址计算在LDT中找到第3个描述符0x00003fff 0x10c0f300提取段基址0x10000000。加上段内偏移0x3004得到线性地址0x10000000段基址 0x3004偏移 0x10003004用calc ds:0x3004验证结果一致。2.4 页表查询与物理地址通过creg查看CR30x00000000即页目录表基址为0。线性地址0x10003004二进制拆分页目录号64高10位1000000页表号3中间10位0000000011页内偏移4低12位000000000100查询页目录项xp /w 064*4 # 显示0x00faa027页表基址为0x00faa000查询第3个页表项xp /w 0x00faa0003*4 # 显示0x00fa7067最终物理地址为页框号0x00fa7 偏移0x004 0x00fa7004。使用xp /w 0x00fa7004确实看到了初始值0x12345678。3. 共享内存实现3.1 系统调用添加首先需要在三个关键文件中添加系统调用声明include/unistd.h 添加调用编号#define __NR_shmget 87 #define __NR_shmat 88kernel/system_call.s 修改系统调用总数nr_system_calls 89include/linux/sys.h 添加函数声明int sys_shmget(); void * sys_shmat();3.2 关键数据结构在include/shm.h中定义共享内存控制块#define SHM_NUM 16 struct struct_shmem { unsigned int size; unsigned int key; unsigned long page; };3.3 shmget实现kernel/shm.c中的核心逻辑int sys_shmget(key_t key, size_t size) { if(size PAGE_SIZE) { errno EINVAL; return -1; } // 检查是否已存在相同key的共享内存 for(int i0; iSHM_NUM; i) { if(shm_list[i].key key) return i; } // 申请新页面 unsigned long page get_free_page(); if(!page) { errno ENOMEM; return -1; } // 填充控制块 for(int i0; iSHM_NUM; i) { if(!shm_list[i].key) { shm_list[i].key key; shm_list[i].page page; shm_list[i].size size; return i; } } return -1; }3.4 shmat实现映射过程的关键步骤void* sys_shmat(int shmid) { if(shmid 0 || shmid SHM_NUM || !shm_list[shmid].page) return NULL; unsigned long tmp get_base(current-ldt[1]) current-brk; put_page(shm_list[shmid].page, tmp); unsigned long ret current-brk; current-brk PAGE_SIZE; return (void*)ret; }这里get_base获取数据段基址current-brk是进程堆顶指针通过put_page建立页表映射。4. 生产者-消费者验证4.1 程序改造要点原始pc.c需要做三处修改将文件缓冲区改为共享内存拆分为producer.c和consumer.c两个独立程序使用相同的SHM_KEY确保访问同一块内存producer.c关键部分#define SHM_KEY 2018 int main() { shm_id shmget(SHM_KEY, BUFFER_SIZE*sizeof(int)); p (int*)shmat(shm_id); while(i PRODUCE_NUM) { sem_wait(Empty); sem_wait(Mutex); p[location] i; sem_post(Mutex); sem_post(Full); } }4.2 运行与调试编译运行命令gcc -o pro producer.c gcc -o con consumer.c ./pro pro.txt ./con con.txt当遇到共享内存无法访问时可以通过dmesg查看内核打印信息。我在调试时就发现因为没有正确设置key导致两个进程访问了不同的内存区域。5. 深度思考与优化在实现过程中我发现原始设计有几个可以改进的点内存泄漏风险当所有进程都退出时共享内存不会自动释放。可以在shm.c中添加引用计数当最后一个进程调用shmdt时自动释放页面。安全性问题当前实现没有权限检查任何进程只要知道key就能访问共享内存。可以借鉴现代Linux的权限位设计在struct_shmem中添加uid/gid字段。性能优化put_page每次都会修改页表对于频繁的共享内存操作可以考虑使用更大的页面尺寸如4MB大页减少TLB失效。这个实验最让我惊喜的是通过亲手实现这些底层机制那些课本上抽象的概念突然变得具象起来。记得在调试页表映射时当第一次看到xp /w成功显示出预期的数值那种窥见计算机灵魂的震撼感至今难忘。

相关新闻

稳定版 Foster → Cauer 转换(使用经典连分式展开 + 数值保护 + 后处理)

稳定版 Foster → Cauer 转换(使用经典连分式展开 + 数值保护 + 后处理)

以下是稳定版 Foster → Cauer 转换(使用经典连分式展开 + 数值保护 + 后处理): 完整稳定版 C# 代码(推荐替换) public static (double[] Rcauer, double[] Ccauer) FosterToCauerStable(

2026/7/14 6:17:27 阅读更多 →
【小白也能轻松玩转龙虾】虾壳云一键部署,图文对照清晰安装步骤(附最新安装包)

【小白也能轻松玩转龙虾】虾壳云一键部署,图文对照清晰安装步骤(附最新安装包)

OpenClaw(小龙虾)Windows 一键部署实操手册|十分钟搭建专属本地数字员工 适配平台:Windows 10/11(64 位)|零基础友好|全可视化界面|无编程门槛 当下热度较高的开源 AI 智…

2026/7/14 6:17:27 阅读更多 →
告别踩坑:Mac 从零搭建 YOLO 深度学习环境

告别踩坑:Mac 从零搭建 YOLO 深度学习环境

本文参考blibli教程整理,适合零基础小白按步骤操作。 参考视频: MacBook M1 深度学习环境 AnacondaPyCharmPyTorch YOLO 算法实战 03 安装依赖包 YOLO 算法实战 04 安装 ultralytics YOLO 算法实战 05 基础术语简介 YOLO 算法实战 06 初体验 一…

2026/7/14 6:15:26 阅读更多 →

最新新闻

Ubuntu下qpOASES二次规划库安装与C++项目集成实战

Ubuntu下qpOASES二次规划库安装与C++项目集成实战

1. 项目概述:为什么我们需要 qpOASES?如果你在 Ubuntu 上搞机器人控制、轨迹优化、模型预测控制,或者任何需要在线求解带约束优化问题的 C 项目,那你大概率绕不开“二次规划”这个坎。简单说,二次规划就是在一堆线性等…

2026/7/14 7:55:55 阅读更多 →
MATLAB Robotics Toolbox:从建模到轨迹规划的六轴机械臂全流程实战

MATLAB Robotics Toolbox:从建模到轨迹规划的六轴机械臂全流程实战

1. 六轴机械臂与MATLAB Robotics Toolbox基础第一次接触工业机械臂时,我被它精准的运动轨迹所震撼。六轴机械臂作为工业自动化领域的"多面手",其每个关节的协同运动背后,是复杂的数学建模和算法支撑。而MATLAB Robotics Toolbox就像…

2026/7/14 7:55:54 阅读更多 →
JavaQuestPlayer:跨平台QSP游戏开发与运行的全面解决方案

JavaQuestPlayer:跨平台QSP游戏开发与运行的全面解决方案

JavaQuestPlayer:跨平台QSP游戏开发与运行的全面解决方案 【免费下载链接】JavaQuestPlayer 项目地址: https://gitcode.com/gh_mirrors/ja/JavaQuestPlayer JavaQuestPlayer是一款基于JavaSE的QSP游戏开发与运行平台,为游戏开发者和玩家提供了一…

2026/7/14 7:55:54 阅读更多 →
DLSS Swapper终极指南:5分钟掌握游戏性能调优神器

DLSS Swapper终极指南:5分钟掌握游戏性能调优神器

DLSS Swapper终极指南:5分钟掌握游戏性能调优神器 【免费下载链接】dlss-swapper 项目地址: https://gitcode.com/GitHub_Trending/dl/dlss-swapper 你是否曾经因为游戏帧率不稳定而烦恼?是否遇到过新DLSS版本在某些游戏中表现不佳,却…

2026/7/14 7:53:53 阅读更多 →
Palworld存档编辑工具:从神秘二进制到可读JSON的魔法转换

Palworld存档编辑工具:从神秘二进制到可读JSON的魔法转换

Palworld存档编辑工具:从神秘二进制到可读JSON的魔法转换 【免费下载链接】palworld-save-tools Tools for converting Palworld .sav files to JSON and back 项目地址: https://gitcode.com/gh_mirrors/pa/palworld-save-tools 你是否曾经好奇《幻兽帕鲁》…

2026/7/14 7:53:53 阅读更多 →
面向多智能体系统的统一认知协议栈设计与实现——以WSaiOS为例

面向多智能体系统的统一认知协议栈设计与实现——以WSaiOS为例

面向多智能体系统的统一认知协议栈设计与实现——以WSaiOS为例作者:东塬一老翁摘要: 随着人工智能从单一模型向多智能体协作系统演进,异构模块间的通信割裂与语义不一致问题成为制约系统可扩展性与鲁棒性的关键瓶颈。本文提出并定义了一种面向AI操作系统…

2026/7/14 7:51:53 阅读更多 →

日新闻

AI Agent数据越界行为如何被精准溯源?——基于GDPR/CCPA双合规的5层审计框架实战指南

AI Agent数据越界行为如何被精准溯源?——基于GDPR/CCPA双合规的5层审计框架实战指南

更多请点击: https://kaifayun.com 第一章:AI Agent数据越界行为的合规性挑战与溯源必要性 AI Agent在自主执行任务过程中,可能因提示注入、上下文污染或权限配置缺陷,无意或有意访问、缓存、传输受保护数据(如PII、G…

2026/7/14 0:01:13 阅读更多 →
Perplexity vs ChatGPT vs Claude:实测127组复杂查询任务,谁才是真正可靠的“事实型AI助手”?

Perplexity vs ChatGPT vs Claude:实测127组复杂查询任务,谁才是真正可靠的“事实型AI助手”?

更多请点击: https://codechina.net 第一章:Perplexity 怎么用 Perplexity 是衡量语言模型预测能力的核心指标,数值越低表示模型对文本序列的不确定性越小、预测越精准。它本质上是交叉熵损失的指数形式,计算公式为:…

2026/7/14 0:01:13 阅读更多 →
全球首发!五一视界定制物理AI卫星ECS-1剑指万亿赛道

全球首发!五一视界定制物理AI卫星ECS-1剑指万亿赛道

五一视界发布公告,近日,公司与环天智慧科技股份有限公司(“环天智慧”)正式达成空天领域战略合作。环天智慧是国内领先、聚焦天基对地观测遥感卫星总体研制与在轨运营的商业航天企业,同时也是西南地区规模最大、具备全自主可控遥感卫星星座建…

2026/7/14 0:03:13 阅读更多 →

周新闻

互联网大厂 Java 求职面试:燕双非的搞笑回答与技术探讨

互联网大厂 Java 求职面试:燕双非的搞笑回答与技术探讨

互联网大厂 Java 求职面试:燕双非的搞笑回答与技术探讨 在一个阳光明媚的上午,互联网大厂的面试官坐在桌前,准备迎接他的面试候选人——燕双非,一个以搞笑和幽默著称的程序员。第一轮提问 面试官:燕双非,作…

2026/7/13 4:38:36 阅读更多 →
车载以太网PMA测试设备选型:示波器、VNA、信号源3类仪器关键参数与预算评估

车载以太网PMA测试设备选型:示波器、VNA、信号源3类仪器关键参数与预算评估

车载以太网PMA测试设备选型:示波器、VNA、信号源3类仪器关键参数与预算评估在智能驾驶和车联网技术快速发展的今天,车载以太网作为新一代车载网络的核心传输技术,其物理层性能直接决定了数据传输的可靠性和稳定性。1000BASE-T1作为当前主流的…

2026/7/13 4:38:38 阅读更多 →
VSCode EIDE 插件 2.0:APM32/STM32 项目迁移实战,5步完成Keil工程转换

VSCode EIDE 插件 2.0:APM32/STM32 项目迁移实战,5步完成Keil工程转换

VSCode EIDE 插件 2.0:APM32/STM32 项目迁移实战指南嵌入式开发领域正经历一场工具链的静默革命。当传统Keil用户首次打开VSCode的扩展市场搜索EIDE时,往往会惊讶于这个看似简单的插件竟能重构十余年的开发习惯。本文将揭示如何用五个精准步骤&#xff0…

2026/7/14 7:15:24 阅读更多 →

月新闻