0%

操作系统笔记(一)

操作系统的启动

刚上电时,操作系统在硬盘中。计算机工作原理是不断地取值执行,要取值执行,就要将代码放到内存中。一开始操作系统在硬盘上,无法取值执行。所以第一部分工作就是将操作系统从硬盘上载入到内存里。这些工作由操作系统的引导扇区来完成,也就是bootsect.s,这是一段汇编程序。

bootsect.s:

  1. 读入setup。
  2. 在屏幕上打出logo。
  3. 调用13号中断,读入system。

setup.s:完成OS启动前的设置。获得计算机的硬件信息,形成数据结构来管理这些设备。

  1. int 0x15中断,获取内存大小。为了让操作系统知道内存有多大,才可以去管理。

  2. 操作系统挪动到从0地址开始的一系列内存。

  3. mov cr0,ax,进入保护模式,即从16位(实模式)切换到32位的寻址方式。cr0这个寄存器的最后一位PE如果是0则为16位模式,是1则为32位模式。

    在保护模式下的地址翻译:

    地址翻译:全局描述符表GDT(Global Descriptor Table),在硬件中完成,速度快。

    CS不再是左移,而是变为了选择子,存放的是表的下标,表的索引。内存地址=根据CS查表+ip。

    jmpi 0,8,CS=8,ip=0。跳到了head.s

接下来要跳到system模块中执行了,system由许多文件编译而成。第一部分是head.s。

关于汇编:

  1. as86汇编:能产生16位代码的Intel 8086(386)汇编。
  2. GNU as汇编:产生32 位代码,使用AT&T系统V语法。
  3. 内嵌汇编,gcc编译x.c会产生中间结果as汇编文件x.s。

head.s初始化一些表,跳出来到main.c。main.c中引用了mem_init函数,这个函数是用来初始化内存。

以上步骤完成了两件事情:将操作系统读进内存和初始化(读取硬件信息等)操作系统。

操作系统的接口

信号转换,屏蔽细节。

命令行是怎么回事?命令输入后发生了什么?

  • 命令是一个用C语言写的程序。

图形按钮是怎么回事?

  • 消息框架程序 + 消息处理程序。

操作系统接口:通过c程序连接操作系统和应用软件。例如:fork。

操作系统提供这样的重要函数。这种重要函数就是操作系统接口:接口表现为函数调用,又由系统提供,所以称为系统调用(system_call)。

系统调用的实现

如果可以随意调用的话计算机会很不安全,所以要将内核程序和用户隔离。内存分为内核段和用户段。

硬件提供了主动进入内核的方法:int 0x80中断。

(待补完)

操作系统历史

IBM7094:

  • 计算机使用原则:只专注于计算。
  • 批处理操作系统(Batch system):一个作业完成,自动读入下一个作业。
  • 典型代表:IBSYS监控系统。

OS/360:计算机进入各种行业,一台计算机要应对不同的使用场景。

  • 多道程序(multiprogramming):多个任务同时出现,交替进行。
  • 作业之间的千幻和调度成为核心。
  • 多进程结构和进程管理概念萌芽。

MUTICS:使用人数增加。

  • 每人启动一个作业,作业之间快速切换。
  • 分时系统(timesharing):分时切换。
  • 核心仍然是任务切换,但是资源复用的思想会操作系统影响很大,虚拟内存就是一种复用。

UNIX:简化的MUTICS,核心概念差不多,但更加灵活和成功。1969年贝尔实验室的两个人开发了UNIX。

Linux:1981年推出的IBM PC。开源。

多进程结构是操作系统的基本图谱。

DOS:

  • 1975年出现了CP/M。写命令让用户用,执行对应的程序,单任务。
  • 1980,在CP/M的基础上开发了QDOS。

MS-DOS:1981,MS-DOS。

Windows:文件,开发环境,图形界面对于OS的重要性。

对用户的使用感受更加重视了。

cpu管理的直观想法

  • cpu的工作原理:自动的取值执行。

因为IO指令非常耗时(与计算指令相比),在一个程序执行IO指令时,可以执行其他程序。就形成了多道程序交替执行。

  • 一个cpu上交替执行多个程序:并发。

怎么做到并发呢?

  • 需要记住切换执行时,程序原来的样子。用PCB存储。

进程:进行中的程序。

  • 进程有开始,有结束,程序没有。
  • 进程会走走停停,走停对程序无意义。
  • 进程要记录离开进程时进程的样子,ax,bx。。

多进程图像

操作系统只需要把这些资源记录好、要按照合理的次序推进(分配资源、进行调度),这就是多进程图像。

用户使用计算机就是启动了一堆进程,用户管理计算机就是管理进程。

多进程如何组织和存放进程?

  • Process Control Block:用来记录进程信息的数据结构。
  • 运行→等待;运行→就绪;就绪→运行。。。

多进程如何交替?

  • 启动进程,启动磁盘读写,将进程设为阻塞态,放入等待队列中。启动schedule()切换函数。
  • getNext函数(调度函数)在就绪队列中找到下一个启动的线程,switch_to函数切换进程,保存当前线程,执行下一个线程。

多个进程如何相互影响?

  • 不同进程有可能会使用同一个内存。
  • 解决方法:映射表。这是一种内存管理的方法。不同进程如果要访问同一个地址,可以用映射表把这个地址变成不同的物理地址。

多个进程之间如何合作?

  • 在打印工作中,多个进程想要打印,如果不做处理多个进程交替进行打印任务,就会出现问题。
  • 解决方法:进程同步。给多个进程需要操作的公共资源上锁。第一个进程上锁,第二个进程想要执行的时候先检查锁,解锁后再执行。

用户级线程

线程:保留了并发的优点,避免了简称切换的代价。一个进程中有多个线程,而这些进程的资源是公用的,使切换速度更快。现在讨论的切换都是线程的切换而不是进程的切换。

create函数同时启动多个线程,线程可以通过yield函数主动切换到第二个线程。

两个线程公用一个栈的话,我们会发现程序的运行顺序会出现问题。为此我们需要给一个线程用一个栈,在调用yield时会切换esp寄存器(用来存放栈顶指针的寄存器,记录在tcb中,一个线程一个tcb)的值。

内核级线程

多核cpu如果想发挥作用,必须支持核心级线程。

这里是多对多的:多个线程和多个核,由操作系统调配。

核心级线程与用户级有什么不同?

  • 切换时切换的是两套站栈。包括用户栈和内核栈。
  • 这时tcp会记录用户栈与内核栈。

用户栈和内核栈之间的关联:

  • 通过中断进入内核栈,通过IRET返回用户栈。

  • 进入内核时,内核栈中压入对应用户栈的SS和SP(栈地址)、CS和IP(指令地址)。

  • 内核栈中记录了如何找到用户栈的信息。

内核switch_to的五段论:

  1. 进入中断。
  2. 中断处理:启动磁盘读或时钟中断,引发切换。
  3. 找到下个要执行的tcb。
  4. 根据tcb完成内核栈的切换。
  5. IRET切换到用户栈。

所以在创建线程时,就需要创建用户栈、内核栈、tcb。