Skip to content

Instantly share code, notes, and snippets.

@melon8
Last active May 2, 2019 11:13
Show Gist options
  • Select an option

  • Save melon8/7c8df9ab01cd9dbda57c53270ed1a0ca to your computer and use it in GitHub Desktop.

Select an option

Save melon8/7c8df9ab01cd9dbda57c53270ed1a0ca to your computer and use it in GitHub Desktop.
MIT 6.828 操作系统 学习记录

Lecture 1 操作系统概述 https://pdos.csail.mit.edu/6.828/2018/lec/l-overview.txt

概述

  • 6.828 课程目标:

    • 理解操作系统设计和实现
    • 自己开发一个小型操作系统,获得一手经验
  • 操作系统的意义:

    • 支持应用
    • 将硬件抽象,变得方便调用和可移植
    • 让硬件在不同软件间多路复用
    • 隔离应用程序,把bug限制在应用程序内部
    • 允许应用程序之间恭喜那个
    • 提高性能
  • O/S设计方法是什么?

    • 具体:管理硬件的库
    • 宏观:将物理机器变成有更好用的属性的抽象概念
  • 层级

    • 硬件: CPU、mem、磁盘等
    • 内核服务
    • 用户应用程序:vi, gcc等 我们要非常关心接口和内部内核结构
  • 操作系统内核通常提供什么服务?

    • 进程
    • 内存分配
    • 文件内容
    • 目录和文件名
    • 安全
    • 其他很多例如:用户、IPC(应该是进程间通讯Inter-Process Communication)、网络、时间、终端 介绍系统调用
  • 系统调用 ls 调用了哪些系统调用?

    • macOS 使用 dtruss 来看: sudo dtruss ls
    • 控制台先打印出ls的结果,然后可以看到调用了超级多的系统调用!

ps: macOS 有一个保护程序,禁止了drace 或者dtruss的调用。解决的办法是可以在恢复模式里禁止保护模式: https://stackoverflow.com/questions/33476432/is-there-a-workaround-for-dtrace-cannot-control-executables-signed-with-restri

Although not recommended by Apple, you can entirely disable System Integrity Protection on you Mac. Here's how:
1. Boot your Mac into Recovery Mode: reboot it and hold cmd+R until a progress bar appears.
2. Go to Utilities menu. Choose Terminal there.
3. Enter this command to disable System Integrity Protection:
 `csrutil disable`)
  • copy
    • UNIX传统:fd 0为“标准输入”,1为“标准输出”, 2为“标准错误输出”
  • 一个更有趣的程序:Unix Shell
    • 它是Unix命令行用户界面

    • 它很好地说明了UNIX系统调用API

    • 一些命令: ls ls > junk ls | wc -l ls | wc -l > junk

    • shell 也是一种编程/脚本语言 cat > script echo one echo two sh < script

    • shell 使用系统调用来设置重定向,管道和等待。 像 wc 这样的程序是不知道输入输出设置的

      (ps: man wc 可以看到wc的定义、使用方式)

看一个简单的shell的源码

( 找不到老师的源码,找到了这个:sh.c ,可以参考)

  • main ()
    • 基本过程:接受输入的命令,解析成树,然后运行

    • 主进程做的事情:getcmdforkwait

    • 子进程做的事情:parsecmdruncmd

    • 为什么fork () ?

      • 我们需要一个新的命令进程
    • fork()做什么? ( ps: man fork 看fork详细介绍)

      • 复制用户内存
      • 复制内核状态,例如文件描述符
      • 所以 child 和 parent 几乎是一样的
      • 子进程具有不同的“进程ID”
      • 现在两个进程并行运行
      • fork()返回两次,一次在父进程中,一次在子进程中
      • fork()将子进程的 pid 返回给父进程
      • fork()将 0 返回给子进程
      • 所以sh是在子进程中调用的runcmd()
    • 为什么wait()? (父进程等待子进程执行,子进程退出后唤醒父进程)

      • 如果子进程在父进程调用wait()之前退出怎么办?(会导致没有办法唤醒父进程,表现为操作系统卡死)
  • runcmd()
    • 执行parsecmd()生成的解析树
    • 不同的cmd类型的简单命令、重定向、管道
  • runcmd(),用于带有参数的简单命令
    • execvp(cmd, args)
    • man execvp
    • ls命令是一个可执行文件,在 /bin/ls 文件夹中
    • execvp在当前进程的内存上加载可执行文件,跳转到可执行文件开始的位置,也就是main()
    • 注意: 如果一切顺利,execvp不会返回
    • 注意: execvp()只有在找不到可执行文件时才返回
    • 注意: 用execvp()替换的是shell子元素
    • 注意: 主shell进程仍然是wait() 子进程
  • runcmd()如何处理I/O重定向?
    • 例如echo hello > junk
    • parsecmd()生成具有两个节点的树
      • cmd->type = ' > ', cmd ->file=“junk”, cmd -> cmd =…
      • cmd->type=' ', cmd -> argv=["echo", "hello"]
    • open ()dup2() 将FD 1替换为输出文件的FD
    • 改变其FD 1的是shell子进程
    • execvp保存FD设置
    • 因此echo运行时,FD 1 连接到了文件 junk
    • 这很好,因为对于上述重定向过程echo,是无感知的的,只需要把内容写到FD 1中
  • 为什么fork和exec是分开的?
    • 也许通过fork复制shell内存是浪费,因为马上复制的内存会在 exec 执行完后扔掉
    • 要点:子进程在调用 exec 前,有机会改变FD设置,并且父节进程的的FD集不会受到干扰
  • 将在lab中实现一些技巧来避免fork()复制成本
  • shell如何实现管道?
    • $ ls | wc -l
  • 内核提供了一个管道抽象 int fds[2] pipe(fds)
    • 一对文件描述符:一个 write FD 和一个 read FD
    • 数据写入写入write FD,出现在read FD上
  • 对于 ls | wc -l, shell 需要:
    • 创建一个pipe
    • fork
    • 设置 fd 1 为 pipe 的 write FD
    • 执行 ls
    • 设置 wc 的fd 0 为 pipe 的 read FD
    • 执行 wc
    • 等待 wc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment