SchoolWork-LaTeX/操作系统/实验报告/Lab3.tex

113 lines
7.9 KiB
TeX
Raw Permalink Normal View History

2024-09-02 17:47:53 +08:00
\documentclass[a4paper]{ctexart}
\input{mypreamble}
\renewcommand{\mychapternum}{3}
\renewcommand{\mylabname}{虚拟内存管理}
\renewcommand{\mydate}{2024年5月7日}
\begin{document}
\mytitle
\begin{enumerate}
\item{\textbf{研读理解相关代码后,回答以下问题:}}
\begin{enumerate}
\questionandanswer[]{
uCore 中的段页式存储管理方案与理论课中讲述的方案有何不同?
}{
$\mu$Core 中简化了分段机制,将逻辑地址直接恒等映射到线性地址,之后使用分页机制将线性地址通过分页映射到物理地址。由于使用了分页机制,因此需要对空闲物理块管理,对空闲物理块的管理使用了链表来管理,链表按照地址排序。
跟我们理论课中的“段页式存储管理”和“使用链表管理存储空间”的方案相似,不同之处在于分段机制简化了,并且只使用链表管理了空闲物理块(已分配的物理块在页表中有记录,所以不需要管理)。
}
\questionandanswer[]{
试简述uCore中缺页异常的处理过程它与理论课中讲述的过程有何不同
}{
在vmm.c的注释中有这样一行
\mint{C}| * CALL GRAPH: trap--> trap_dispatch-->pgfault_handler-->do_pgfault|
显然,在$\mu$Core中缺页异常从\mintinline{C}{trap}触发,之后通过\mintinline{C}{trap_dispatch}根据中断号(\mintinline{C}{tf->tf_trapno}分发给不同的处理程序,这里是缺页中断(\mintinline{C}{T_PGFLT}),所以分发给\mintinline{C}{pgfault_handler},再调用\mintinline{C}{do_pgfault},之后在\mintinline{C}{do_pgfault}中找到一个pte并且分配内存或者从交换分区换入一个页面或者由于访问权限不正确而直接返回失败。
与理论课中讲述的过程的不同是进行了简化,取消了快表,也就是只有一级索引而没有二级索引。
}
\questionandanswer[]{
为了支持页面置换在数据结构Page中添加了哪些字段其作用是什么
}{}
{\kaishu
\begin{minted}[fontsize=\zihao{-5}]{C}
struct Page {
int ref; // page frame's reference counter
uint32_t flags; // array of flags that describe the status of the page frame
unsigned int property; // the num of free block, used in first fit pm manager
list_entry_t page_link; // free list link
list_entry_t pra_page_link; // used for pra (page replace algorithm)
uintptr_t pra_vaddr; // used for pra (page replace algorithm)
};
\end{minted}
添加了\mintinline{C}{pra_page_link}\mintinline{C}{pra_vaddr}这两个字段,\mintinline{C}{pra_page_link}是用来将物理块组织成FIFO队列使用链表实现用来进行页面置换的\mintinline{C}{pra_vaddr}是物理块对应的虚拟地址,用来记录访问哪个虚拟地址的时候产生的缺页,以便进行页面置换。
}
\questionandanswer[]{
请描述页目录项页(PDE)和页表目录项(PTE)的组成部分对uCore实现页面置换算法的潜在用处。请问如何区分未映射的页表表项与被换出页的页表表项请描述被换出页的页表表项的组成结构。
}{
用处在于记录某个页面在内存中还是在外存对换区中以及对应物理地址在内存中或者offset在外存对换区中在下次页面换入或换出时确保页面被放到正确的位置上。
由于未映射的页表表项全是0所以被换出的页的offset从1开始以区分。这样如果页表表项全是0就说明是未映射如果在offset高24位中存在1那么就是被换出的。
被换出页的页表表项复用了pte的结构\mintinline{C}{memlayout.h}中有这样一行:
\mint{C}|typedef pte_t swap_entry_t; //the pte can also be a swap entry|
再根据示意图:
\begin{center}
\includegraphics[width=0.5\linewidth]{imgs/2024-05-10-08-49-47.png}
\end{center}
可以看到其高24位为offset代表在外存对换区里的位置存在位最低位为0表示此页面不存在对应的物理块中间的7位都保留暂不使用。
}
\end{enumerate}
\item \textbf{程序设计与实现的基本思路}
\begin{enumerate}
{\kaishu
\item$\mu$Core中原先实现的是FIFO页面置换算法这里要改成第二次机会页面置换算法可以发现页面的组织方式不需要更改仍然使用链表每次插入页面时仍然是添加到链表头部不需要更改只需要更改换出页面的算法即可。
\begin{center}
\includegraphics[width=0.9\linewidth]{imgs/2024-05-10-09-00-25.png}
\end{center}
\item 课上讲的这张示意图右侧是链表的头部左侧是链表的尾部每次插入的页面在最右侧即链表的头部。当需要换出页面时从左侧链表尾部取出一个页面如果这个页面的访问位是1那么将其访问位改为0并放到右侧链表头部。接着再从左侧链表尾部检测下一个页面直到找到一个访问位为0页面的作为换出的页面。所以可以写出代码如下
\begin{minted}{C}
// 从后往前,最后面的是最早访问的
list_entry_t *current = head->prev;
list_entry_t *le = NULL;
for (; current != head; current = current->prev) {
pte_t *ptep = get_pte(mm->pgdir, le2vma(current, vm_start), 0);
if (*ptep & PTE_A) { // 访问位为1
*ptep &= !PTE_A; // 清除访问位
list_del(current); // 从链表中移除
list_add(head, current); // 添加到链表头部
} else {
le = current;
break;
}
}
\end{minted}
\mintinline{C}{le}即为最终的找到的用来换出的页面。
\item 当然还需要完善一些问题。当页面只有一个并且访问位为1时从链表中移除此页面再放入后链表结构并未改变所以下一次的\mintinline{C}{current}指向链表头结点,循环退出了,但此时\mintinline{C}{le}还是空的!但期望的返回结果应该是这一个页面,所以需要对这种情况进行处理:
\begin{minted}{C}
if (le == NULL) {
le = head->prev; // 循环一遍找不到就最后一个
}
\end{minted}
当循环一遍仍然找不到可以换出的页面的时候就选择最后一个页面和FIFO一样作为换出的页面。当然其实使用第二次机会页面置换算法的话页面大于一个的时候必定能找到一个换出的页面的请自行验证而且也不会出现页面为0个情况总不能页表数量为0吧所以其实这样就只是解决了页面只有一个时的异常。
\item 测试代码\mintinline{C}{_fifo_check_swap}仍然需要修改因为使用第二次机会页面置换算法缺页次数肯定与FIFO算法不尽相同。测试代码中的\mintinline{C}{pgfault_num}即为缺页次数。
\item 由于时间紧迫一些细节可能没有考虑周到如有发现错误欢迎在下方的链接中提Issue。
}
\end{enumerate}
\myitem{代码}{
\item \url{https://gitea.shuishan.net.cn/10213903403/os_kernel_lab}
\item 也可以看上传的附件。
}
\end{enumerate}
\end{document}