LOADING

加载过慢请开启缓存 浏览器默认开启

操作系统笔记

2025操作系统

中断是激活操作系统的唯一方式

页式虚拟存储管理

页式虚拟存储管理的基本思想

将进程信息副本存放在外存中,当它被调度投入运行时,程序和数据没有全部装入内存,仅装入当前使用页面,进程执行过程中访问到不在内存的页面时,再由系统自动调入。

页式虚拟存储是现代 OS 的主流存储管理技术

首次只把进程第一页信息装入主存,称为请求页式存储管理:由于页面在需要时是根据进程请求装入内存的

请求页式存储管理:

  1. 优点:进程的程序和数据可按页分散存储在内存中,有利于内存利用率和多道程序运行
  2. 缺点:需要硬件支持、处理缺页中断、机器成本增加、系统开销加大,页内存在碎片。
页式虚拟存储管理的页表

需要扩充页表项,至少包含如上信息,指出:

  1. 虚拟地址、实际地址
  2. 主存驻留标志:指出页面是否已经装入内存。1 表示在内存中可以被正常访问,0 表示不能立即访问,产生缺页异常。
  3. 修改位:被设置后,该页被调出内存前必须先写回磁盘,保障数据一致性
  4. 保护位:限制页面访问权限
  5. 引用位:在页面被引用无论是读写时设置,用来帮助系统进行页面淘汰。
  6. 内存块号:页面对应的页框号,用来地址转换。

32 位操作系统:32bit 标识一个页表项

页号是隐含信息,不是直接存储的信息。

页式虚拟存储管理的实现

CPU 处理地址:

  1. 若页驻留,则获得块号形成绝对地址
  2. 若页不在内存,则 CPU 发出缺页中断

OS 处理缺页中断:

  1. 若有空闲页架,则根据辅存地址(虚存)调入页,更新页表与快表等
  2. 若无空闲页架,则决定淘汰页,调出已修改页,调入页,更新页表与快表
页式虚拟存储管理的地址转换
缺页中断的处理流程

本指令没有被处理完,是在查找地址的时候发生的中断,所以要回退指令执行。 缺页中断完成后要重新执行被中断指令

页式虚拟存储管理的地址转换全过程 *

地址转换过程:

  1. MMU 接收 CPU 传送来的逻辑地址并自动按页面大小把它从某位起分解成两部分:页号和页内位移。
  2. 以页号为索引快速搜索快表 TLB。
  3. 如果命中,立即送出页框号,并与贾内位移拼接成物理地址,然后进行访问权限检查,如获通过,进程就可以访问物理地址。
  4. 如果不命中,由硬件以页号为索引搜索页表,页表基址由硬件页表基址寄存器指出。
  5. 如果页表被命中,说明访问页面已在内存中,可送出页框号,并与页内位移拼接成物理地址,然后进行访问权限检查,如获通过,进程就可以访问物理地址,同时要把这个页面和页框信息装入快表 TLB,以备再次访问。
  6. 如果发现页表中的对应页面失效,MMU 发出缺页异常,请求操作系统进行处理,MMU 工作到此结束。

MMU 发现缺页并发出缺页异常,存储管理接收控制,进行缺页异常处理的过程如下:

  1. 挂起请求调页的进程。
  2. 根据页号搜索外页表,找到存放此页的磁盘物理地址。
  3. 查看内存是否有空闲页框,如有则分配一个,转(6)。
  4. 如果内存中无空闲页框,按照替换算法选择淘汰页面,检查其是否被写过或修改过,若否则转(6),若是则转(5)。

反置页表

反置页表是针对主存页框建立的一个页表,它的页表项按照页框号排序,其表项包括正占有该页框的进程号/页号、特征位和哈希链指针等。之前叙述的页表是按照页号做索引,其页表项中记录页框号,而这种按照页框号做索引,页表项记录进程号/页号的页表就自然而然地被称为反置页表。

IO软件的实现层次

I/O 中断处理程序

  1. I/O 中断处理程序位于操作系统底层,与硬件设备密切相关,与系统其余部分尽可能少地发生联系
  2. 进程请求 I/O 操作时,通常被挂起,直到数据传输结束后并产生 I/O 中断时,操作系统接管 CPU 后转向中断处理程序
  3. 当设备向 CPU 提出中断请求时,CPU 响应请求并转入中断处理程序

I/O 中断处理程序的功能

检查设备状态寄存器内容,判断产生中断的原因,根据 I/O 操作的完成情况进行相应的处理:

  1. 如果数据传输有错,向上层软件报告设备的出错信息,实施重新执行
  2. 如果正常结束,唤醒等待传输的进程,使其转换为就绪态
  3. 如果有等待传输的 I/O 命令,通知相关软件启动下一个 I/O 请求

