- 博客(51)
- 收藏
- 关注
原创 MIT6.s081 2021 Lab File system
xv6 文件系统的 inode 中地址域addrs[]由 12 个直接地址和 1 个一级间接地址组成,本实验要求将地址域更改为 11 个直接地址、1 个一级间接地址和 1 个二级间接地址组成,以支持更大文件的存储。代码的实现有了直接地址和一级间接地址做参考,就很简单了,直接查看代码部分即可。
2024-08-16 19:37:49
425
原创 MIT6.s081 2021 Lab Multithreading
xv6 已经实现了进程的切换机制,本实验要求参考进程的切换,实现一个用户态线程的切换。要实现线程切换,必然涉及上下文,即寄存器的保存和恢复,那么需要保存哪些寄存器?实际上,只需要保存被调用者保存寄存器(callee-saved registers),而实现调用者保存寄存器(caller-saved registers)的保存与恢复的代码由编译器自动生成。关于调用者保存与被调用者保存寄存器有哪些可以参照下述 RISC-V 的 calling convention:另外,根据的注释,最后通过ret。
2024-08-14 16:25:27
686
原创 MIT6.s081 2021 Lab Copy on-write
xv6 使用fork()系统调用创建子进程时,需要将父进程的地址空间进行,即将页表和实际物理空间同时进行拷贝,以实现父进程和子进程地址空间的独立性。但很多时候,如 shell 程序,fork()通常与exec()搭配使用,首先使用fork()创建子进程,随后在子进程中使用exec()将指定的程序加载到当前地址空间,这样在fork()中进行的地址空间拷贝就白白浪费了。本实现要求实现一个写时复制(copy-on write)的fork()系统调用。
2024-08-13 17:59:28
844
原创 MIT6.s081 2021 Lab Page tables
题目要求在每个进程初始化时为它的页表插入一个页表项,内核通过这样预先缓存页表项的操作,来加速特定系统调用的执行速度。遍历空闲链表,寻找一个可分配的物理页面。若找到,返回该页面的首(物理)地址;否则,返回 0 (空指针)。释放已分配的首地址为pa的物理页面,并更新空闲链表。遍历进程数组proc,寻找未被使用的。若找到,则初始化其状态,为创建一个新的,并返回指向它的指针;否则,返回 0(空指针)。释放与进程p相关的数据的内存空间,并清空p的的所有信息。在页表pagetrable中创建从起始虚拟地址va。
2024-07-01 15:21:38
885
原创 MIT6.s081 2021 Lab System calls
不同于 Lab1 利用已实现的系统调用来实现一些用户态下的命令行程序,本 Lab 是要在内核层面实现一些系统调用。这其中难免涉及到一些对内核数据结构的操作,以及处理器体系结构(本系列 Lab 基于 RISCV)相关的内容,那么首先有必要梳理一下 xv6 下系统调用的实现过程。tracetrace:这是一个Perl脚本的“shebang”行,指定使用解释器执行此脚本,并开启警告(-w)选项。:打印注释说明此文件是由usys.pl脚本自动生成的,不应手动编辑。:输出一条预处理器指令,包含一个名为。
2024-06-27 11:51:03
622
原创 MIT6.s081 2021 Lab Utilities
按照示例切换到util分支后,看到目录下包含Makefile文件,执行make qemu即可。
2024-06-24 21:09:17
1095
原创 OSTEP Projects:KV
本文将介绍操作系统导论(Operating Systems: Three Easy Pieces)作者所开源的操作系统相关的 KV 部分,包含个人的代码实现和设计思路。more。
2024-05-10 21:20:47
367
2
原创 OSTEP Projects:Reverse
本文将介绍操作系统导论(Operating Systems: Three Easy Pieces)作者所开源的操作系统相关的 Reverse 部分,包含个人的代码实现和设计思路。more。
2024-05-06 19:55:48
412
原创 OSTEP Projects:Unix Utilities
本文将介绍操作系统导论(Operating Systems: Three Easy Pieces)作者所开源的操作系统相关的 Unix Utilities 部分,包含个人的代码实现和设计思路。more。
2024-05-04 18:30:59
512
原创 高效的区间二叉搜索树:线段树
与树状数组类似,线段树也是一种用来维护区间信息的数据结构,可以在对数时间复杂度内实现更新和查询等操作。但相较于树状数组多用于前缀和查询不同,线段树的应用范围更为广泛,例如区间最值等问题,代价是需要消耗更多的存储空间。more。
2024-03-18 14:57:54
417
原创 动态前缀和数组:树状数组
前缀和是一种常见的算法思想,能够实现在常数时间复杂度下得到某个子区间内所有元素和。以一维数组 nums 为例,定义前缀和数组 preSum,preSum[i]表示 nums 前 i 个元素的和,利用动态规划的思想,易得的递推关系,因此构造一个前缀和数组的时间复杂度为 O(n),而查询前 i 个元素的和只需查询preSum[i]的值,为常数时间。
2024-03-04 15:22:09
853
原创 从机器指令的角度看一些位级操作
C/C++ 中有时会遇到一些位级操作,通常是一些隐式的类型转换,它们往往很难凭借高级语言层面的直觉来理解或记忆。本文旨在分析这些操作对应的汇编代码,从机器指令的角度来理解这类操作。more。
2024-01-19 21:52:05
441
原创 二分搜索的几种写法与常见问题
最近在比赛和刷题的时候经常遇到二分答案的题,但时不时会因为一些细节上的错误而浪费时间,本文旨在整理常见的二分搜索的写法、二分搜索可能会遇到的一些小问题,以及C++中与二分搜索相关的库函数,以免今后再犯类似的错误。
2023-09-18 11:58:13
271
原创 算法分析与设计编程题 回溯法
中搜索状态,每种状态下需要 O(n) 时间来进行最优解的更新,因此两种算法的渐进时间复杂度都为 O(n * 2。(n 为被搜索对象的数目,在本例中为货物的总数)。由于递归回溯的本质可以看作是对一棵二叉树进行的搜索,每次选或者不选都将产生两个分支,那么所有情况的数量为 2。有没有被选择,通常用 1 代表被选择,0 代表不被选择。,关注它的 n 位二进制形式,其中 mask 的第 i 位二进制位就代表对应的货物。了,可以遍历 0~n-1 的所有整数 i,并将其右移 i 位,将。事实上,对于此类涉及。
2023-09-14 22:19:37
210
原创 王道数据结构编程题 图
已知无向连通图 G 由顶点集 V 和 边集 E 组成,当 G 中度为奇数的结点个数为不大于 2 的偶数时,G 存在包含所有边且长度为 |E| 的路径(称为 EL 路径),假设图采用邻接矩阵存储。分别采用基于深度优先遍历和广度优先遍历算法判别以邻接表形式存储的有向图中是否存在由顶点 vi 到顶点 vj 的路径(i ≠ j)。假设图用邻接表表示,设计一个算法,输出从顶点 vi 到顶点 vj 的所有简单路径。写出图的深度优先搜索 DFS 算法的非递归算法(图采用邻接表形式存储)。
2023-09-09 22:23:23
181
原创 王道数据结构编程题 栈和队列
假设 I 和 O 分别表示入栈和出栈操作,栈的初态和终态均为空,入栈和出栈的操作序列可表示为仅由 I 和 O 组成的序列,可以操作的序列称为合法序列,否则称为非法序列。编写一个算法,判定所给的序列是否合法。若合法,返回 true,否则返回 false.
2023-09-09 22:21:54
242
原创 王道数据结构编程题 顺序表
从顺序表中删除具有最小值的元素(假设唯一)并由函数返回被删元素的值。空出的位置由最后一个元素填补,若顺序表为空,则显示出错信息并退出运行。
2023-09-09 22:18:40
152
原创 有关C++字符串拷贝的一个小问题
最近面试被问到了一个 C++ 中的小问题,就是如果有字符串 s1 和 s2,将 s1 赋值给 s2 后,它们的内存分布是什么样的。当时感觉可能是共享的,但也不太确定,回来后查阅资料发现结果并不是那么简单。more。
2023-04-04 16:49:37
155
原创 计算机基础面试题总结
大端和小端是指在多字节数据类型的存储方式中,高位字节和低位字节的存储顺序。大端模式是指高位字节存储在低地址,低位字节存储在高地址;小端模式是指低位字节存储在低地址,高位字节存储在高地址。死锁是指两个或多个进程在执行过程中,因争夺资源而造成的一种僵局,若无外力作用,它们都将无法继续执行下去。分段是将程序分成若干个逻辑段,每个段可以包含一个模块或若干个模块,每个段的长度是不固定的,每个段都有一个段名和段长,段名是一个符号,段长是指该段所包含的字节数。
2023-04-04 16:48:07
760
原创 C++面试题总结
野指针是指指向不可用内存的指针,可能会导致内存泄漏和程序崩溃。const 定义的常量是变量,带有数据类型,而 define 定义的常量是预处理器替换的文本,不带数据类型。const 定义的常量在编译运行时起作用,可以进行调试,而 define 定义的常量在预处理阶段起作用,不能进行调试。const 定义的常量可以进行作用域限制,而 define 定义的常量没有作用域的概念。const 定义的常量可以进行类型检查,而 define 定义的常量不能进行类型检查。
2023-03-24 12:41:48
485
原创 Ping命令的实现
Ping (Packet Internet Groper)是一种因特网包探索器,用于测试网络连接量的程序。本文将基于 Socket 编程,实现一个基本的 Ping 命令程序。
2022-06-03 09:43:13
1998
7
原创 使用遗传算法解决旅行商问题
遗传算法(Genetic Algorithm,GA)最早是由美国的 John holland于20世纪70年代提出,该算法是根据大自然中生物体进化规律而设计提出的。是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法。本文利用遗传算法解决经典的NP问题——旅行商问题,并加深对该算法的理解。问题描述有若干个城市,每个城市给定一个坐标,一个旅行商需要经过每个城市各一遍且不能重复经过城市,起点可以任意选择,求旅行商经过所有城市的总距离的最小值及其最
2022-05-26 12:57:23
7031
13
原创 停止等待协议的模拟实现
协议原理设计思路基本传输本次实验我采用了程序模拟的方式实现。发送方和接收方都为一个数组,传输过程即为发送方数组向接收方数组传递数据,并使用随机数生成的方式模拟传输过程中可能出现的差错,并且传输时间也为一个在 50 - 150 ms 间的随机数,用一个迭代器来模拟此时发送方的数据位置。传输过程为一个循环语句,终止条件为发送迭代器到达发送方数组的末尾位置。选择重传每次进行传输,传输时间就会累加,在一轮传输的最后判断累计时间是否超过了规定 tout,如果未超过,代表数据成功接收,发送迭代器自增 1。
2022-05-06 16:54:41
1370
原创 使用K-means算法进行聚类分析
本文将介绍如何使用 K-means 算法对给定的坐标数据进行聚类分析。使用K-means算法进行聚类分析问题描述K-means算法对data中数据进行聚类分析(1)算法原理描述(2)算法结构(3)写出K-means具体功能函数(不能直接调用sklearn.cluster(Means)功能函数)具体函数功能中返回值包括 数据类标签,累中心,输入包括:数据,类别数(4)可视化画图,不同类数据采用不同颜色(5)算法分析类类方差,平均方差,不同初始点对聚类结果的影响?如何解决?算法描述
2022-05-06 16:54:29
3629
原创 使用AStar算法解决八数码问题
八数码问题是一个经典的搜索问题,本文将介绍如何使用启发式搜索—— AStar 算法来求解八数码问题。问题描述八数码问题的A星搜索算法实现要求:设计估价函数,并采用c或python编程实现,以八数码为例演示A星算法的搜索过程,争取做到直观、清晰地演示算法,代码要适当加注释。八数码难题:在3×3方格棋盘上,分别放置了标有数字1,2,3,4,5,6,7,8的八张牌,初始状态S0可自己随机设定,使用的操作有:空格上移,空格左移,空格右移,空格下移。试采用A*算法编一程序实现这一搜索过程。算法描述
2022-04-28 00:41:48
3281
原创 C++代码优化 Chapter2
本文将继续介绍一些常见的 C++ 代码优化技巧,本文为该系列的第二章,未来不定期更新。非必要时使用常量引用在上一章我们介绍了在进行函数的参数传递时,尤其对于所占内存空间较大的参数的传递,为了避免拷贝所带来的不必要的性能开销,应当尽量使用引用传递。并且,当该函数不需要对传入的参数进行更改时,应当在参数类型前添加 const 关键字表示这是一个常量引用。可能有朋友认为这里的 const 关键字的添加并不是必要的,但这样会带来两个问题:首先便是程序的可读性的下降,如果不添加 const 关键字,用户可能会
2022-04-19 15:37:19
443
原创 循环语句中指针赋值出错
最近在写人工智能作业的时候遇到了一点问题,就是在循环语句中对指针类型赋值出现错误,导致所有的结点的前驱指针最终指向自身。问题描述以下使用一个简单的示例来模拟当时出现的问题。MyStruct 为一个自定义结构体类型,包含数据成员 val 和前驱结点 pre。首先将初始结点(0,nullptr)加入队列 Q,随后在每次循环中,用变量 fs 接收队列 Q 的队首元素并将其出队,并根据该结点生成一个新结点,该新结点 val = fs.val + 1,且将其前驱结点设为 fs 并加入到队列 Q 中。直到 fs
2022-03-31 10:00:21
4815
原创 OpenGL入门 矩阵堆栈实现简单行星系统
本文介绍如何使用矩阵堆栈原理实现简单的行星运行系统。原理有时我们需要在一个场景中绘制不同的模型,如果这些模型彼此间没有联系,即各模型的位置不会相互影响,那我们只需要单独为每个模型创建合适的变换矩阵,并经过渲染管线将其渲染即可。而对于一个位置会相互影响的系统而言,例如行星运行系统,地球围绕太阳公转,而月球围绕地球公转。处理这样问题的关键在于如何确定各物体变换矩阵,准确来说是模型-视图矩阵。而矩阵堆栈可以很好地将这问题简化。所谓矩阵堆栈,就一个用来存储变换矩阵的堆栈结构,栈顶矩阵为栈底矩阵乘上另一个矩阵
2022-03-18 10:18:35
706
原创 子集生成算法
本文介绍生成一个集合子集的两种常见算法,借此从中深入理解搜索问题中常见的两种思路。递归回溯思路对于集合中的每个元素,我们都有选择和不选择两种处理方式,这种思路类似于二叉树的遍历,每种情况都向下衍生出两种情况,最终当遍历到下标 index = nums.size() 时,将生成的子集保存。由于此处我们使用一个数组的引用来保存子集元素,因此在递归回溯时,我们需要手动将上一步中加入添加的元素去除,来回溯到该元素未被选择的状态。代码class Solution {private: std::vec
2022-03-16 10:29:30
1285
原创 C++代码优化 Chapter1
本文将介绍一些常见的 C++ 代码优化技巧,本文为该系列的第一章,未来不定期更新。使用前置递增(递减)运算符可能很多从 C 语言开始学习的朋友会对此感到困惑,觉得这两者在适用的情况下可以任意选择,如 for 循环语句写作 for (int i = 0; i < n; i++) 。这样做当然没错,但会造成一定程度上的资源浪费,因为后置递增运算符需要先将原本的变量值保存下来,再对其进行递增操作,而在此 for 循环中,我们并不需要使用原本的 i 值。并且 ++i 的写法相对来说更符合我们的意愿。当
2022-03-08 13:21:37
731
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人