408_OS复习_疑难杂症

任务、作业与进程、线程

结论:作业下面多个任务,任务下面多个进程,进程下面多个线程。任务/作业面向用户的抽象概念,进程/线程面向CPU实体概念

作业简单理解为批处理系统的一次运行,这次运行有多个任务,完成每个任务又需要多个进程协同工作。在没有被真正运行时,作业在外存的等待队列中等待执行

就拿bash脚本来说,一整个脚本是一个作业,这个作业里面我需要用word打开文档、又需要打开音乐、需要浏览器打开指定格式参考文本,这就包括了三个任务,每个任务下可能又需要打开多个进程

个人认为作业算是批处理系统中老概念了,相当于现在的程序就行

协程:一种轻量级的线程,与线程最大区别就是,状态存放在堆中,可以暂停。详细参考C++20协程入门教程 | Zplutor’s写的非常好

同步互斥问题

首先区别一下同步和互斥

  • 同步:是指两个进程在并发运行的条件下仍要按照一定顺序访问资源。相当于入口必须先A进后B进
  • 互斥:指的是两个进程要访问同一个资源,但是该资源只能被一个进程访问。相当于入口只能通过一人

互斥原则:空闲让进、忙则等待、有限等待、让权等待(非必要)

同步互斥实现方式:

  • 软件实现:peterson算法

  • 硬件:关中断、借助硬件实现的原语操作(TestAndSet、Swap)

  • 互斥锁

  • 信号量:即PV操作,需要记住P–,V++,将相应代码对应

    void wait(semaphore S){
    	S.value--;
    	if(S.value < 0){
    		add this process to S.L;
    		block(S.L);
    	}
    }
    void signal(semaphore S){
    	S.value++;
    	if(S.value <= 0){
    		remove a process P from S.L;
    		wakeup(P);
    	}
    }
    
  • 管程:和之前的进、线、协程都不同,管程专门用于同步互斥,是一个抽象的数据结构。以面向对象来说,管程就是一个类,其中封装了互斥资源,而且对该资源的相关操作也都封装在该类中,同时只能由一个实体访问

段式内存管理和程序中段的关系

需要先明确的一点是目前基本都是页式内存管理(个人OS)

程序中的段我们以ELF文件为例

  • 当ELF在外存时分的代码段、数据段、共享段等等(也可以叫节,这里用于区分)
  • 加载到内存时,这些段会根据各自的属性,重新合并,来放置到不同的物理页(下面的page)中
  • 这些合并后的段,在内存上都不算是连续的,因为一页一般不会占满(页内碎片)

而段式管理中的段则对应于上面的物理页,则可以推出这两个段不是一个东西