设备驱动程序

  1. I/O 设备驱动程序包括与设备密切相关的所有代码
  2. I/O 设备的功能是从独立于设备的软件中接收并执行 I/O 请求:
    1. 把用户提交的逻辑 I/O 请求转化为物理 I/O 操作的启动和执行,如设备名转换为端口等
    2. 监督设备是否正确执行,管理数据缓冲区,进行必要的纠错处理
  3. 某些控制器一次只能接受一条命令(DMA),有些控制器可以接受一串命令后执行(通道)

设备驱动程序的功能

  1. 设备初始化:在系统初次启动或设备传输数据时,预置设备和控制器以及通道状态
  2. 执行设备驱动例程:
    1. 负责启动设备,进行数据传输
    2. 对于具有通道方式,还负责生成通道指令和通道程序,启动通道工作
  3. 调用和执行中断处理程序:负责处理设备和控制器及通道所发出的各种中断

设备驱动程序的处理方式 *

  1. 阻塞自己:命令开始执行时,进程阻塞自己,直到昨晚才解除阻塞。
  2. 无须阻塞:很快就可以完成,比如滚屏。
  3. 无论哪种,操作完成后都需要记性数据传输正确性校验,如果有错则报告。

设备驱动程序的层次

每个设备驱动程序只处理一种设备,或者一类紧密相关的设备

设备驱动程序分为整体驱动程序和分层驱动程序

  1. 整体驱动程序直接向操作系统提供接口和控制硬件。适用于功能简单的驱动程序,效率较高,但较难迁移
  2. 分层驱动程序将驱动程序分成多层,放在栈中,系统接到 I/O 请求时先调用栈顶的驱动程序,栈顶的驱动程序可以直接处理请求或向下调用更低层的驱动程序,直至请求被处理。适用于功能复杂、重用性要求较高的驱动程序,结构清晰且便于移植,但会增加一部分系统开销

独立于设备的 I/O 软件

执行适用于所有设备的常用 I/O 功能,并向用户层软件提供一致性接口

I/O操作执行步骤

UNIX多级文件索引

文件的使用

建立文件

“建立文件”用于创建一个文件。

所需参数:文件名、设备类(号)、文件属性及存取控制信息。

处理流程:在相应设备上建立一个文件目录项,为文件分配第一个物理块,在活动文件表中申请一个项,登记有关目录信息,并返回一个文件句柄。

int fd;           // 创建成功后系统返回的文件描述符
int mode;         // mode 是文件所具有的权限
char *filenamep;  // 指向要创建的文件路径名的字符串指针
fd = create(filenamep, mode);
  1. 创建成功后,存取权限存放在 inode 的 i_mode 中。

  2. fd 是创建成功后系统返回的文件描述符,即用户打开文件表中相应文件表项的序号。

  3. create() 创建的同时也打开了文件。

  4. 创建过程:

    create("path", 0775)
    
    1. 为新文件 newfile 分配磁盘 inode 和活动 inode,并把 inode 编号与文件分量名 newfile 组成新目录项,记到目录中,这个过程中执行目录检索程序。
    2. 在新文件所对应的活动 inode 中置初值,如置存取权限 i_mode=0775,连接计数 i_nlink=1 等。
    3. 分配用户打开文件表项系统打开文件表项,为后者置初值,包括特征位为写,读写位移 f_offset 清 0。
    4. 把各表项及文件对应的活动 inode 用指针连接起来
    5. 把文件描述字 fd 返回给调用者。

撤销文件

“撤销文件”用于删除一个文件。

所需参数:文件名和设备类(号)。

处理流程:若文件没有关闭,先关闭文件;若为共享文件,进行联访处理;在目录文件中删去相应目录项;释放文件占用的文件存储空间。

  1. 删除把指定文件从所在的目录文件中除去。
  2. 如果没有连接用户(i_link 为 1),还要把文件占用的存储空间释放。删除系统调用形式为:unlink(filenamep)
  3. 在执行删除时,必须要求用户对该文件具有”“操作权。

打开文件

“打开文件”用于建立起文件和用户进程之间的使用联系。

所需参数:文件名、设备类(号)、打开方式。

处理流程:在主存活动文件表中申请一个项,返回一个文件句柄;跟据文件名查找目录文件,把目录信息复制到活动文件表相应栏;按存取控制说明检查访问的合法性;若打开的是共享文件,则应有相应处理。

