MIT 6.828 / 6.S081 Fall 2020 Study Notes

Share

Why Study This Course?

MIT 6.828 is a famous operating-systems course. To complete Building a Computer with Nexys4 DDR [2]: Operating System, I planned to go through it.

QQ–20210323164948-1

This course mainly consists of lectures and labs, with the labs being the core. So my study here is lab-oriented, using the lectures as reference while learning by doing.

The English xv6 book is here.

The Chinese version is here.

Content Overview

There are 11 labs:

QQ–20210325094116

Plus environment setup.

Environment Setup

QQ–20210324141250

If installing Debian, you need to install the testing version, Bullseye. The QEMU version in Buster is too old to run the provided programs.

After installing Debian Bullseye, install QEMU and the GCC RISC-V toolchain. The script provided by the course can complete this in one line. Note that Fall 2019 used QEMU 4.x, while this script always installs the latest QEMU, already 5.x at that time, so make qemu in the Fall 2019 project may fail.

Finally, clone xv6, enter the directory, and run make qemu.

QQ–20210324142452

Lab 1: Utilities

Understand application-layer calls.

sleep

Put a process to sleep for n ticks. One tick is 100 milliseconds.

pingpong

Use fork and pipe to create a parent process and child process, and send data between them.

primes

Use fork and pipe to create multiple processes and compute prime numbers.

find

Find files under a specified directory.

xargs

Add pipe-like support for programs that do not support pipes directly.

Lab 2: Syscall

Understand how the kernel and user space interact through syscalls.

trace

Print syscalls within a selected range.

sysinfo

Print remaining system memory and the number of running processes.

Lab 3: Pgtbl

Understand page tables under the RISC-V architecture and how xv6 manages them.

vmprint

Print all PTEs, page table entries, in the page table and their physical addresses.

A kernel page table per process

An application’s userpagetable is stored sequentially from address 0 to sz, so copying PTEs from userpagetable to kernelpagetable only needs to follow the process size sz when computing addresses.

simplify copyin/copyinstr

After completing the previous step, this part becomes easier. The core is implementing a function that copies all PTEs from the user page table to the user’s kernel page table. The user page table spans addresses from 0 to sz * PGSIZE, so it can be copied page by page in order.

Be careful that virtual addresses must not exceed the PLIC address. PLIC is the interrupt controller under RISC-V, and exceeding this region will cause overwrite. Also, set the PTE_U flag of PTEs copied into the kernel to 0, so the operating system can access user-program data in kernel mode.

The tests for this lab are computationally heavy. If using a virtual machine, raise the VM configuration or increase the test timeout; otherwise the tests may time out.

Lab 4: Traps

The main learning goal is to become familiar with how xv6 handles interrupts and exceptions.

RISC-V assembly

This part is mainly for becoming familiar with RISC-V assembly instructions.

This RISC-V manual helps with understanding.

Backtrace

Implement a function that traces the error location.

Alarm

Implement a syscall that periodically calls a user function.

Lab 5: Lazy Page Allocation

Change xv6 page-table allocation from “allocate as many pages as requested” to “allocate a page only when the user program actually uses it”.

This improves xv6 runtime speed by reducing the number of allocated page tables.

Eliminate allocation from sbrk()

Modify sbrk() so it only changes the size of the user page table without actually allocating memory.

Lazy allocation

Modify interrupt handling, uvmalloc(), uvmunmap(), and related functions so that every page fault allocates one page table for the user program, while also ensuring that page-table removal works correctly.

Lab 6: Copy-on-Write Fork for xv6

This chapter implements the parent-child shared-memory page-table method described in the lecture notes. Although it has only one hard-level task, this part took me more than three days.

The hardest part was combining the lectures, the RISC-V reference manual, and xv6 source code to understand the whole process of process page-table allocation and release.

One pitfall I encountered: when implementing reference counting for releasing page tables, the decrement operation should be placed directly inside kfree(). If not, it is very hard to find all places where the reference count needs to be decremented, and usertests can produce errors that are difficult to locate.

Lab 7: Thread

Uthread: switching between threads

Implement a user-level thread.

Debugging xv6 with gdb

  1. In the xv6 root directory, open terminal 1 and run make qemu-gdb. It prints a TCP address.
  2. Open terminal 2 in the same location and run gdb-multiarch. multiarch means cross-platform. If using ordinary gdb, the default architecture is usually the host architecture, often x86, but here we need RISC-V, so extra configuration is required.
  3. In terminal 2, run target remote:xxx, where xxx is the TCP address printed in terminal 1.
  4. Start debugging.

Using threads

Become familiar with Unix pthread functions. When implementing multithreading, use locks to prevent incorrect data writes.

Barrier

Use the pthread library to implement a barrier. In short, each thread waits inside this function until all threads have reached it, and then all threads wake up together. This uses the same principle as xv6’s sleep/wakeup.

Lab 8: Locks

This part introduces xv6’s locking mechanism, including spinlocks and sleeplocks.

Memory allocator

Change page-table allocation locks from one global lock for all CPUs to one lock per CPU.

Buffer cache

Change the Buffer lock from one shared global lock to multiple parallel locks using a hash function. The difficult part is changing the original bcache into a hash table.

Lab 9: File System

Become familiar with the xv6 file system.

Large files

Add a second-level index to inode data-block links. This design is almost identical to the ext2 file system I previously built in an operating-systems course project.

Implement symbolic links, supporting up to 10 levels of iteration. This was my first time implementing this feature by hand; before this, I had only seen it in operating-system books.

Lab 10: mmap

Implement Unix mmap and munmap.

My own understanding is that mmap serves a role similar to write and read, but it can operate on data more conveniently and directly, without repeated write or read calls.

The difficulty is that these two functions must operate on both memory page tables and the file system, and they also need to consider locking.

Lab 11: Networking

Following the provided documentation normally is enough.

I passed this lab after switching network and computer devices.

xv6-labs-2020

MIT 6.828 | Star Trail

Read more

可多路视频播放的VisionOS 媒体查看器开发

可多路视频播放的VisionOS 媒体查看器开发

开发一款能够同时播放多个视频的vision pro媒体查看器。 0:00 /0:40 1× 缘起 Vision Pro 发布时我就特别想买,毕业工作后终于有资金购入并加入Apple开发者计划,从今年五月到现在也用了快小半年,用起来确实挺爽。 但是有些痛点还是很难受,其中一个痛点就是无法同时播放多个视频音频(实际上VisionOS提供了同时播放音频的API,但是似乎我用的APP都是不遵守🤣 导致都在抢占),因此为了满足我自己的这个痛点,也学习一下Vision OS 的应用开发,甚至完成度足够的话考虑上架App Store,便有了这个目标是多视频同时播放的媒体查看器项目。 现有工作 我购买了4XVR、Infuse、Moon Player、ES 文件助手(这款只有iPad OS版,不是专供Vision OS的),这几个月体验下来,全都存在我提到的和其他APP抢占音频通道,无法同时播放的问题,其他的我的主观的体验如下: 4XVR:使用最多,用起来最舒服,格式支持很全,VR视频也能看,号称全v

By Feiran Yu