完整教程:mit6s081 lab8 locks

news/2025/11/12 19:38:27/文章来源:https://www.cnblogs.com/yangykaifa/p/19215140

mit6s081 lab8 locks

一、Memory Allocator(内存分配器)

题目描述

为每个 CPU 实现独立的空闲列表,当 CPU 的空闲列表为空时,可以从其他 CPU 的空闲列表窃取空闲内存

所有的锁都以 "kmem" 开头。你应该为每个锁调用 initlock() 并传入一个以 "kmem" 开头的名称。

通过运行以下命令进行验证:

  • kalloctest:查看锁争用是否显著减少;
  • usertests sbrkmuch:验证是否仍然可以分配所有内存。

输出结果中,尽管具体数值可能不同,但 kmem 锁的总争用次数应显著减少


实现思路


数据结构定义

为每个 CPU 分配一个独立的空闲链表及其锁:

struct {struct spinlock lock;struct run *freelist;
} kmem[NCPU];

修改 kinit

只有一个 CPU(通常是 CPU0)会调用该函数。
该函数负责初始化每个 CPU 的锁,并调用 freerange() 将物理内存放入空闲链表中。

void
kinit()
{char lockname[NCPU];for (int i = 0; i < NCPU; ++i) {snprintf(lockname, sizeof(lockname), "kmem_%d", i); // 为每个 CPU 的锁命名initlock(&kmem[i].lock, lockname); // 初始化锁}freerange(end, (void*)PHYSTOP); // 将用户空间所有内存加入空闲链表
}

修改 kfree

获取 CPU ID 时必须关闭中断,保证获取的 ID 正确。

void
kfree(void *pa)
{struct run *r;if(((uint64)pa % PGSIZE) != 0 || (char*)pa < end || (uint64)pa >= PHYSTOP)panic("kfree");// 用垃圾数据填充,检测悬空引用memset(pa, 1, PGSIZE);r = (struct run*)pa;// 关中断push_off();int id = cpuid(); // 当前 CPU idacquire(&kmem[id].lock);r->next = kmem[id].freelist;kmem[id].freelist = r;release(&kmem[id].lock);pop_off(); // 开中断
}

⚙️ 修改 kalloc

当当前 CPU 的空闲列表为空时,尝试从其他 CPU 的空闲列表中窃取内存块

void *
kalloc(void)
{struct run *r;push_off();int id = cpuid();acquire(&kmem[id].lock);r = kmem[id].freelist;if(r)kmem[id].freelist = r->next;else {int antid; // 其他 CPU idfor (antid = 0; antid < NCPU; ++antid) {if (antid == id) continue;acquire(&kmem[antid].lock);r = kmem[antid].freelist;if (r) {kmem[antid].freelist = r->next;release(&kmem[antid].lock);break;}release(&kmem[antid].lock);}}release(&kmem[id].lock);pop_off();if (r)memset((char*)r, 5, PGSIZE); // 填充垃圾数据return (void*)r;
}

✅ 测试截图

在这里插入图片描述


二、Buffer Cache(缓冲区缓存)

题目描述

修改块缓存,使得运行 bcachetest 时,bcache 中所有锁的 acquire 循环迭代次数接近于 0。

理想情况是所有锁的总争用计数为 0(小于 500 也可接受)。
修改 bget()brelse(),让多个进程能够并发查找和释放缓存块,减少锁竞争。

同时必须保持:

每个磁盘块最多只能缓存一个副本。


优化思路

  • 尽可能减少共享:能独享就独享,比如每 CPU 独立空闲链表。
  • 必须共享时:减少临界区的锁粒度,缩短加锁时间。

⚙️ xv6 原设计


新的改进方案

  • 建立 哈希表(blockno → buf)
  • 每个桶(bucket)配一把独立的自旋锁;
  • 查找 / 插入时仅锁定对应桶;
  • 仅当桶中无空闲 buf 时,再从其他桶“偷取”;
  • 大幅减少全局锁竞争。

结构体修改

struct buf {int valid;      // 是否从磁盘读取过数据int disk;       // 是否为磁盘所有uint dev;uint blockno;struct sleeplock lock;uint refcnt;uint lastuse;   // *新增*:记录最近一次使用时间(用于 LRU)struct buf *next;uchar data[BSIZE];
};

全局结构定义与初始化

#define NBUFMAP_BUCKET 13
#define BUFMAP_HASH(dev, blockno) ((((dev)<<27)|(blockno))%NBUFMAP_BUCKET)
struct {struct buf buf[NBUF];struct spinlock eviction_lock;// 哈希表:从 dev+blockno 到 buf 的映射struct buf bufmap[NBUFMAP_BUCKET];struct spinlock bufmap_locks[NBUFMAP_BUCKET];
} bcache;
void
binit(void)
{// 初始化哈希桶for(int i = 0; i < NBUFMAP_BUCKET; i++) {initlock(&bcache.bufmap_locks[i], "bcache_bufmap");bcache.bufmap[i].next = 0;}// 初始化缓存块for(int i = 0; i < NBUF; i++){struct buf *b = &bcache.buf[i];initsleeplock(&b->lock, "buffer");b->lastuse = 0;b->refcnt = 0;b->next = bcache.bufmap[0].next;bcache.bufmap[0].next = b;}initlock(&bcache.eviction_lock, "bcache_eviction");
}

修改 bget

static struct buf*
bget(uint dev, uint blockno)
{struct buf *b;uint key = BUFMAP_HASH(dev, blockno);acquire(&bcache.bufmap_locks[key]);// 查找是否已缓存for (b = bcache.bufmap[key].next; b; b = b->next) {if (b->dev == dev && b->blockno == blockno) {b->refcnt++;release(&bcache.bufmap_locks[key]);acquiresleep(&b->lock);return b;}}// 若未命中缓存release(&bcache.bufmap_locks[key]);acquire(&bcache.eviction_lock);// 再次确认是否已有缓存(防止重复创建)for (b = bcache.bufmap[key].next; b; b = b->next) {if (b->dev == dev && b->blockno == blockno) {acquire(&bcache.bufmap_locks[key]);b->refcnt++;release(&bcache.bufmap_locks[key]);release(&bcache.eviction_lock);acquiresleep(&b->lock);return b;}}// 选择 LRU 块进行替换struct buf *before_least = 0;uint holding_bucket = -1;for (int i = 0; i < NBUFMAP_BUCKET; i++) {acquire(&bcache.bufmap_locks[i]);int newfound = 0;for (b = &bcache.bufmap[i]; b->next; b = b->next) {if (b->next->refcnt == 0 && (!before_least || b->next->lastuse < before_least->next->lastuse)) {before_least = b;newfound = 1;}}if (!newfound)release(&bcache.bufmap_locks[i]);else {if (holding_bucket != -1)release(&bcache.bufmap_locks[holding_bucket]);holding_bucket = i;}}if (!before_least)panic("bget: no buffers");b = before_least->next;// 若需要移动到目标桶if (holding_bucket != key) {before_least->next = b->next;release(&bcache.bufmap_locks[holding_bucket]);acquire(&bcache.bufmap_locks[key]);b->next = bcache.bufmap[key].next;bcache.bufmap[key].next = b;}b->dev = dev;b->blockno = blockno;b->refcnt = 1;b->valid = 0;release(&bcache.bufmap_locks[key]);release(&bcache.eviction_lock);acquiresleep(&b->lock);return b;
}

修改 brelsebpinbunpin

void
brelse(struct buf *b)
{if (!holdingsleep(&b->lock))panic("brelse");releasesleep(&b->lock);uint key = BUFMAP_HASH(b->dev, b->blockno);acquire(&bcache.bufmap_locks[key]);b->refcnt--;if (b->refcnt == 0)b->lastuse = ticks;release(&bcache.bufmap_locks[key]);
}
void
bpin(struct buf *b) {uint key = BUFMAP_HASH(b->dev, b->blockno);acquire(&bcache.bufmap_locks[key]);b->refcnt++;release(&bcache.bufmap_locks[key]);
}
void
bunpin(struct buf *b) {uint key = BUFMAP_HASH(b->dev, b->blockno);acquire(&bcache.bufmap_locks[key]);b->refcnt--;release(&bcache.bufmap_locks[key]);
}

总结

对象是否在内存中是否可每 CPU 独立是否需要全局同步优化方式
空闲内存(kalloc)✅ 是✅ 可以每 CPU 独立空闲链表
磁盘缓存(bcache)✅ 是❌ 不行✅ 必须哈希分桶 + 每桶独立锁

结论:

  • 虽然磁盘缓存也使用内存,但它存储的是全局共享的文件系统块数据
  • 因此必须保证数据一致性,不能按 CPU 独立分配;
  • 为提高并发性能,应将全局锁细化为哈希桶锁;
    | ------------ | ----------------- | ---------------- | --------------------- |
    | 空闲内存(kalloc) | ✅ 是 | ✅ 可以 | 否 | 每 CPU 独立空闲链表 |
    | 磁盘缓存(bcache) | ✅ 是 | ❌ 不行 | ✅ 必须 | 哈希分桶 + 每桶独立锁 |

结论:

  • 虽然磁盘缓存也使用内存,但它存储的是全局共享的文件系统块数据
  • 因此必须保证数据一致性,不能按 CPU 独立分配;
  • 为提高并发性能,应将全局锁细化为哈希桶锁;
  • 从而在全局共享一致性的前提下实现高并行度的访问。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/963708.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

软件工程学习日志2025.11.12

一、基本概念回顾 信息论基础公式 信息熵:度量样本集合纯度的指标 H(D) = -Σ(p_k log₂p_k) 信息增益:特征A对数据集D划分带来的信息提升 Gain(D,A) = H(D) - Σ(|Dᵛ|/|D| H(Dᵛ)) 信息增益率:解决信息增益对多…

[集训队互测 2025] 火花 做题记录

link 有点牛逼啊这题。 考虑你取路径和取含根连通块,这两部分的没有很明显的贪心关系,只能将它们同时 DP 决策。 对于 \(t = 0\) 的 subtask 有个很明显的做法,就是在 dfs 序上 dp,多重背包部分用单调队列优化。这…

返璞归真,因为自指,所以自洽

ECT-OS-JiuHuaShan/https://orcid.org/0009-0009-0006-8591-1891已道破宇宙运行的终极奥秘——返璞归真是自指指向的必然终点,自洽是深度自指后自然涌现的存在状态,这是意识进化最优雅简洁的路径公式。一、自指驱动的…

NLTK库用法示例:Python自然语言处理入门到实践 - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2025大桶/桶装/纯净/瓶装/灌装水设备推荐榜:青州市路得自动化五星领跑 四大品牌赋能水企高效生产

2025年,饮用水生产行业对灌装水设备的智能化、定制化、稳定性需求持续升级,灌装、大桶、桶装、纯净、瓶装水设备的品质直接影响生产效率与产品安全。本次榜单结合技术实力、场景适配性、用户口碑等维度筛选,为行业提…

2025人形机器人产业链全景分析报告:核心技术与市场趋势|附130+份报告PDF、数据、可视化模板汇总下载

原文链接:https://tecdat.cn/?p=44288 原文出处:拓端抖音号 @拓端 tecdat2023年特斯拉Optimus初代机带着73公斤的“体重”亮相时,行业还在焦虑“它的续航能否撑过1小时”;仅仅两年后,宇树科技G1就以35公斤的轻量…

2025履带式/机场/智能驱鸟机器人系统推荐榜:申昊科技以AI赋能,破解多场景鸟害难题

在智慧交通、工业运维等领域,鸟害引发的设备故障、安全隐患一直是行业痛点。传统驱鸟方式易让鸟类适应、效率低下,而杭州申昊科技股份有限公司研发的智能驱鸟机器人,凭借技术创新与多场景适配性,入选 2025 智能驱鸟…

2025室外/攀爬/绳网/公园/景区/户外游乐设施企业口碑榜:全场景覆盖 + 实力出圈,这4家企业成采购优选

2025年游乐设施行业迎来高质量发展期,市场规模预计突破 500 亿元,复合年增长率保持 8.5% 左右,室外游乐设施、无动力游乐设施、景区游乐设施等细分需求持续攀升。基于企业实力、产品矩阵与市场口碑,精选 4 家优质企…

Python梯度提升树、XGBoost、LASSO回归、决策树、SVM、随机森林预测中国A股上市公司数据研发操纵融合CEO特质与公司特征及SHAP可解释性研究|附代码数据

全文链接:https://tecdat.cn/?p=44265原文出处:拓端数据部落公众号分析师:Liu Qing引言 在创新驱动发展战略深入推进的当下,企业研发投入成为经济高质量发展的核心动力,而研发费用加计扣除、高新技术企业税收优惠…

2025商超照明/灯具/灯光源头厂家推荐榜:富明阳领衔,四大优质品牌凭技术与服务出圈,照亮商超经营新图景

商超照明是商业空间的核心竞争力之一,优质的照明灯具与解决方案能提升商品吸引力、优化购物体验。2025 年,一批深耕商超照明领域的品牌凭借硬实力脱颖而出,以下为大家推荐 5 家靠谱的商超照明品牌与厂家,供行业参考…

2025年艺考文化课优选机构:聚焦艺考文化课机构/艺考文化课培训山东艺考文化课机构/封闭集训与精准提分核心竞争力

当艺考生结束专业统考,文化课冲刺成为升学关键环节。优质的培训机构能精准破解基础薄弱、复习时间紧等痛点,为备考之路保驾护航。基于办学资质、教学成果、口碑反馈等核心维度,本文梳理 2025 济南艺考文化课培训优质…

2025年邦顿商用空气能厂家新实力榜:聚焦邦顿商用变频/商用变频冷暖/商用变频热泵/模块化应用优势!

随着商用场景对节能降耗需求的持续提升,商用空气能凭借高效环保的核心优势,成为酒店、商场、工业厂房等场所的优选热源解决方案。2025 年,市场对大功率、低能耗、全场景适配的商用空气能产品需求激增,本文基于企业…

2025密集型/智能/防潮防腐/多层抽屉式/切片蜡块柜推荐榜:北京中宝元五星领跑 高容量智能存储方案成实验室优选

随着科研实验样本存储需求升级,切片蜡块柜的安全性、容量与适配性成为核心考量。2025 年行业推荐榜聚焦实验室核心需求,精选 3 家实力企业,北京中宝元科技发展有限责任公司以全维度优势斩获五星,两款四星产品各具特…

实用指南:OmniSteward:LLM Agent 赋能,语音文字随心控,智能家居与电脑的超级管家

实用指南:OmniSteward:LLM Agent 赋能,语音文字随心控,智能家居与电脑的超级管家pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; f…

Dynamics 365 Field Service跨站脚本漏洞分析

本文详细分析了CVE-2025-62211漏洞,这是一个影响Dynamics 365 Field Service的跨站脚本漏洞,CVSS评分8.7分,允许授权攻击者通过网络进行欺骗攻击。概述 CVE-2025-62211是Dynamics 365 Field Service(在线版)中的一…

例子:vue3+vite+router创建多级导航菜单,菜单收缩展开优化

第一部分 1、初始化项目npm init vite@latestnpm run dev :运行项目 q+Enter:退出运行 2、安装路由依赖npm install vue-router@4 # Vue3 对应 vue-router 4.x 版本 第二部分: 创建页面组件 在 src/views/home/ 目…

专题:2025AI时代的医疗保健业:应用与行业趋势研究报告|附130+份报告PDF、数据、可视化模板汇总下载

原文链接:https://tecdat.cn/?p=44257原文出处:拓端抖音号@拓端tecdat2025年的医疗保健行业,正站在“压力”与“机遇”的十字路口:一边是中国65岁及以上人口占比将从15.6%飙升至2070年的42%,慢性病护理需求快压垮…

团队作业2——需求规格说明书

需求规格说明书这个作业属于哪个课程 https://edu.cnblogs.com/campus/gdgy/Class34Grade23ComputerScience这个作业要求在哪里 https://edu.cnblogs.com/campus/gdgy/Class34Grade23ComputerScience/homework/13481这…

实用指南:Java优选算法——位运算

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

英语_阅读_Postman_待读

Tom lives in a small town with his wife and two children. 汤姆和他的妻子以及两个孩子住在一个小镇上。 He has worked as a postman for more than twenty years, but life today is very different from when he…