一份我学习 mit 6.s081 操作系统课程时的笔记,gitbook链接

xv6 Learning

操作系统接口

操作系统的四大职能

  • 资源共享:在多个程序间分配计算机资源。

  • 硬件抽象:提供比底层硬件更易用的服务(如 Word 无需关心硬盘型号)。

  • 多路复用:让多个程序看起来在同时运行。

  • 受控交互:管理程序间的数据共享与协作。

我的理解是一种“中介”角色,操作系统在硬件和应用程序之间提供一个抽象层,使得应用程序可以更方便地使用硬件资源,而不需要直接与硬件打交道。

内核与系统调用

  • 内核 (Kernel):向运行程序提供服务的特殊程序。

  • 进程 (Process):运行中的程序,拥有独立的指令、数据和栈空间。

  • 硬件保护机制:内核拥有硬件特权,而用户进程没有。

  • 系统调用 (System Call):

    • 用户进程请求内核服务的唯一接口。

    • 执行时硬件特权级提升,进入内核,完成后返回用户空间。

shell ——system call——> kernel

进程总是在用户空间和内核空间之间交替运行。

核心机制详解

  • A. 进程管理 (Process & Memory)

    • xv6 进程由两部分组成,一部分是用户内存空间(指令,数据,栈),另一部分是仅对内核可见的进程状态。

    • fork():创建一个与父进程内存完全相同的子进程。返回值:父进程获得子进程 PID;子进程获得 0。

    • exec(filename, argv):用新程序替换当前进程的内存空间,从入口点重新执行。

      • 在这里我的理解出现了一些障碍,解释一下:内存包括了代码段、数据段、堆栈等。exec 操作时先从path加载可执行文件到内存,而argv则是动态参数,放在栈上。exec后,进程的内存空间被新程序覆盖,原有的代码和数据都被替换掉了,但栈上的参数仍然可以被新程序访问到。
    • wait():父进程等待子进程退出。

    • sbrk(n):动态增加进程内存。

    • 核心设计:将 fork 和 exec 分开,使得 shell 可以在子进程执行新程序前,对其 I/O 环境进行配置。

  • B. I/O 与文件描述符 (File Descriptors)

    • 本质:一个小的整数,代表内核管理的 I/O 对象(文件、管道、设备)。

    • 默认约定:0 (stdin), 1 (stdout), 2 (stderr)。

    • 常用调用:read / write(基于当前偏移量操作)、close、dup(复制描述符)。

    • 重定向原理:fork 出子进程 -> close(0) -> open("file")(系统会自动分配最小可用号,即 0)-> exec

  • C. 管道 (Pipes)定义:内核维护的一个环形缓冲区,暴露为一对文件描述符(读端和写端)。

    • 特性:
      • 自我清扫:任务结束自动销毁。

      • 流式传输:可传输任意长度数据。

      • 阻塞同步:读端会等待写端写入数据或关闭。

  • D. 文件系统 (File System)

    • 结构:目录树。
      • Inode:文件的底层标识,一个 Inode 可以对应多个文件名(通过 link 实现)。

      • 设备文件:通过 mknod 创建,读写操作被内核转发到具体的硬件驱动。

      • unlink:删除文件名。只有当 Inode 的链接数减为 0 且无进程打开时,数据才会被真正从磁盘擦除。