MIT-6.S081

内容

Schedule: 6.S081 / 2020年秋季 — 6.S081 / Fall 2020 (mit.edu)

  1. Basic ideas of OS
  2. Study of the code in xv6 (a small teaching OS)
    1. talk about how it works
    2. look at the code and show the code executing
    3. reading assignments, a book that describes how xv6 operates and why it’s designed that way.
    4. xv6 is a simplified unix-like operating system, which runs on the RISC-V microprocessor that is the same microprocessor and the focus of 6.004, but in this course we will run xv6 under the QEMU machine emulator which runs on Linux.
  3. Background to help do the labs, like about C works, how the RISC-V which is the microprocessor that will be used.

Labs

Either implementing basic operating system features or adding a kernel extensions to the xv6 operating system.

2023 Guidance: 6.1810 / 2023 年秋季 — 6.1810 / Fall 2023 (mit.edu)

安装中遇到的棘手问题(Apple M芯片、macOS 14)

  1. 不需要安装xcode IDE,只需要安装$ xcode-select --install即可,是xcode的命令行工具
  2. 安装Homebrew,按照官网给的一句话命令安装
  3. https://github.com/riscv/homebrew-riscv 这是homebrew下安装risc-v,旧系统、旧芯片可能会装到/usr/local/opt/riscv-gnu-toolchain/bin,但新系统、新芯片则装到了/opt/homebrew/Cellar/riscv-gnu-toolchain/main.reinstall/bin
  4. The brew formula may not link into /usr/local. You will need to update your shell’s rc file (e.g. ~/.bashrc) to add the appropriate directory to $PATH.
    1. 此处需要手动添加PATH,例子中说的是bashrc,M2、macOS14系统下默认终端是zsh,因此需要在家目录下的.zshrc中添加:PATH=$PATH:/opt/homebrew/Cellar/riscv-gnu-toolchain/main.reinstall/bin。意味着将此目录添加到当前用户的环境变量 PATH 中。这个操作的作用是将该目录下的可执行文件路径包含进系统的执行路径中,使得系统可以直接在命令行中找到并执行这些命令。
    2. 修改 .zshrc 后,需要执行 source ~/.zshrc 命令使其生效,或者关闭当前终端窗口重新打开一个新窗口。
  5. 用brew安装qemu,默认装到了/opt/homebrew/Cellar/qemu/9.0.1
  6. 然后,以上这些和xv6没关系,第一节课演示的xv6系统需要git源码:git clone git://g.csail.mit.edu/xv6-labs-2023然后进入make qemu。
  7. 如何退出xv6:先按Ctrl+A后单击X

Lab1

Writing applications that make the system calls

The Last Lab

Add a network stack and a network driver, to be able to connect in over the network to the operating system that you run.

零碎

Xv6 I/O 与文件描述符

https://blog.csdn.net/u012419550/article/details/113850465

OS设计原则

OS should be defensive.

  • app cannot crash the OS
  • app cannot break out of its isolation

Strong isolation between app and OS

  • typical : Hardware Support
    • user / kernel mode
    • virtual memory system

E01 - open & fork

Operating Systems provide a lot of features and a lot of services, but they actually tend to interact, and sometimes in odd ways that require a lot of thought, even the simple examples given with open and fork.
if a program allocates a file descriptor with the open system call, and then that same program forks.
The semantics of fork turned out to be that you create a new process that’s a copy of the current process, this file descriptor you opened is truly to be a copy, this file descriptor still has to be present and usable in the child. So that is the files, the opened file descriptors, interact with fork in this interesting way.
fork的语义是:创建一个进程,是当前进程的副本。
刚才打开的文件描述符在子进程中仍然存在并可用。

Page Faults

Plan:

  1. Implement Virtual Memory features using page faults
    1. lazy allocation
    2. copy on write fork
    3. demand paging
    4. memory mapped files

C语言_动态内存分配

malloc

  1. 返回类型为void *
  2. 参数为(unsigned int size),表示总共要开辟的字节数
1
2
3
4
5
int* p = nullptr;
int n = 0;
scanf_s("%d", &n);
//p = (int*)malloc(n);//这是错误的参数,因为malloc的参数要写要开辟的字节数,而不是以变量数为单位。
p = (int*)malloc(sizeof(int) * n);

calloc

  1. 返回类型为*void
  2. 参数为(unsigned int count, unsigned int size),count表示变量数,size表示单个变量(类型)的字节数。
1
2
3
4
5
6
7
8
9
10
11
12
13
#include<stdio.h>
#include<stdlib.h>
#include<string.h>//包含memset函数
typedef unsigned int size_t;
void* My_Calloc(size_t count, size_t size)
{
void* p = malloc(count * size);
if(nullptr != p)
{
memset(p, 0, count * size);//把p指向的内存空间中的数据赋值为0x00
}
return p;
}

free

  1. 不管是malloc还是calloc开辟的空间都是用free(p)来释放的。

  2. free并不是把p释放掉了,而是把p指向堆区的空间从引用状态转换成未引用状态。

  3. 空间的释放只能释放一次,不能释放多次

  4. free(p)释放后,要给p赋值nullptr,防止指针失效带来的麻烦。

    1
    2
    3
    4
    int* p = (int*)My_Calloc(10, sizeof(int));
    free(p);
    p = nullptr;
    return 0;

realloc

realloc扩充或收缩之前分配的内存块(重新分配内存块)

1
void *realloc(void *ptr, size_t new_size);
  1. 参数中的ptr指向需要重新分配的内存区域的地址,new_size为新的字节数
  2. 返回值:成功时,返回指向新分配内存的指针,返回的指针必须用free或realloc归还。;失败时,返回空指针。原指针ptr保持有效,并需要通过free或realloc归还。

重新分配给定的内存区域。它必须是之前为malloc/calloc/realloc分配的,并且仍未被free或realloc的调用所释放。否则,结果未定义。

1
2
3
4
5
6
7
8
9
int size=5;//分配空间的变量数为5
int new_size=10;//最终要分配空间的变量数为10
int* p = (int*)malloc(sizeof(int)*size);//开辟size个int空间
for(int i=0;i<size;++i)
{
p[i]=1;
}
p = (int*)realloc(p, sizeof(int) * new_size);//增加到new_size个int空间,即由原来5个扩充到10个
p = (int*)realloc(p, sizeof(int) * 2);//减少到2个int空间,即由原来5个收缩到2个