Stanford CS144 For Computer Network(二):Lab0 Networking Warmup
Lab0 Networking Warmup
Lab0实验手册: https://vixbob.github.io/cs144-web-page/assignments/lab0.pdf(2021
Fall)
部分实验目的和内容摘抄自手册。
Networking by hand
这一小节只是简单的网络实验,不涉及代码,围绕telnet、netcat的一些操作展开,无兴趣的可以跳过。
Fetch a Web page
打开浏览器,访问http://cs144.keithw.org/hello,你会看到Hello, CS144!;
现在虚拟机可以做同样的事情,Linux下运行: 1telnet cs144.keithw.org http
这个命令建立你和另一台计算机(cs144.keithw.org)的可靠字节流,并且运行万维网使用的http(Hyper-Text
Transfer
Protocol,超文本传输协议)服务。telnet和ssh类似,都是用于远程登录或管理设备的网络协议,但telnet的数据以明文发送,仅支持基本用户名-命名验证,没有文件传输能力,基本 ...
Stanford CS144 For Computer Network(一):环境搭建
大三学过计算机网络,后面就没有碰过这门课了。那时候的教材是谢希仁教授的《计算机网络》,为了应付期末考试还将课件和资料整理成了上万字的文档,放到校内网去低价出售,不知道光顾的那几位老哥考得咋样,可能不如多看几道课后题考得高分,多少有点误人子弟(哭),计算机网络是一个庞大的课程,往下它可以和硬件层各种协议交流,网上它需要提供应用层的各种软件接口,作为EE专业的主修课,授课的时候更倾向于信号处理、电路连接等联系,后面选修的《网络体系空间结构》更是承接了这个特点,几乎没有从代码的角度构建过这些通信协议,Stanford
CS144利用C++以及容器算法,围绕TCP协议开展实验,技术栈还是比较匹配的,就尝试做做吧。
一个有意思的插曲是斯坦福的老师在2019年开源了这个项目,后续又出了2021、2023等多个版本,但是后面因为考虑到自己的学生可能会直接从开源仓库获取答案,遂关闭了官方仓库,要求其他仓库克隆者也应该将仓库转为private,一位清华大佬希望只去除“CS144”防止被google索引,而且回复道:
I think opensourcing is irrelevant to w ...
操作系统MIT 6.S081 xv6内核(十):File System实验
前置提醒
fs分支的文件系统布局和常规xv6布局是不一样的,常规情况下,文件系统的磁盘布局是:46个元数据块(boot、super、30
log、13 inode 、1
bitmap)、954个数据块;fs分支下:70个元数据块(boot、super、30
log、13 inode 、25
bitmap)、199930个数据块;因为它需要支持二级Inode索引,知晓这点再去看代码(指系统代码,不是实验代码)才会理解。
Large files实验
实验目的
看过Inode层理论或者我的基础理论一文,就知道xv6文件大小的限制是每个Inode只能存放256+12个块大小,因此这里需要我们牺牲一个Direct
Number,用于创建二级Indirect Number,这种提升是明显的,因为每个Indirect
Number指向256个,二级的Indirect Inode存储的块是11+256+256*256;
具体实现
这个实现比较简单,只要看一下kernel/fs.c哪些代码涉及间接Indirect
inode设计即可,即bmap函数和itrunc函数,前者负责将 ...
操作系统MIT 6.S081 xv6内核(九):Lock实验
Memory allocator实验
实验目的
目前的页帧分配共用一个大锁kmem.spinlock和一个共用空闲页帧链表kmem.freelist,也即无论哪个CPU想要通过kalloc获取页帧,都需要首先从这个共享的数据结构获取锁和页帧,理论和实验表明这个设计是导致race condition最严重的事件之一,导致性能瓶颈;本节的实验旨在通过为每个CPU都维护一个独享的锁和页帧空闲分配链表,以降低进程内存分配时的严重竞争条件。此外还需要考虑当当前CPU耗光页帧时,如何从其他的CPU安全地“窃取”空闲页帧。
具体实现
从kernel/param.h获知了系统最大CPU核心数定义,这也是CPU遍历的基本原理;
1#define NCPU 8 // maximum number of CPUs 通过kernel/proc.c函数可以获取当前CPU编号:
123456intcpuid() {int id = r_tp();return id;} 全部代码仅在kernel/kalloc.c修改即可:
将kmem设计 ...
操作系统MIT 6.S081 xv6内核(八):Multithreading实验
Uthread: switching
between threads实验
实验目的
实现一个用户级的线程切换:测试程序user/uthread.c会创建三个线程,每个线程打印一个语句,大部分逻辑已经完成,只剩下context切换逻辑。抢占式中断因为经过陷入机制,因此流程是比较繁琐的。核心的切换是在内核中调用yield,yield调用sched,sched做了一些故障检查,就调用了swtch,从这里我们会进入线程调度器线程,保存14个用户进程的内核寄存器,并且返回到scheduler函数调用的swtch函数,去除原来进程信息、释放锁,此后调度器又将另一个线程装载,调用swtch,并且从当前新进程的sched调用的swtch返回。继续执行陷入处理
直至恢复执行;
在用户级线程切换设计测试代码中,则省去了很多繁琐的跳转步骤;首先thread_schedule模拟了一部分scheduler函数功能,将线程存储在all_thread数组中,最大线程数量为4;线程初始化时取第一个线程,现在只需要解决两个问题:
线程如何执行程序?
如何实现线程的切换?
具体实现
直接看代码 ...
操作系统MIT 6.S081 xv6内核(七):Copy-On-Write Fork实验
Implement copy-on write实验
实验目的
本节实验不是最难的一个,但是逻辑细节比较多(所以坑也多),也让我花了不少时间去打印和调试。本节和上一节页懒分配类似,都是利用Page
Fault特性向xv6增加一些扩展。主要目的是,每次系统启动父进程会通过fork函数创建子进程,系统为子进程分配与父进程大小相当的空间,例如shell进程占4个页帧(4*4096字节),子进程也会分配新的4个字节;然而子进程很快就会被exec占据并且去运行其他进程,大部分情况下这新分配的空间没有被使用就被丢弃了,既浪费了内存也消耗了启动性能。
因此本节核心思想是在调用fork复制父进程时,不要直接为子进程分配物理内存,而是通过页表将子进程的虚拟地址也指向父进程的物理内存(暂且称其为COW内存);为了保证这个物理内存的安全,在共享后必须将物理内存的写权限取消成为只读内存,当子进程确实需要空间时,对该物理内存进行写操作就会造成Page
Fault;而又为了区分进程是对这种COW内存操作,还是真的误读了其他只读的页帧,我们需要引入新的标志位PTE_COW来区分两种只读页面。
为了处理这个 ...
操作系统MIT 6.S081 xv6内核(六):Lazy Page Allocation实验
Eliminate allocation from
sbrk()实验
没有实验,只谈现象
这是Fans教授在课上提到的现象,在基础理论一文的Lazy
Allocation一节我也具体剖析过,看完不难理解:只增加了虚拟内存,uvmunmap释放了虚拟内存指向的不存在的物理内存。
Lazy allocation实验
实验目的
实现一个简单的Lazy
allocation,要求进程使用sbrk进行内存分配时不要直接满足,引入懒分配策略等到进程使用到了再申请物理内存,如果设计是成功的,那么shell能够正常运行echo hi命令。
具体实现
这是一个简单的Lazy
allocation实现,在基础理论已经实现并且做了剖析讨论,看过基础理论或者课程的可以直接跳到第三个实验。具体步骤是在kernel/sysproc.c中sbrk函数增加虚拟内存,取消物理内存分配
123 myproc()->sz=myproc()->sz+n;//new//if(growproc(n) < 0)// return -1; 这个改动会得到page
fault,因此需要在k ...
VMware Ubuntu配置静态IP
以前习惯在VMware直接做命令,现在使用Vscode比较多。但是远程SSH的问题在于虚拟机会不定期更新内网IP,规律是:重启不一定更新、关机不一定更新,电脑关盖子睡眠一定更新。。。非常奇怪,导致每次都要重新打开工作区。
尝试配置静态IP,环境为:
Ubuntu 18.04
VMware 16
NAT模式
总体而言基本没有遇到困难,但是发行版不同、文件、步骤都不一样,也容易踩坑,所以记录一下。
Win10打开“虚拟网络编辑器”,选中NAT桥接VMnet8,设置子网IP和子网掩码;子网IP第三个网段自行设置成以前常用的。
进入NAT设置,将网关设置成“192.168.xxx.1”,xxx和步骤1保持一致。
Win10打开设置——更改适配器选项;
在Ipv4协议属性中设置IP地址,子网掩码,默认网关和DNS;默认网关保持和刚刚设置的一致。
上面的IP只是基本的设置,还不是我们要设置的静态IP
进入虚拟机,如无意外/etc/netplan下会存在一个yaml网络配置文件,按照下文增加和修改配置,addresses是要使用的静态IP,d ...
操作系统MIT 6.S081 xv6内核(五):Traps实验
RISC-V assembly实验
没有实验,回答问题
阅读call.asm中函数g、f和main的代码:
哪些寄存器保存函数的参数?例如,在main对printf的调用中,哪个寄存器保存13?
答:函数参数从a0到a7存储,13是第三个参数,所以是a2保存;
main的汇编代码中对函数f的调用在哪里?对g的调用在哪里(提示:编译器可能会将函数内联)
答:提示已经给出答案,汇编代码的sp没有变动,也没有存入ra,说明没有进行函数调用,f8已经被函数内联优化并且提前算出答案11了,这一行调用就是打印12、13;
printf函数位于哪个地址? 调用位置在 1230: 00000097 auipc ra,0x034: 5e6080e7 jalr 1510(ra) # 616 <printf>
答:存入pc0x30到ra,1510的16进制对应0x5e6,所以跳转地址是二者相加0x616;
在main中printf的jalr之后的寄存器ra中有什么值 ...
操作系统MIT 6.S081 xv6内核(四):Page Table实验
Print a page table实验
实验目的
当您启动xv6时,它应该像这样打印输出来描述第一个进程刚刚完成exec(),init时的页表:
12345678910page table 0x0000000087f6e000..0: pte 0x0000000021fda801 pa 0x0000000087f6a000.. ..0: pte 0x0000000021fda401 pa 0x0000000087f69000.. .. ..0: pte 0x0000000021fdac1f pa 0x0000000087f6b000.. .. ..1: pte 0x0000000021fda00f pa 0x0000000087f68000.. .. ..2: pte 0x0000000021fd9c1f pa 0x0000000087f67000..255: pte 0x0000000021fdb401 pa 0x0000000087f6d000.. ..511: pte 0x0000000021fdb001 pa 0x0000000087f6c000.. .. ..510: ...