2023南大操作系统课程笔记(一) 绪论部分

文章目录

  • 0.前言
  • 1.概述
    • 1.1 为什么要学操作系统
    • 1.2 什么是操作系统
    • 1.3 怎么学习操作系统
  • 2.应用视角下的操作系统
    • 2.1 理解高级语言程序
    • 2.2 操作系统上的软件
    • 2.3 系统调用示例
  • 3.硬件视角下的操作系统
    • 3.1 调试MBR
    • 3.2 编译运行操作系统内核
  • 4.Python建模操作系统
  • 补充学习

0.前言

os课程的视频回放:
南大操作系统课视频回放

往期南大课程笔记

  • ICS2021 P2.3 笔记
  • ICS2021 P3.1 笔记

本章节课程实验M1: M1: 打印进程树

1.概述

jyy推荐的库

  • z3: 求解任何逻辑方程组的工具
  • sympy: 可以用于符号计算

1.1 为什么要学操作系统

2023南大操作系统课程笔记(一) 绪论部分_第1张图片

1.2 什么是操作系统

2023南大操作系统课程笔记(一) 绪论部分_第2张图片

  • 从硬件视角来看: 操作系统就是一个c程序, 只管取指执行就行
  • 从软件视角来看: 操作系统是一个库里面包含有大量的对象和API

1.3 怎么学习操作系统

  1. 读可靠的教材
  • Operating Systems: Three Easy Pieces
  • Computer Systems: A Programmer’s Perspective
  • The Art of Readable code
  1. 问题驱动, 不怕写代码.

问: 怎么删除代码复制过来时候的行号?
答: vscode中Alt+shift, 使用鼠标拖动范围即可, 再统一删除

2.应用视角下的操作系统

计算机=数字电路=状态机
同时课上提到的通过非递归来实现递归可以查看博客: 非递归方法实现递归

2.1 理解高级语言程序

函数是由很多个栈帧组成的, 每一个栈帧都有一个pc值, 函数调用的本质就是, 在栈顶上添加新的一帧, 该帧的pc为0; 函数的返回则是, 将栈顶"pop"掉; 函数的执行, 取栈顶上pc值对应的语句执行.

所以所谓的C语言其实就是一个状态机:

  • 状态: 栈帧列表和全局变量组成

  • 初始状态: main函数的第一条语句

  • 状态迁移:

    • 执行frames.top.PC处的简单语句
    • 函数调用 = push frame
    • 函数返回 = pop frame

2.2 操作系统上的软件

系统上只有一个进程(程序)有访问屏幕操作的权限, 所有的程序vscod, xedit都是对该程序进行send和receive.

所以所有的程序, 都是计算一个状态机, 然后执行系统调用

strace的使用

  • 使用类似strace ls |& grep -e read -e write来简化strace的结果.
  • strace -o trace.txt your_command可以保存strace的结果, 同时保证you_command的正常执
  • 将多条命令的系统调用序列拼接起来
strace -o trace.txt command1
strace command2 >> trace.txt 2>&1
strace command3 >> trace.txt 2>&1
# 2>&1: 表示将标准错误(文件描述符2)重定向到标准输出(文件描述符1)

2.3 系统调用示例

命令(xxxxxxx) = -1 XXX: "= -1"通常表示该系统调用失败, XXX表示错误码, 表示具体的错误原因:

  • EINVAL: 该错误码表示传递给系统调用的参数有误
  • ENOENT: 该错误码表示指定的文件或目录不存在

openat: 用于打开文件或目录, 调用成功返回文件描述符
mmap: 用于将一个文件的一部分映射到进程的地址空间, 调用成功返回映射的起始地址
execve: 用于在新的进程中执行一个可执行文件
arch_prctl: 用于调整进程或线程的架构相关参数
newfstatat: 用于获取文件状态信息,

3.硬件视角下的操作系统

程序编译链接流程:

  • .c -> 预编译 -> .i -> 编译 -> .s -> 汇编 -> .o -> 链接 -> a.out

硬件厂商会约定好CPU Reset后的状态, 主板厂商只要提供Firmware, 主板上的固件通常被称为BIOS(基本输入/输出系统)或UEFI(统一扩展固件接口.
如今Firmware面临更多的硬件, 所以需要UEFI.
BIOS提供机制, 将程序员的代码(操作系统)载入内存

  • 以 Legacy BIOS为例, 它将第一个可引导扇区的第一个512字节加载到物理内存的7c00位置

3.1 调试MBR

mbr.img: mbr.S
    gcc -ggdb -c $<
    ld mbr.o -Ttext 0x7c00
    objcopy -S -O binary -j .text a.out $@

run: mbr.img
    qemu-system-x86_64 $<

debug: mbr.img
    qemu-system-x86_64 -s -S $< &  # Run QEMU in background
    gdb -x init.gdb  # RTFM: gdb (1)

clean:
    rm -f *.img *.o a.out

-s: 在tcp的1234端口打开gdbserver
-S: 不启动cpu

3.2 编译运行操作系统内核

hello.c为例

NAME := hello
SRCS := hello.c
export ARCH := x86_64-qemu

# 执行make run, 会启动一个qemu的虚拟机, 通过该虚拟机来执行SRCS

include $(AM_HOME)/Makefilesole

# 虚拟机build的操作
(
  cat $AM_HOME/am/src/x86/qemu/boot/bootblock.o;
  head  -c  1024  /dev/zero;
  cat /home/ziqiang/os2023/3-Demo2/build/hello-x86_64-qemu.elf
) > /home/ziqiang/os2023/3-Demo2/build/hello-x86_64-qemu

运行的程序就称为进程

4.Python建模操作系统

问: 什么样的指令序列可以调用c++中的虚函数.

答: (ChatGPT的答案)

C++ 中的虚函数调用是通过虚函数表(vtable)实现的。当对象被创建时,一个指向虚函数表的指针(vptr)被添加到对象的内存布局中。每个类都有自己的虚函数表,其中包含类的虚函数的地址。当调用虚函数时,程序会使用 vptr 找到正确的虚函数。

在汇编语言层面,对虚函数的调用可能涉及到加载 vptr 的值、查找虚函数表、获取函数地址并跳转到函数等操作。

应用中,关心的两种东西:

  • 纯粹的计算(内存的数据结构->内存中的数据结构)
  • 系统调用

程序就是个状态机

def main():
    x = sys_choose(['Head', 'Tail'])
    x = x.lower()
    sys_write(f'{x}\n')

上述程序的状态机如下:红字说明是系统调用,当执行write系统调用时,程序本身的状态没有发生改变(x='head'),圆圈是程序的状态,方框是操作系统的状态

2023南大操作系统课程笔记(一) 绪论部分_第3张图片

操作系统就是状态的管理者, 本身可以容纳多个状态机
线程可以有共享的内存, 而进程只有独立的内存能够访问
系统调用——切换线程的做法:

  • 封存当前状态机的状态
  • 恢复另一个被封存的状态机的执行

后面就是看jyy操作的时候,太秀了55555

补充学习

  1. yield关键字
  2. 小的编程技巧,如何在main函数执行之前或执行结束的时候再执行一部分代码

你可能感兴趣的:(笔记,linux)