内存映射过程(段页式为例

  1. CPU拿到逻辑地址A,取出前几位为段号S

    如果是二级页表,将段表过程换位一级页表即可

  2. 判断段号是否越界,如果S>=段表长度M,则产生越界中断

    这里的段表长度M来自相应界地址寄存器,下面的段表起始位置来自相应的基地址寄存器

    还有判断的方法就是直接在寄存器中给出上下限地址寄存器

  3. 在段表中拿着段号S找到对应的段表项,取出对应页表地址

    在仅有页式管理时,单级页表的位置由页表寄存器PTR指出,多级页表的话,对应的一级页表寄存器叫做页目录基址寄存器

  4. 逻辑地址A后再取页号K,同样判断是否越界

  5. 之后根据K在页表中查找对应页表项,获取其中的物理块号

  6. 拼接最终得到物理地址

目前常用的就是页式管理,采用多级页表+TLB的方式

基本页式内存管理和请求页式管理区别

  • 基本页式、基本段式、基本段页式中进程的所有页/段一次性都装载到内存上,因而不存在置换、请求等操作

  • 请求式分页、分段、段页式中进程的页并不会一次性全部加载到内存,而是加载到虚拟内存中(内存+外存交换区),当需要交换区中的页时,就进行请求调页,内存驻留集有空就直接给,否则就进行页面置换(交换区足够放置进程所需东西)

    交换区不够的话,则不会被修改的文件将直接从文件区加载

    unix系统中,未运行过的页都在外存文件区,只有从内存上换下来的才会放到交换区。

内存映射文件

将一个文件映射到进程的虚拟地址空间中,而非通过文件I/O操作访问,这时访问该文件就相当于访问内存中的一块大号连续字符,不会像I/O操作一样将文件全部读入,而是需要那一页时再单独读入,并利用关闭映射时的回写操作从而实现写文件

共享内存基于上述原理实现,一个文件被映射到了多个进程的虚拟地址空间中(页表项),当进程A在映射到这个文件上的操作时,另一进程B由于实际上看的是同一份,这时就能立刻看到上一个进程的操作

COW:copy on write,父子进程共享相同的页面工作,然后子进程修改页面时标记写时复制,此时系统就会创建该页面的副本给子进程写,而父进程还使用原先的页面。

在这个过程中子进程需要一个新的页,除了申请之外,还可以借助页面池分配。

什么是池,简单来讲就是提前初始化过的东西,需要就拿,用完就放回,省去了一些步骤

工作集、抖动、驻留集相关概念

概念区别

  • 驻留集是一个进程在内存中被分配的页框数目,因为不需要全部一次装进。比如此时驻留集分了两块,其中放了进程的第2、3块

    虚拟内存中的叫页块,真实内存的是页框

  • 工作集是一个进程在一段时间内需要用到的页块集合,需要注意的是这是一个序列,不存在指明内存还是交换区的问题。工作集序列2、3、5、4

  • 抖动就是刚放入驻留集的页块(因为页面置换)又要被马上换出来,或者刚换出来的马上又要用到而放驻留集中

驻留集和缺页过程

  • 驻留集是进程在内存中的页框集合。

  • 进程的页表中页号应该是全的,但是因为驻留集的存在导致部分页号对应的页框号为空(这部分位于外存的交换区,而非内存中),因此需要通过页面置换算法来从驻留集中选一个页框出来,选出来的页框来存放新的东西

    这里想要说明的是,题目中一旦给定驻留集中的所有页框号,之后该进程所有的页号,都会存在于这几个页框号中

基本IO操作

int open(const char * pathname, int flags);
fd = open("flag.txt",O_RDONLY);

ssize_t read(int fd, void * buf, size_t count);
read(fd,&ch,1);

ssize_t write (int fd, const void * buf, size_t count);

int close(int fd);

需要说明的是,当open打开文件时,该文件并不会被加载到内存中,而是该文件对应的文件记录块FCB会被加载到内存中。(参考下面的VFS)

内存中有个系统的打开文件表、进程的打开文件表,各自的打开表中都会添加该文件相关条目

具体open如何运行有待后续进一步学习

磁盘分区格式化

磁盘初始化过程

  1. 低级格式化/物理格式化:一般是由厂商操作,将其分成一个个扇区,包括头部、数据区、尾部,并利用CRC字段对扇区进行校验,其中的坏块也会被标记不进行使用

  2. 分区:将每个分区的起始扇区和大小都记录到磁盘主引导记录的分区表中

  3. 逻辑格式化/高级格式化:这里开始安装文件系统,各个分区都可以有自己的文件系统

    文件系统安装后,因为默认扇区通常是512KB,为提升效率,现在的OS经常会将几个扇区给合并到一起,windows中的簇,linux中的块

引导过程:

  1. 激活CPU,读取ROM中的boot程序,执行BIOS
  2. 构建中断向量表,进行硬件自检
  3. 加载硬盘,找到引导硬盘后,读取其开头的MBR主引导记录
  4. MBR中的小程序将从MBR后的分区表中找到引导分区(即OS启动程序所在分区)
  5. 读取引导分区中的第一个扇区,即引导扇区,运行OS启动程序

成组链接法过程

内容分属于文件系统中,空闲空间管理,其他还有,空闲表法、空闲链表法、位图法等。FAT表中的也算是一种

当然与空闲空间管理对应的有文件的空间管理(也叫文件的物理结构),顺序存储、链式存储、索引存储等

(也可以将空闲空间当作文件管理,感觉没啥毛病

现在假设每组10块,第一块中存放着<本组空闲块数目,下一组开头块>,其它的都指向空闲块,第一组存放在内存专用栈——空闲盘块号栈。

  • 分配时:从第10块(栈顶),向上开始分配,分配到第一块时,将下一组内容内容读入该栈,同时将下一组内容读入栈

  • 回收时:回收的盘块至于栈顶,当数量到达一组最大时,表示栈满,将目前栈中的10个指针存入新回收的盘块,并将这个新回收的盘块号作为新栈底

    注意移动栈顶时,本组空闲块数目对应++/–;手画一边过程方便理解

VFS及四大对象

VFS即虚拟文件系统,因为每个分区都可以有不同的文件系统,而我们不可能在不同的分区有不同的操作,ntfs_readfat_read等,于是乎VFS层就是相当于屏蔽了这层差异,给上面的使用者提供了统一的接口read

VFS只存在于内存中,并不实际存在于外存。四大数据结构如下

  • 超级块:superblock,一个超级块对应一个文件系统,用于描述文件系统的信息。各个超级块对象都用双向循环链表链接起来

  • 索引节点:inode,保存文件的元数据(也就是属性)。需要区分inode在外存和内存上的形式,当文件打开后,其索引节点会被复制到内存中,并添加额外的信息,比如“访问计数”、“逻辑设备号”等内容。

    这里可以引申到软链接和硬链接内容

  • 文件:file,又一个结构体,并非是文件本身,其中保存了文件读写指针、锁变量、文件路径等内容。每当打开一个文件,该结构体就会插入到系统打开文件表中(双链表形式),而用户则会有用户打开文件表来管理所有的file结构体。

  • 目录:dentry,linux中一切皆文件,目录也是目录文件,当然也对应着一个inode。与inode一样外存到内存会有些许不同

    区分VFS仅在内存中这句话,外存上的inode/dentry结构不算是VFS

Linux中管理进程的结构体是task_struct,其中有个变量指向用户打开文件表,根据文件描述符可以找到对应的file结构体,获取文件的路径,找到目录,找到inode索引节点,从而获取文件

常说的文件描述符其实就是这个文件在用户打开文件表中的下标

不同于现在的面向对象,这里面的四大对象都是通过其中的一个operation指针来指向对应的操作结构体,其中存放一系列操作函数。并非都挤在一个struct中

IO软件层次结构过程

从上到下:用户层软件、设备独立性软件、设备驱动软件、中断处理软件、硬件

要注意这里的设备独立性软件和前面的VFS有异曲同工之妙,都是用于屏蔽下面的差异

大致过程scanf()

  1. scanf函数调用系统调用封装函数read(),其中有一条陷阱指令,借此进入内核
  2. 内核调出read对应的sys_read系统调用服务例程进行执行,在设备无关层进行若干调用
  3. 最终来到设备驱动层处理,设备驱动程序对本次IO进行初始化,阻塞用户进程P,CPU执行其他进程
  4. 用户在键盘上输入字符后,外设向CPU发出中断请求
  5. CPU响应中断后,启动键盘中断处理通用驱动程序对中断进行通用处理后,唤醒具体的处理键盘输入的驱动程序
  6. 上述专用驱动程序将字符从键盘控制器读入系统缓冲区
  7. 传输完成后,唤醒P并插入就绪队列,进行中断返回,进程P也从系统调用返回

设备独立性软件主要是对各种设备之间的统一的操作,比如打开关闭等

设备驱动软件则是对应具体种类,具体硬件的操作,比如磁盘当中的地址转为磁面、磁道、扇区

中断处理相当于是通知机制,硬件的驱动运行完成后,借助中断告知内核

IO设备分配过程

名称功能
LUT逻辑设备表逻辑设备名——》物理设备名+驱动程序入口
SDT系统设备表系统一张一个设备对应一个条目;物理设备名——》DCT+驱动程序入口
DCT设备控制表每个设备都有一张,说明属性;DCT——》COCT
COCT控制器控制表每个设备控制器有一张,每个都由一个通道控制,;COCT——》CHCT
CHCT通道控制表CHCT——》COCT
  1. LUT逻辑设备表,每个表项中有三项<逻辑设备名,物理设备名,设备驱动程序入口地址>。进程根据I/O请求中的逻辑设备名来获取物理设备名

    该表可以整个系统中设置一张,也可以每个用户一张,这样不同的用户就可以使用相同的逻辑设备名

  2. 进程根据上一步的物理设备名查找SDT,从中找到对应设备的DCT,从而了解该设备状态

    如果忙,则将进程的PCB挂到DCT下对应的等待队列;否则就分配

  3. 设备分配后,来到对应的COCT,同样也是根据状态来是否分配

  4. 分配好控制器后,来到CHCT,查询状态据此分配

  5. 只有当设备、控制器、通道依次分配成功后,才可以启动设备进行数据传送

中断的详细过程

每个中断源都有各自的中断请求标记触发器,这些触发器共同组成中断请求标记寄存器。中断异常由硬件进行检测

当:有中断请求、没有关闭中断、指令执行完成后,CPU开始响应中断

  1. 关中断,令中断允许触发器IF=0

  2. 保存当前断点位置(x86的保存PC和PSW,MIPS的保存PC到特殊寄存器)

  3. 进行中断识别,一般是中断向量,即通过中断类型号,在中断向量表中找到对应中断向量,从而定位中断服务程序

    此前的都属于中断隐指令,由硬件实现;后面都属于中断程序范畴,软件实现

  4. 保存现场和屏蔽字

    各个中断源的屏蔽触发器共同构成屏蔽字寄存器,该寄存器用于多重中断

  5. 执行中断服务程序

  6. 恢复现场和屏蔽字

  7. 开中断,中断返回

如果允许多重中断的话,需要在第五步前后,加一个开中断和关中断

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值