int fd, mode;
char * filenamep;
fd = open(filenamep, mode);
  1. 文件使用前需要打开,以建立进程与文件之间的联系,而文件描述符唯一标识了这种连接,其任务是把文件的磁盘 inode 复制到内存活动 inode中去,同时建立一个独立的读写文件数据结构,即系统打开文件表的一个表项。
  2. 打开过程:
    1. 检索目录
      1. 如果没有则会出错
      2. 检索到指定文件后,把它的磁盘 inode 复制到活动 inode 表中。
      3. 如果 inode 号已经在活动表项中则直接执行下一步。
    2. 根据参数 mode 核对权限(与创建时的 mode)
      1. 如果非法,则这次打开失败。
      2. 当“打开”合法时,为文件分配用户打开文件表项系统打开文件表项,并为后者赋初值。通过指针建立这些表项与活动 inode 间的联系。把文件描述字,即用户打开文件表中相应文件表项的序号返回给调用者。
  3. 输入是含路径的文件名 → 依据层次式目录结构解释与检索 → 匹配文件名并读取目录项 → 提取 inode 号 → 按号定位,在 inode 区读取 inode 数据结构(主存活动 inode)
  4. 系统实现上必须有 inode 号,但是对文件名而言是透明的。

关闭文件

“关闭文件”用于结束一个文件的读写。

所需参数:文件句柄。

处理流程:将活动文件表中该文件的“当前使用用户数”减 1;若此值为 0,则收回此活动文件表;完成“推迟写”;若活动文件表目内容已被改过,则应先将表目内容写回文件存储器上相应表目中,以使文件目录保持最新状态。

int fd;
close(fd);
  1. 关闭文件时需要释放掉 inode 来保证空间。
  2. 关闭过程
    1. 根据 fd 找到用户打开文件表项,再找到系统打开文件表项。释放用户打开文件表项
    2. 把对应系统打开文件表项中的 f_count 减 1,如果非 0,说明还有进程共享这一表项,不用释放直接返回;否则释放表项。
    3. 把活动索引节点中的 i_count 减 1,若不为 0,表明还有用户进程正在使用该文件,不用释放而直接返回,否则在把该活动索引节点中的内容复制回文件卷上的相应索引节点中后,释放该活动索引节点。
  3. f_count 和 i_count 分别反映进程动态地共享一个文件的两种方式
    1. f_count 反映不同进程通过同一个系统打开文件表项共享一个文件的情况;
    2. i_count 反映不同进程通过不同系统打开文件表项共享一个文件的情况。
  4. 通过两种方式,进程之间既可用相同的位移指针 f_offset,也可用不同位移指针 f_offset 共享同一个文件。

读/写文件

“读/写文件”用于读写文件。

所需参数:文件句柄、用户数据区地址、读写的记录或字节个数。

处理流程:按文件句柄从活动文件表中找到该文件的目录项信息;根据目录项指出的该文件的逻辑和物理组织方式,把相关逻辑记录转换成物理块。

int nr;     // 系统调用后实际读入的字节数
int fd;     // 文件描述符
int count;  // 要求传送的字符
char buf[]; // 应该输入的用户数据区的首地址
nr = read(fd, buf, count);
  1. 读指将文件的内容读入用户数据区,读入数据的逻辑地址由 offset 决定
  2. 读文件过程
    1. 系统根据 f_flag 中的信息,检查读操作合法性
    2. 如果合法,再根据当前位移量 f_offset 值,要求读出的字节数,及活动索引节点中 i_addr 指出的文件物理块存放地址,把相应的物理块读到缓冲区中,然后再送到 buf 指向的用户主存区中。
int nw;     // 系统调用后实际写入的字节数
int fd;     // 文件描述符
int count;  // 要求传送的字符
char buf[]; // 数据传送的源地址
nw = write(fd, buf, count);

写是将用户数据区的数据写入文件中,写入数据的逻辑地址由 offset 决定

定位文件

“定位文件”用于调整所打开文件的读写指针位置。

所需参数:文件句柄,定位指针。

  1. 在文件初次“打开”时,文件的位移量 f_offset 清空为 0,以后的文件读写操作总是根据 offset 的当前值,顺序地读写文件。为了支持文件的随机访问,提供系统调用 lseek,它允许用户在读、写文件前,事先改变 f_offset 的指向系统调用的形式为:
long offset;      // 当前的 offset
int whence;       //
int fd;           // 指向一个以读或写方式打开的文档
lseek(fd, offset, whence);
  1. 文件描述字 fd 必须指向一个用读或写方式打开的文件
    1. 当 whence 是 0 时,则 f_offset 被置为 offset,
    2. 当 whence 是 1 时,则 f_offset 被置为文件当前位置加上 offset。

文件系统的实现层次