博客列表 - 第 4 页

共 92 篇文章

操作系统复习 第四章

# 第四章 存储器管理 存储器是计算机系统的重要组成部分之一。 对存储器加以有效管理,不仅直接影响存储器的利用率,而且对系统性能有重大影响。存储器管理的主要对象是内存,对外存的管理在文件管理中。 ## 存储器的层次结构 - 存储器的多层结构 - 理想的存储器: - 速度快 - 容量大 - 价格低 - 现代计算机系统的存储部件实际上采用了层次结构,组成了一-个速度由快到慢,容量由小到大,价格由高到低的存储装置层次。 - 可执行存储器 - 寄存器和主存储器为可执行存储器。 - 进程访问可执行存储器:使用load或者store指令便可访问 - 进程访问辅存:通过I/O设备实现,在访问中将涉及到中断、设备驱动程序以及物理设备的运行。 - 层次结构 - 寄存器 - 寄存器访问速度最快,完全能与CPU协调工作,但价格昂贵,因此容量不可能做得很大。寄存器的长度一般以字为单位。 - 高速缓存 - 是现代计算机结构中的一个重要部件,其容量大于或远大于寄存器,速度快于主存储器。 - 根据局部性原理,将主存储器中一些经常访问的信息存放在高速缓存中,减少访问主存储器的次数,提高程序执行速度。 - 主存储器 - 简称内存或主存,用于保存进程运行时的程序和数据,也成为可执行存储器。 - CPU的控制部件只能从主存储器中取得指令和数据,数据能够从主存储器读取并将他们装入到寄存器中,或者从寄存器存入到主存储器中。 - 外存 - 由于I/O速度远低于对主存的访问速度,因此加了磁盘缓存,利用它将使用频繁的部分磁盘数据和信息,暂时存放在磁盘缓存中,用以减少磁盘访问次数。 - 它利用主存空间来暂存从磁盘中读出的信息。 ## 程序的连接与装入 在多道程序环境下,要使程序运行,必须为之。先建立进程。创建进程的第一件事是将程序和数据装入内存。 将用户源程序变为可在内存中执行的程序的步骤: - 编译:由编译程序将用户源代码编译成若干个目标模块 - 链接:由链接程序将编译后形成的一组目标模块,以及它们所需要的库函数链接在一起,形成一个完整的装入模块 - 装入:由装入程序将装入模块装入内存 ### 程序的装入 - 绝对装入方式 - 在编译时,如果知道程序驻留在内存的什么位置,那么编译程序将产生绝对地址的目标代码。 - 装入模块装入内存后,程序中的逻辑地址与实际内存地址完全相同,不须对程序和数据的地址进行修改。 - 程序中所使用的绝对地址,可在编译或汇编时给出,也可由程序员赋予。 - 只适合于单道程序环境 - 可重定位装入方式(Relocation Loading Mode) - 在多道程序环境下,可重定位装入方式,根据内存的当前情况,将装入模块装入到内存的适当位置。 - 注意:在采用可重定位装入方式将装入模块装入内存后,会使装入模块中的所有逻辑地址与实际装入内存的物理地址不同。 - 在装入时对目标程序中指令和数据的修改过程称为重定位。地址变换在装入时一次完成,以后不再改变,称为静态重定位。 - 动态运行时的装入程序 - 在把装入模块装入内存后,并不立即把装入模块中的相对地址转换为绝对地址,而是把这种地址转换推迟到程序真正要执行时(访问内存之前)才进行。 - 装入内存后的所有地址都仍是相对地址。 - 为使地址转换不影响指令的执行速度,应设置一个重定位寄存器。 - 重定位寄存器:存放装入模块的起始位置 ### 程序的链接 - 静态链接方式 - 在程序运行前,将目标模块及所需的库函数链接成一个完整的装配模块 ,以后不再拆开。 - 将目标模块装配成装入模块时需解决的两个问题: - 对相对地址进行修改 - 变换外部调用符号 - 库有两种:静态库和动态库。windows. 上对应的是.lib .dll、 linux. 上对应的是.a .so - 静态库 - :在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中。因此对应的链接方式称为静态链接。 - 静态库对函数库的链接是放在编译时期完成的程序在运行时与函数库再无瓜葛,移植方便。 - 浪费空间和资源,因为所有相关的目标文件与牵涉到的函数库被链接合成一个可执行文件 - 动态库 - 动态库在程序编译时并不会被连接到目标;代码中,而是在程序运行时才被载入。 - 不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题。 - 装入时动态链接 - 用户源程序经编译后所得的目标模块,是在装入内存时,边装入边链接的,即在装入一个目标模块时,若发生一个外部模块调用事件,将引起装入程序去找出相应的外部目标模块,并将它装入内存,还要修改目标模块中的相对地址 - 优点: - 便于修改和更新 - 便于实现对目标模块的共享。 - 运行时动态链接 - 运行时动态链接是将对某些模块的链接推迟到执行时才执行,即在执行过程中,当发现一个被调用模块尚未装入内存时,立即由OS去找到该模块并将之装入内存,把它链接到调用者模块上。 - 凡执行过程中未被用到的目标模块,不会调入内存和链接,这样不仅加快程序的装入过程。而月节省大量的内存空间. ## 连续分配存储方式 连续分配方式:为一个用户程序分配一个连续的存储空间。 ### 单一连续分配 - 最简单,只适用于单用户、单任务系统,内存只有一道用户程序 - 内存分为两部分: - 系统区 - 内存的低址部分,仅供OS使用 - 不一定需要内存保护 - 用户区 - 系统区以外的全部内存空间,供用户程序使用,存储器利用率低 ### 固定分区分配 将内存用户空间划分为若干个固定大小的区域,在每个分区中只装入一道作业,便可以有多道作业并发执行。 当有一空闲分区时,便可以再从外存的后备作业队列中,选择一个适当大小的作业装入该分区,当该作业结束时,可再从后备作业队列中找出另一作业调入该分区。 - 划分分区 - 分区大小相等 - 适用于控制多个相同对象的场合 - 缺乏灵活性,小程序浪费空间,大程序无法装入 - 分区大小不等 - 解决了灵活性问题,将内存分为多个大小不等的分区:小分区(较多) ,中等分区(适量) ,大分区(少量) - 内存分配 - 分区说明表 - 用于管理和分配内存的数据结构。 - 每个表项对应一个分区,记载着这个分区的序号、空间大小、起始地址和使用状况。 - 分配过程 - 当有一用户程序要装入时,由内存分配程序检索该表,从中找出一-个能满足要求的、尚未分配的分区,将之分配给该程序,然后将该表项中的状态置为“已分配”; - 若未找到大小足够的分区,则拒绝为该用户程序分配内存。 ### 动态分区分配 动态分区法在作业执行前并不建立分区,分区的建立是在作业的处理过程中进行的,且其大小可随作业或进程对内存的要求而改变。 这就改变了固定分区法中那种即使是小作业也要占据大分区的浪费现象,从而提高了内存的利用率。 采用动态分区法,在系统初启时,除了操作系统中常驻内存部分之外,只有一-个空闲分区。随后,分配程序将该区依次划分给调度选中的作业或进程。 - 在实现过程中涉及如下问题: - 分区分配中的数据结构 - 空闲分区表 - 在系统中设置-一张空闲区表,每个表目记录-个空闲区,主要参数包括分区号、长度和起始地址。 - 空闲分区链 - 在每个分区的起始部分,设置一些用于控制分区分配的信息,以及用于链接各分区所用的前向指针;在分区尾部则设置一后向指针,将所有的空闲分区链接成一个双向链。 - 分区分配算法 - 把一个新作业装入内存时,须按照一 定的动态分区分配算法,从空闲分区表(或空闲分区链)中选出一个分区分配给该作业。由于分配算法算法对系统性能有很大的影响,因此人们对它进行了广泛的研究。 - 基于顺序搜索的动态分区分配算法 - 首次适应算法(First Fit) - 要求按地址递增的次序组织空闲区表(链)。 - 申请和分配:从低地址找起,直至找到-个能可满足要求的空闲分区,根据作业大小划出一-块给申请者,剩余空间仍留在空闲链中,成为一个小的空闲分区。 - 优点: - 优先使用内存中低址部分的小空闲区,从而保留了高址部分的大空闲区,有利于大作业。 - 缺点: - 低址部分不断被划分,形成许多难以利用的小空闲分区(碎片) ,造成间浪费 - 碎片聚集在低址区域,每次又从低址开始查找,增加时间开销 - 循环首次适应算法(Next Fit) - 是FF算法的演变和改进,每次分配不再从空闲分区链(表)的开始找起,而是从上次找到的空闲分区的下一个找起,找到一个能满足要求的空闲区。 - 需增设一个起始查寻指针,指示下一次查找从那个空闲分区开始。 - 优点:使空闲分区分布均匀,减少查找开销 - 缺点:缺乏大空闲分区,不利于大作业 - 最佳适应算法(Best Fit) - '最佳”的含义:把能满足要求的最小空闲分区分配给作业,避免“大材小 用” - 空闲分区链组织方式:按容量从小到大 - 优点:尽量使用小空闲区,保留大空闲区 - 孤立地看,对每个程序,分区大小是最合适的,浪费最小 - 宏观上看,每次分配切割下来的剩余部分最小,因此会形成许多难以利用的碎片 - 最坏适应算法(Worst Fit) - 总是挑选最大的空闲分区分割给作业使用 - 空闲分区链组织方式:按容量从大到小 - 优点: - 防止产生碎片,空间浪费最少有利于中、小作业 - 查找效率很高(只需查找第一块) - 缺点 - 缺乏大的空闲分区 - 基于索引搜索的动态分区分配算法 - 快速适应算法 - 也称分类搜索法 - 将空闲分区按大小分类,每类具有相同容量,放入一个空闲分区链表 - 增设一张管理索引表,每个表项对应一个分类,并记录相应链表的表头指针 - 即:按分区容量大小,分类索引、搜索 - 优点: - 查找效率高,仅需要根据进程的长度,寻找到能容纳它的最小空闲区链表,并取下第一块进行分配即可。 - 缺点: - 在分区归还主存时算法复杂,系统开销较大 - 浪费空间,空闲分区划分越细,浪费则越严重。 - 伙伴系统 - 无论已分配分区或空闲分区,分区大小必须是2的k次幂,k为整数, I≤k≤m - 2<sup>m</sup>表示最大分区大小,通常是整个可分配内存的大小 - 每次切分必须对半分(分开的两半称之为一对伙伴) - 每次合并必须与其伙伴合并 - 分配过程: - 首先计算一个i值 ,使2<sup>i-1</sup><n<=2<sup>i</sup> - 在分区大小为2<sup>i</sup>的空闲分区链表中查找,找到则分配,否则转3 - 查找分区大小为2i+1的空闲分区链表,若存在空闲分区,则将其划分为两个大小相同(2<sup>i</sup>)的分区(一对伙伴) , 一个用于分配,一个加入到分区大小为2的空闲分区链表。若仍然找不到, 转4 - 继续查找大小为2<sup>i+2</sup>的空闲分区链表,此时需要进行两次划分 - 以此类推 - 回收 - 回收时,与其伙伴分区合并一次回收可能进行多次合并 - 性能 - 时间开销:查找、分割、合并空闲分区 - 哈希算法 - 哈希算法就是利用哈希快速查找优点,以及空闲分区在可利用空间表中的分布规律,建立哈希函数,构造一张以空闲分区大小为关键字的哈希表,该表的每一个表项记录了一个对应的空闲分区链表表头指针。 - 当进行空闲分区分配时,根据所需要的分区大小,通过哈希函数计算,即得到在哈希表中的位置,从中得到相应的空闲分区链表,实现最佳分配策略。 - 分区分配及回收操作 - **分配**:利用某种分配算法,从空闲分区链(表)中找到所需大小的分区。设请求的分区大小为u.size ,表中每个空闲分区的大小表示为m.size ,若m.size- u.sizessize(规定的不再切割的分区大小, 将整个分区分配给请求者,否则从分区中按请求的大小划出一块内存空间分配出去,余下部分留在空闲链中,将分配区首址返回给调用者。 - **回收**:当某一个用户作业完成释放所占分区时,系统应进行回收。在可变式分区 中,应该检查回收区与内存中前后空闲区是否相邻 - 若相邻,则应进行合并,形成一个较大的空闲区,并对相应的链表指针进行修改 - 若不相邻,应将空闲区插入到空闲区链表的适当位置。 ### 动态重定位分区分配 动态分区分配方式,要求把一个系统程序或用户程序装入一个连续的内存空间中。 随着各进程不断申请和释放内存,导致在内存中出现大量分散的小空闲区。 内存中这种容量太小、无法利用的小分区称做<mark>(外部)“碎片"</mark>或“零头” **碎片**: - 内部碎片:指已分配给作业的存储空间中未被利用的部分。如固定分区中存在的碎片。 - 外部碎片:指系统中无法利用的小空闲分区。如动态分区中存在的碎片。 **动态重定位分区分配** - 将内存中所有作业移到内存一端(作业在内存中的位置发生了变化,这就必须对其地址加以修改或变换,即重定位) , 使本来分散的多个小空闲分区连成一个大的空闲区 - 这种通过移动作业从把多个分散的小分区拼接成一个大分区的方法称为拼接或紧凑。 - 拼接时机: - 分区回收时;当找不到足够大的空闲分区,且总空闲分区容量可以满足作业要求时。 - 定时。 - 实现 - 作业被装入内存后所有地址仍然是相对地址,将相对地址转换为物理地址的工作,被推迟到程序指令真正执行时。 - 需要硬件地址变换机构的支持 - 重定位寄存器,保存作业在内存中的起始地址 - “紧凑”之后,程序移动了位置,只需更改重定位寄存器的内容为新的起始地址 ![](../../../../assets/default.png) ## 对换 - 问题 - 内存中被阻塞的进程占用大量空间,外存,上却有许多作业因为内存不足而等待。 - 对换 - 把内存中暂时不能运行的进程或暂时不用的程序和数据调出到外存上,以便腾出足够的内存空间 - 类型 - 进程 - “整体对换”, "进程对换”,常用于中级调度、分时系统 - “页”或"段” - "页面对换”或"分段对换”,统称“部分对换”,用于支持虚拟存储系统 - 空间管理 - 一般从磁盘上划出一块空间作为对换区使用 - 在系统中设置相应的数据结构以记录外存的使用情况 - 对换空间的分配与回收,与动态分区方式时的内存分配与回收雷同。 - 进程的换入与换出 - 进程的换出 - 选择换出进程的优先次序 - 阻塞>睡眠>优先级&驻留时间>就绪进程 - 换出过程 - 申请对换空间(外存) - 启动磁盘并传送数据 - 回收内存空间 - 修改数据结构 - 进程的换入 - 选择 - “就绪”已换出>换出最久 - 换入过程 - 申请内存 - 申请成功,直接调入 - 申请失败,先换出,再换入 - 对换伴随着较大的系统开销 - CPU时间 - I/O开销 - 不必要的对换可能导致系统性能下降 - 常用方案:正常时并不启用对换,内存紧张时,启用对换,把部分进程调出,缓解紧张状况后,暂停对换程序 ## 分页存储 - 连续分配方式的缺点: - 会形成许多“碎片” - “紧凑”产生较大开销 - 离散分配方式 - 允许将一个进程分散地装入多个不相邻的分区,从而无需“紧凑”。 - 可按离散分配的基本单位,分为两种方式: - 分页存储管理方式 - 分段存储管理方式 - 段页式存储管理方式 **页面** - 把进程的逻辑地址空间划分成若干大小相等的区域,每个区域称作**页面**或**页**。每个页都有一个编号,叫做页号。页号一般从0开始编号,如0 , 1, 2, ...等。 - 把内存空间划分成若3 F和页大小相同的物理块,这些物理块叫**页框**(frame)或(物理)块。同样,每个物理块也有一个编号,块号从0开始依次顺序排列。 - 以**页**为单位进行内存分配,并按进程的页数多少来分配。逻辑上相邻的页,物理上不- 定相邻。 - **“页内碎片”**:最后一页装不满而形成的碎片,不可利用。 **页面大小** - 页太大,页表短,管理开销小,内碎片大,内存利用率低 - 页太小:内碎片小,内存利用率高,但页面数目多,使页表过长,占大量内存,管理开销大 - 页面大小由硬件地址结构决定,机器确定,页面大小就确定了 - 一般来说,页面大小为2的若干次幂,根据计算机结构的不同,其大小从1 KB到8KB不等。 **地址结构**: - 分页地址中的地址结构如下: - ![](../../../../assets/default.png) - 地址长度32位: - 0~11位为位移量(页内地址),即每页的大小为4KB - 12-31位为页号,地址空间最多允许有1 M页 - 对于某特定的机器,其地址结构是一定的。 - 如果给定的逻辑地址是A ,页面的大小为L ,则: - <mark>页号P = INT[A/L]</mark> - <mark>页内地址d = [A] MOD L</mark> **页表** - 进程的每一页离散地存储在内存的任一存储块中,为方便查找,系统为每一进程建立一张页面映像表,简称页表。 - 页表实现了从页号到物理块号的地址映射。 **地址变化机构** - 由于页内地址和(块内)物理地址是一-对应的 ,地址变换机构的任务实际上是将逻辑地址中的页号转换为内存中的物理块号。 - 基本的地址变换机构 - 页表寄存器PTR - 每个进程对应一个页表,页表驻留在内存中,页表始址和长度存放在PCB中,进程被调度时,这两个数据被装入页表寄存器 - 地址变换处理 - 得到页号:自动将逻辑地址分为页号和页内地址 - 用页号查页表,得到块号 - 将块号与页内地址拼接,即得物理地址 - 越界保护 - 查页表前,将页号与PTR中的页表长度比较,超出(> =)则越界 - 具有快表的地址变换机构 - 对于基本的地址变换机构(无快表) ,每存取一个数据,需要访问两次内存 - 访问页表=>数据所在的块号,形成物理地址 - 访问数据所在的物理地址=>数据 - 增设一个联想寄存器(快表TLB ) - 具有并行查询能力的高速缓冲寄存器 - 存放当前访问的那些页表项 - 每次地址变换时,先在快表中查找页号 - 快表中找不到,再访问内存中的页表,并将页表项存入快表,若快表已满,应换出最老的页表项 - 命中率:第3步时,在快表中查找成功的概率。 **局部性原理** - 时间局部性:如果执行了程序中的某条指令,那么不久后这条指令很有可能再次执行;如果某个数据被访问过,不久之后该数据很可能再次被访问。(因为程序中存在大量的循环) - 空间局部性:一旦程序访问了某个存储单元,在不久之后,其附近的存储单元也很有可能被访问。(因为很多数据在内存中都是连续存放的) **访问内存的有效时间:** - 进程发出指定逻辑地址的访问请求,到在内存中找到对应的实际物理地址单元并取出数据,所需要花费的总时间,为内存的有效访问时间(EAT)。 - 假设访问一次内存的时间为t ,在基本分页存储管理方式中,有效访问时间为 - EAT=t+t=2t - 在引入快表的分页存储管理方式中,有效访问时间的计算公式即为: - EAT =axλ+ (t+λ)(1-a)+t=2t+λ-txa - λ表示查找快表所需要的时间, a表示命中率, t表示访问一次内存所需要的时间。 **两级和多级页表** - 现代计算机系统都支持非常大的逻辑地址空间(232~264) ,页表就非常大,需占用较大的地址空间。 - 解决方法: - 采用离散方式存储 - 只将当前所需页表项调入内存 - 二级页表 - 将页表分页,并离散地将各个页面分别存放在不同的物理块中,同时为离散分配的页表再建立一张页表,称为外层页表,其每个页表项记录了页表页面的物理块号。 - ![](../../../../assets/default.png) - 上述方法用离散分配空间解决了大页表无需大片存储空间的问题,但并未减少页表所占的内存空间。 - 解决方法: - 把当前需要的一批页表项调入内存,以后再根据需要陆续调入。在采用两级页表结构的情况下,对正在运行的进程,必须将其外层页表调入内存,而对页表则只需调入一页或几页。 - 这就需要在外层页表项中增设一个状态位S ,用于表示该页表是否内存调入内存。 - 多级页表 - 二级页表的扩展,对外层页表再分页 **反置页表** - 反置页表是为每一个物理块设置一个页表项并将按物理块号排序,其中的内容则是页号及其隶属进程的标志符。 - 所有进程共同使用一张页表 - ![](../../../../assets/default.png) ## 分段存储 - 引入 - 分页从根本.上克服了外部碎片(地址空间、物理空间都分割)。内存利用率提高。 - 缺点 - 无论信息内容如何,按页长分割,分割后装入内存,有可能使逻辑完整的信息分到不同的页面, 执行速度降低 - 所以考虑以逻辑单位分配内存。 - 分页主要是为了提高系统资源利用率 - 分段主要是为了满足用户(程序员)的需求 - 方便编程. - 信息共享 - 信息保护 - 动态增长或者动态链接 - 分段 - 进程的地址空间:按照程序自身的逻辑关系划分为若干个段,每个段都有一个段名(在低级语言中,程序员使用段名来编程),通常用段号代替段名,每段从0开始编址,段内地址是连续的。 - 段长由逻辑信息组的长度决定,逻辑地址由段号(段名)和段内地址所组成。 - 段表 - 分段式存储管理:以段为单位分配内存,每一个段在内存中占据连续空间,各段之间可以不连续存放。 - 为使程序正常运行,须在系统中为每个进程建立一张段映射表,简称"段表”。每个段在表中占有一个表项。 - 段表结构:段号;段在内存中的起始地址(基址) ;段长。 - 段表可以存放在寄存器中,但更多的是存放在内存中。 - 段表用于实现从逻辑段到物理内存区的映射。 - 分页与分段 - 相似点 - 采用离散分配方式,通过地址映射机构实现地址变换 - 不同点 - 页是信息的物理单位,分页是为了满足系统的需要;段是信息的逻辑单位,含有意义相对完整的信息,是为了满足用户的需要。 - 页的大小固定且由系统确定,由系统把逻辑地址分为页号和页内地址,由机器硬件实现;段的长度不固定,取决于用户程序,编译程序对源程序编译时根据信息的性质划分。 - 分页的作业地址空间是一维的;分段的作业地址空间是二维的。 - 信息共享 - 分段系统的一个突出优点是易于实现段的共享和保护,允许若干个进程共享一个或多个分段,且对段的保护十分简单易行。 - 分页系统中虽然也能实现程序和数据的共享,但远不如分段系统方便。 - 分页系统的信息共享 - 共享页面时只需要在物理内存中保存一个编辑器的拷贝。 - 每个用户的页表映射到编辑器的同一物理拷贝,而数据页映射到不同的块。 - 分段系统的信息共享 - 在分段系统中,实现共享十分容易,只需在每个进程的段表中为共享程序设置一个段表项。 ### 段页式存储 - 作业地址空间进行段式管理。( 面向用户 ) - 每段内再分成若干大小固定的页,每段都从零开始为自己的各页依次编写连续的页号。 - 对内存空间的管理仍然和分页存储管理一样,将其分成若干个和页面大小相同的物理块。(面向机器 ) - 作业的逻辑地址包括3个部分:段号、页号和页内位移。 - 为实现地址变换,段页式系统设立了段表和页表。 ![](../../../../assets/default.png)

操作系统复习 第五章

# 第五章 虚拟存储器 虚拟存储器:是指具有请求调入功能和置换功能,能从逻辑.上对内存容量加以扩充的一种存储器系统。其逻辑容量由内存容量和外存容量之和所决定,其运行速度接近于内存速度,而每位的成本却接近于外存。 ## 概述 - 常规处理器管理方式的特征 - 一次性 - 作业必须一次性全部装入内存后才能开始运行。 - 这会造成两个问题: - 作业很大时,不能全部装入内存,导致大作业无法运行 - 当大量作业要求运行时,由于内存无法容纳所有作业,因此只有少量作业能运行,导致多道程序并发度下降。 - 驻留性: - 一旦作业被装入内存,就会一直驻留在内存中,直至作业运行结束。 - 事实上,在一个时间段内,只需要访问作业的一小部分数据即可正常运行,这就导致了内存中会驻留大量的、暂时用不到的数据,浪费了宝贵的内存资源。 - 局部性 - 基于局部性原理,在程序装入时,可以将程序中很快会用到的部分装入内存,暂时用不到的部分留在外存,就可以让程序开始执行。 - 在程序执行过程中,当所访问的信息不在内存时,由操作系统负责将所需信息从外存调入内存,然后继续执行程序。 - 若内存空间不够,由操作系统负责将内存中暂时用不到的信息换出到外存。在操作系统的管理下在用户看来似乎有一个比实际内存大得多的内存,这就是虚拟内存 虚拟内存的最大容量是计算机的地址结构, CPU寻址范围决定的。 <mark>虚拟内存的实际容量是内存与外存之和, CPU寻址范围,两者的最小值</mark> - 虚拟存储器的特征 - 多次性 - 一个作业被分成多次调入内存运行。多次性是虚拟存储器最重要的特征,与常规存储器管理的一次性相对应。 - 对换性 - 系统允许作业在运行过程中进行换进、换出操作。换进和换出能有效地提高内存利用率。 - 虚拟性 - 虚拟性是指从逻辑上扩充内存容量,并非实际存在。用户感觉到的很大的虚拟存储容量实际上是一种“假象” <mark>虚拟存储器的实现都是建立在离散分配的存储管理方式的基础上。</mark> ## 请求分页系统 - 在分页系统的基础上,增加了请求调页功能和页面置换功能所形成的页式虚拟存储系统。置换时以页面为单位。 - 为实现请求调页和置换功能,系统必须提供必要的支持: - 硬件支持: - 请求分页的页表机制 - 在请求分页系统中所需要的主要数据结构是页表。其基本作用仍然是将用户地址空间中的逻辑地址变换为内存空间中的物理地址。 - 由于只将应用程序的一部分调入内存,还有一部分仍在盘上,故需在页表中再增加若干项,供程序(数据)在换进、换出时参考。 - ![](../../../../assets/default.png) - 缺页中断机构 - 在请求分页系统中,每当要访问的页面不在内存时,便产生一缺页中断,请求OS将所缺之页调入内存。 - 缺页中断作为中断,同样需要经历诸如保护CPU环境、分析中断原因、转入缺页中断处理程序进行处理、恢复CPU环境等几个步骤。 - 但缺页中断是一种特殊的中断,与一般中断有明显区别: - 缺页中断在指令执行期间产生和处理中断信号,而一般中断在一条指令执行完后检查和处理中断信号。 - 缺页中断返回到该指令的开始重新执行该指令,而一般中断返回到该指令的下一条指令执行。 - 一条指令在执行期间,可能产生多次缺页中断。 - 地址变换机构 - 请求分页系统中的地址变换机构,是在分页系统地址变换机构的基础上,再为实现虚拟存储器而增加了某些功能而形成的,如产生和处理缺页中断,以及从内存中换出一页的功能等。 - 软件支持: - 实现请求调页的软件 - 实现页面置换的软件 - 请求分页中的内存分配 - 最小物理块数的确定 - 最小物理块数,指能保证进程正常运行所需的最小物理块数。当系统为进程分配的物理块数少于此值时,进程将无法运行。 - 进程应获得的最小物理块数与计算机的硬件结构有关,取决于指令的格式、功能和寻址方式。 - 物理块的分配策略 - 在请求分页系统中,可采取两种内存分配策略: - 固定分配策略:为每个进程分配一定数目的物理块,在整个运行期间不再改变 - 可变分配策略:先为每个进程分配一定数量的物理块,在整个运行期间可适当增多或减少。 - 在进行置换时,也可采取两种策略 - 全局置换:发生缺页时,只选进程自己的物理块置换 - 局部置换:可以将操作系统保留的空闲物理快分配给进程,也可以将别的进程持有的物理块置换到外存,再分配给缺页进程。 - 组合出的三种策略: - 固定分配局部置换(Fixed Allocation , Local Replacement) - 为每个进程分配一定数目的物理块,在整个运行期间不再改变。 - 采用该策略时,如果进程在运行中发现缺页,只能从该进程在内存中的n个页面中选出一页换出,然后再调入一页。 - 困难:应为每个进程分配多少个物理块难以确定。 - 可变分配全局置换(Variable Allocation , Global Replacement) - 在采用这种策略时,先为系统中的每个进程分配一定数目的物理块,而OS自身也保持一个空闲的物理块队列。 - 如果某进程发生缺页时,由系统从空闲的物理块队列中,取出一个物理块分配给该进程,并将欲调入的页装入其中。 - 当空闲物理块队列中的物理块用完后, OS才能从系统中的任一进程中选择一页调出。 - 可变分配局部置换(Variable Allocation , Local Replacement) - 为每个进程分配一定数目的物理块,如果某进程发生缺页时,只允许从该进程在内存的页面中选出一页换出,不会影响其他进程执行。 - 如果进程在运行中频繁发生缺页中断,则系统再为进程分配若干物理块 - 如果进程在运行中缺页率特别低,则适当减少分配给该进程的物理块。 - 物理块的分配算法 - 在采用固定分配策略时,如何将系统中可供分配的物理块分配给各个进程,可采用以下几种算法: - 平均分配算法:将系统中所有可供分配的物理块,平均分配给各个进程。 - 按比例分配算法:根据进程的大小按比例分配物理块。 - 设系统中共有n个进程,每个进程的页面数为Si ,则系统中各进程页面数的总和为: $$ S=\sum_{i+1}^{n}S^i $$ - 又假定系统中可用的物理块总数为m ,则每个进程所能分到的物理块数为bi ,将有 $$ b_i=\frac{S_i}{S}*m $$ - bi应该取整,必须大于最小物理块数。 - 考虑优先权的分配算法:在实际应用中,为了照顾重要的、急迫的作业尽快完成,为它分配较多的内存空间 - 方法: - 把内存中可供分配的物理块分为两部分: - 一部分按比例分配给各进程; - 一部分则根据各进程的优先权,适当地增加其相应份额,分配给各进程。 - 页面调入策略 - 何时调入页面 - 预调页策略 - 采用以预测为基础的预调页策略,将那些预计在不久之后便会被访问的页面,预先调入内存。 - 主要用于进程的首次调入时 ,由程序员指出应该先调入哪些页。 - 请求调页策略 - 当程序在运行中需要访问某部分程序和数据时,若发现其所在的页面不在内存,便立即提出请求,由OS将其所需要的页面调入内存。 - 优点:由请求调页策略所确定调入的页, 一定会被访问;请求调页策略比较容易实现。 - 缺点:每次仅调入一页,需花费较大的系统开销,增加了磁盘I/O的启动频率。 - 从何处调入页面 - 系统拥有足够的对换区空间,这时可以全部从对换区调入所需页面,以提高调页速度。 - 系统缺少足够的对换区空间,则将不会被修改的文件直接从文件区调入,将可能会被修改调到对换区。 - 如何进行调入 - 每当程序所要访问的页面未在内存时,便向CPU发出一缺页中断,中断处理程序首先保护CPU环境,分析中断原因后,转入缺页中断处理程序。 - 程序通过查找页表,得到该页在外存上的物理块后,如果此时内存能容纳新页则启动磁盘I/O将所缺之页调入内存,然后修改页表。 - 如果内存已满,则需按照某种置换算法从内存中选出一页准备换出;如果该页未被修改过,可不必写回磁盘;但如果此页已被修改,则必须将它写回磁盘,然后把所缺的页调入内存,并修改页表中的相应表项,置其存在位为“1" , 并将此页表项写入快表。 - 在缺页调入内存后,利用修改后的页表,形成所要访问的物理地址,再去访问内存数据。整个页面调入过程对用户是透明的 - 缺页率 - 假设一个进程的逻辑空间为n页,系统为其分配的内存物理块数为m(m≤n)。 - 如果在进程的运行过程中,访问页面成功(即所访问页面在内存中)的次数为S ,访问页面失败(即所访问页面不在内存中,需要从外存调入)的次数为F ,则该进程总的页面访问次数为A= S+ F - 那么该进程在其运行过程中的缺页率即为 $$ 缺页率=\frac{缺页次数}{访问总次数} $$ - 影响缺页率的因素: - 页面大小 - 进程所分配页框的数目 - 页面置换算法 - 程序固有属性 - 请求分段系统 - 在分段系统的基础.上,增加了请求调段功能和分段置换功能所形成的段式虚拟存储系统。置换时以段为单位。 - 为实现请求调段和置换功能,系统必须提供必要的支持: - 硬件支持: - 请求分段的段表机制 - 缺段中断机构 - 地址变换机构 - 软件支持: - 实现请求调段的软件 - 实现段的置换的软件 ## 页面置换算法 在程序执行过程中,当所访问的信息不在内存时,由操作系统负责将所需信息从外存调入内存,然后继续执行程序。 若内存空间不够,由操作系统负责将内存中暂时用不到的信息换出到外存用页面置换算法决定应该换出哪个页面 页面的换入、换出需要磁盘I/O ,会有较大的开销,因此好的页面置换算法应该追求更少的缺页率 - 最佳置换算法 - 其所选择的被淘汰页面,将是以后永不再用的,或许是在最长(未来)时间内不再被访问的页面。 - 优点:保证获得最低的缺页率 - 缺点:无法预知一-个进程在内存的若干个页面,哪个在未来最长时间内不再被访问。 - 算法无法实现,但可评价其他算法。 - 先入先出页面(FIFO)置换算法 - 算法总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面予以淘汰。 - 算法实现简单,只需把一个进程已调入内存的页面,按先后次序链接成一个队列,并设置一个指针(替换指针) ,使它总是指向最老的页面。 - 算法与进程的实际运行规律不相适应,因为进程中的某些页面经常被访问,但先进先出置换算法不能保证这些页面不被淘汰。 - **Belady现象** - 采用FIFO算法时,如果对一个进程未分配它所要求的全部页面,有时就会出现分配的页面数增多但缺页率反而提高的异常现象。 - Belady现象的原因是FIFO算法的置换特征与进程访问内存的动态特征是矛盾的,即被置换的页面并不是进程不会访问的,因而FIFO并不是- -个好的置换算法。 - 最近最久未使用(LeastRecently Used)算法 - 算法根据页面调入内存后的使用情况进行决策。由于无法预测各页面将来的使用情况,只能利用“最近的过去”作为“最近的将来”的近似,因此,LRU置换算法是选择最近最久未使用的页面予以淘汰。 - 该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间t ,当需淘汰一个页面时,选择现有页面中其t值最大的,即最近最久未使用的页面予以淘汰。 - 需有以下两类硬件之一的支持: - 寄存器 - 为每个在内存中的页面配置一个移位寄存器,用来记录某进程在内存中各页的使用情况。移位寄存器表示为 - $$ R= R_{n-1}R_{n-2}R_{n-3}\cdots R_2R_1R_0 $$ - 当进程访问某物理块时,要将相应寄存器的R.1位置成1。此时,定时信号将每隔一定时间将寄存器右移一位。如果把n位寄存器的数看作一个整数,那么具有最小数值的寄存器所对应的页面,就是最近最久未使用的页面。 - 栈 - 利用一个特殊的栈来保存当前使用的各个页面的页面号 - 每当进程访问某页面时,**便将该页面的页面号从栈中移出,将它压入栈顶**。 - 栈顶始终是最新被访问页面的编号,而栈底则是最近最久未使用页面的页面号。 - 最少使用置换(Least Frequently Used)算法 - 在采用LFU算法时,应为在内存中的每个页面设置一个移位寄存器,用来记录该页面被访问的频率。该置换算法选择在最近时期使用最少的页面作为淘汰页。 - 简单的Clock置换算法 - 当采用简单Clock算法时,只需为每页设置一位访问位,再将内存中的所有页面都通过链接指针链接成一个循环队列。 - 当某页被访问时,其访问位被置1。 - 置换算法在选择一页淘汰时,只需检查页的访问位。如果是0 ,就选择该页换出;若为1 ,则重新将它置0 ,暂不换出,而给该页第二次驻留内存的机会 - 再按照FIFO算法检查下一个页面。 - 当检查到队列中的最后一个页面时,若其访问位仍为1 ,则再返回到队首去检查第一个页面。 - 因此简单的CLOCK算法选择一个淘汰页面最多会经过两轮扫描 - 改进型CLock算法 - 在将一个页面换出时,如果该页已被修改过,便须将该页重新写回到磁盘上;但如果该页未被修改过,则不必将它拷回磁盘。 - 在改进型Clock算法中,除须考虑页面的使用情况外,还须再增加一个因素,即置换代价,这样,选择页面换出时,既要是未使用过的页面,又要是未被修改过的页面。 - 把同时满足这两个条件的页面作为首选淘汰的页面。 - 由访问位A和修改位M可以组合成下面四种类型的页面: - 1类(A=0 , M=0) :表示该页最近既未被访问,又未被修改,是最佳淘汰页。 - 2类(A=0 , M=1) :表示该页最近未被访问,但已被修改,并不是很好的淘汰页。 - 3类(A=1 , M=0) :表示该页最近已被访问,但未被修改,该页有可能再被访问。 - 4类(A=1 , M=1) :表示该页最近已被访问且被修改,该页可能再被访问。 - (1)从指针所指示的当前位置开始,扫描循环队列,寻找A=0且M=0的第一类页面,将所遇到的第一个页面作为所选中的淘汰页。在第一次扫描期间不改变访问位A。 - (2)如果第一步失败,则开始第二轮扫描,寻找A=0且M= 1的第二类页面,将所遇到的第一个这类页面作为淘汰页。在第二轮扫描期间,将所有扫描过的页面的访问位都置0。 - (3)如果第二步也失败,则将指针返回到开始的位置,然后回到第一步重新开始,一定能找到被淘汰的页。 - 该算法与简单Clock算法比较,可减少磁盘的I/O操作次数。但为了找到一个可置换的页,可能须经过几轮扫描。换言之,实现该算法的开销有所增加。 - ![](../../../../assets/default.png) - 页面缓冲算法(Page Buffering Algorithm) - 影响效率的因素 - 页面置换算法。 - 写回磁盘的频率。 - 建立了一个已修改换出页面的链表,则对每一个要被换出的页面(已修改) ,系统可暂不把它们写回磁盘,而是将它们挂在已修改换出页面的链表.上,仅当被换出页面数目达到一定值时,例如64个页面,再将它们一起写回磁盘上 - 读入内存的频率。 - 如果有进程在这批数据还未写回磁盘时需要再次访问这些页面时,就不从外存上调入,而直接从已修改换出页面链表中获取,这样也可以减少将页面从磁盘读入内存的频率,减少页面换进的开销。 - 特点 - 显著地降低了页面换进、换出的频率,使磁盘I/O的操作次数大为减少,因而减少了页面换进、换出的开销; - 正是由于换入换出的开销大幅度减小,才能使其采用一种较简单的置换策略,如先进先出(FIFO)算法,它不需要特殊硬件的支持,实现起来非常简单。 - 空闲页面链表 - 该链表是一个空闲物理块链表。是系统掌握的空闲物理块,当进程需要读入一个页面时,便可利用空闲物理块来装入该页。 - 当有一个未被修改的页面要换出时,实际上并不将它换回到外存,而是把它们所在的物理块挂在空闲链表的末尾。这些挂在空闲链表中的物理块是有数据的,如果以后某个进程需要访问这些页面时,可以直接从空闲链表中取下,免除了从磁盘读入数据的操作,减少了页面换进的开销。 - 修改页面链表 - 该链表是由已修改的页面所形成的链表。设置该链表的目的是减少修改页面换出的次数。当进程需要将一个已经修改的页面换出时,系统并不立即将它换出到磁盘上,而是将它所在的物理块挂在修改页面链表的末尾。 - 当已修改页面的链表上的页面个数达到一定程度时,会-起将这些页面写回到磁盘。如果这些被换出的页面在写回磁盘之前,有进程需要访问其中的页面,那么可以直接从已修改页面链表.上获取该页面。所以可见,减少了磁盘I/O操作,并且减少了内存写入频率。 ### 访问内存的有效时间 - 查找快表时间( λ ) - 访问实际物理地址时间( t ) - 缺页中断处理时间( ε ) - 命中率(a) - 缺页率(f ) - 在内存,在快表 - EAT =快表时间+内存时间=λ+t - 在内存,不在快表 - EAT =快表时间+内存时间+修改快表时间+内存时间=λ+t+λ+t - 不在内存 - EAT =快表时间+内存时间+缺页中断时间+修改快表时间+内存时间=λ+t+ε+λ+t - 考虑命中率与缺页率 - EAT =aX(+t)+(1-a)X [fX(+t++s+i+t)+(1-f)x(2+t+i+t)]=λ+ aXt+(1-a) X [t+f X (ε+ λ+t)+(1-f) X (1+ t)] - 不考虑命中率,仅考虑缺页率, - EAT=f X (t+ε+t)+ (1-f) X(t+t)=t+f X (ε+ t)+(1-f) X t ## 抖动与工作集 ### 抖动 由于请求分页式虚拟存储器系统的性能优越,在正常运行情况下,它能有效地减少内存碎片,提高处理机的利用率和吞吐量,故是目前最常用的一种系统。 但如果在系统中运行的进程太多,进程在运行中会频繁地发生缺页情况,这又会对系统的性能产生很大的影响,故还须对请求分页系统的性能做简单的分析。 ![](../../../../assets/default.png) **刚被淘汰的页面又马.上被调回内存,调回内存不久后又被淘汰出去,如此频繁进行,这种现象称为抖动(或称颠簸)**。它使得系统中页面调度非常频繁,以致CPU大部分时间都花费在内存和外存之间的调入调出上。 发生"抖动”的根本原因是,同时在系统中运行的进程太多,由此分配给每一个进程的物理块太少,不能满足进程正常运行的基本要求。抖动是在进程运行中出现的严重问题,必须采取相应的措施解决它。 ### 工作集 ![](../../../../assets/default.png) 如果将缺页率控制在上界与下界(比如0.1%~1%) 之间,那么缺页率达到0.5%时的驻留集尺寸W将是比较适宜的。 我们无法事先预知程序在不同时刻将访问哪些页面,故仍只有像置换算法那样,用程序的过去某段时间内的行为作为程序在将来某段时间内行为的近似。 **所谓工作集,是指在某段时间间隔△里,进程实际所要访问页面的集合。** 把进程在某段时间间隔O里,在时间t的工作集记为w(t,A) ,变量△称为工作集“窗口尺寸” 对于给定的页面走向,如果△= 10次存储访问,在t1时刻的工作集是W(t1,10)=(1,2,5,6,7) ,在t2时刻,工作集是W(t2,10)=(3,4) ## 抖动的预防 - 采取局部置换策略 - 即使该进程发生了"抖动”, 也不会对其它进程产生影响,于是可把该进程”抖动”所造成的影响限制在较小的范围内 - 但在某进程发生"抖动”后,它还会长期处在磁盘I/O的等待队列中,使队列的长度增加,这会延长其它进程缺页中断的处理时间。 - 把工作集算法融入到处理机调度中 - 当调度程序发现处理机利用率低下时,它将试图从外存调入一个新作业进入内存,在从外存调入作业之前,必须检查每个进程在内存的驻留页面是否足够多。 - 如果都足够多,此时便可以从外存调入新的作业,不会因新作业的调入而导致缺页率的增加; - 反之,如果有些进程的内存页面不足,则应首先为那些缺页率居高的作业增加新的物理块,此时将不再调入新的作业。 - 利用"L=S"准则调节缺页率 - L是缺页之间的平均时间, S是平均缺页服务时间,即用于置换一个页面所需的时间。 - 如果是L远比S大,说明很少发生缺页,磁盘的能力尚未得到充分的利用; - 反之,如果是L比S小,则说明频繁发生缺页,缺页的速度已超过磁盘的处理能力。 - 只有当L与S接近时,磁盘和处理机都可达到它们的最大利用率。 - 理论和实践都已证明,利用"L=S"准则,对于调节缺页率是十分有效的。 - 选择暂停的进程 - 当多道程序度偏高时,已影响到处理机的利用率,为了防止发生“抖动”,系统必须减少多道程序的数目,以便腾出内存空间分配给那些缺页率偏高的进程。

操作系统复习 第八章

# 磁盘存储器的管理 ## 外存的组织方式 - 磁盘的物理地址(盘块号)是(柱面号,盘面号,扇区号) - 磁盘存储器中用t表示每个柱面上的磁道数(盘面数), - 用s表示每个磁道.上的扇区数, - 根据块号可以确定该块在磁盘上的位置 - 每个柱面.上有: sxt个磁盘块 - 计算第p块在磁盘上的位置,可以令d=sxt,则有: - i柱面(磁道)号=[p/d] - j盘面号=[(p mod d)/s] - k扇区号=(pmodd)mods - 文件的物理结构直接与外存的组织方式有关。对于不同的外存组织方式,将形成不同的文件物理结构。目前常用的外存组织方式有: - 顺序组织方式:早期文件系统使用,现今仅在磁盘文件对换区的使用上还能看到 其影子。 - 连续分配方式要求每个文件在磁盘上占有一-组连续的块。 - (逻辑块号,块内地址) →(物理块号,块内地址)。只需转换块号就行,块内地址保持不变 - 优点: - 顺序访问容易,支持定长记录文件随机存取; - 顺序访问速度快。 - 缺点: - 要求为一个文件分配连续的存储空间,产生外部碎片。 - 必须事先知道文件的长度。 - 不能灵活地删除和插入记录。 - 文件的动态增长困难。 - 链接组织方式:分为隐式链接和显式链接两类。FAT12、 FAT16、FAT32文件系统使用的就是显式链接方式 - 采用链接分配方式时,可通过在每个盘块.上的链接指针,将同属于一个文件的多个离散的盘块链接成一个链表, 把这样形成的文件称为链接文件。 - 链接组织方式的主要优点: - 消除了磁盘的外部碎片,提高了外存的利用率。 - 对插入、删除和修改记录都非常容易。 - 能适应文件的动态增长,无需事先知道文件的大小。 - 链接方式又可分为两种形式: - 隐式链接 - 隐式链接分配方式的主要问题: - 它只适合于顺序访问,对随机访问是及其低效的 - 可靠性差 - 为了提高检索速度和减小指针所占用的存储空间,可以将几个盘块组成一个簇(cluster)。在进行盘块分配时,是以簇为单位进行的。同样,链接文件也是以簇为单位的。 - 显式链接 - 把用于链接文件各物理块的指针显式地存放在一-张表中。 即文件分配表(FATFile Allocation Table) - 注意:一个磁盘仅设置一张FAT - 开机时,将FAT读入内存,并常驻内存 - 逻辑块号转换成物理块号的过程不需要读磁盘操作 - 文件分配表可同时管理磁盘的空闲盘块 - FAT技术 - FAT12:每个FAT表项为12位, - 每个FAT表最多允许4096 (212) 个表项,如果每个盘块大小为512 (29)B,则每个磁盘分区容量最大为2MB。 - 以簇为分配的基本单位,如果一簇包含8个扇区, 则每个磁盘分区容量为1 6MB,但是簇内碎片也会增加。 - FAT16:每个FAT表项为1 6位 - 最大表项数增值65536 (216) 个,每个簇中有最多有64个扇区,最大分区空间为216x64x 512=2048MB - FAT32 - 最大支持磁盘分区为2TB - 链接分配方式虽然解决了连续分配方式所存在的问题,但又出现了另外两个问题: - 不能支持高效的直接存取。要对一个文件进行直接存取,需首先在FAT中顺序的查找许多盘块号。 - FAT需占用较大的内存空间。当磁盘容量较大时,FAT可能要占用数MB以上的内存空间。这是令人难以忍受的。 - 索引组织方式: ext2、ext3、 ext4等UNIX文件系统采用该方式。 - 单级索引 - 索引分配允许文件离散地分配在各个磁盘块中,系统会为每个文件建立一张索引表 - 索引表中记录了文件的各个逻辑块对应的物理块(索引表的功能类似于内存管理中的页表)。 - 索引表存放的磁盘块称为索引块。文件数据存放的磁盘块称为数据块。 - 优点: - 能顺序存取,又能直接存取 - 满足了文件动态增长、插入删除的要求 - 没有外碎片,外存空间利用率较高 - 缺点 - 索引表本身需要存储空间 - 文件比较小时,索引表利用率低 - 多级索引 - 将一个大文件的所有索引表(二级索引)的地址放在另一个索引表(一级索引)中(原理类似于多级页表)。如果文件非常大,还可用三级、四级。 - 访问目标数据块,需要多次磁盘I/O - 对与中小文件,访问磁盘次数过多 - 增量式索引 - 多种索引分配方式的结合。例如,一个文件的索引结点中,既包含直接地址(直接指向数据块),又包含一次间接地址(指向单层索引表)、还包含多次间接地址(指向两层索引表) - 在UNIX System V的索引结点中设有13个地址项,即i.addr(0) ~i.addr(12) ## 文件存储空间管理 - 磁盘管理要解决的重要问题之一是如何为新创建的文件分配存储空间。 其解决方法与内存的分配情况有许多相似之处 - 连续分配方式 - 空闲表法 - 与内存的动态分配方式雷同,它为每个文件分配一块连续的存储空间。系统为外存上的所有空闲区建立一张空闲表, 每个空闲区对应于一个空闲表项,再将所有空闲区按其起始盘块号递增的次序排列 - 离散分配方式 - 空闲盘块链 - 这是将磁盘上的所有空闲空间以盘块为单位拉成一条链,其中的每一个盘块都有指向后继盘块的指针。 - 空闲盘区链 - 这是将磁盘上的所有空闲盘区拉成一条链。 在每个盘区上除含有用于指示下一个空闲盘区的指针外,还应有能指明本盘区大小(盘块数)的信息。 - 位示图法(连续离散都适用) - 利用二进制的一位来表示磁盘中一个盘块的使用情况。当其值为0时表示对 应的盘块空闲,为1时表示已分配(Linux)。 有的系统则相反。 - 磁盘上的所有盘块都有一个二进制位与之对应,这样由所有盘块所对应的位构成一个集合,称为位示图。 - 通常可用`m*n`个位数来构成位示图,并使`m*n`等磁盘的总块数。 - 存储空间的基本分配单位都是磁盘块而非字节。 - 为了实现存储空间的分配,首先必须记住空闲存储空间的使用情况。 - 数据结构 - 分配和回收功能 - 根据位示图进行盘块分配时,可分三步进行: - 顺序扫描位示图,从中找出一个或一组其值为 "0”的二进制位( "0"表示空闲时) - 将所找到的一个或-组二进制位转换成与之相应的盘块号。假定找到的其值为"0"的二进制位位于位示图的第i行、第j列,则其相应的盘块号应按下式计算:`b=n(i-1) +j`式中,n代表每行的位数 - 修改位示图,令`map[i, j] = 1` - 盘块的回收分两步: - 将回收盘块的盘块号转换成位示图中的行号和列号。转换公式为: `i= (b-1)DIV n+ 1` `j=(b-1)MODn+1` - 修改位示图。令`map[i,j] = 0`

操作系统复习 第六章

# 第六章 输入输出设备 ## I/O系统 - I/O系统管理的主要对象是I/O设备和相应的设备控制器。 - 其最主要的任务是 - 完成用户提出的I/O请求 - 提高I/O速率 - 提高设备的利用率 - 为更高层的进程方便地使用这些设备提供手段 - 基本功能 - 隐藏物理设备的细节 - 与设备的无关性 - 提高处理机和I/O设备的利用率 - 对I/O设备进行控制 - 采用轮询的可编程1/O方式 - 采用中断的可编程I/O方式 - 直接存储器访问方式 - I/O通道方式 - 确保对设备的正确共享 - 独占设备,进程应互斥地访问这类设备,即系统一旦把这类设备分配给 了某进程后,便由该进程独占,直至用完释放。典型的独占设备有打印机、磁带机等。 - 共享设备,是指在一段时间内允许多个进程同时访问的设备。典型的共享设备是磁盘,当有多个进程需对磁盘执行读、写操作时,可以交叉进行,不会影响到读、写的正确性。 - 错误处理 ![](../../../../assets/default.png) ### I/O软件 - 中断处理程序 - 当I/O任务完成时,I/O控制器会发送一个中断信号,系统会根据中断信号类型找到相应的中断处理程序并执行。 - 设备驱动程序 - 驱动程序一般会以一个独立进程的方式存在。 - 主要负责对硬件设备的具体控制,将上层发出的一系列命令(如read/write) 转化成特定设备“能听得懂”的一系列操作。包括设置设备寄存器;检查设备状态等 - 不同的I/O设备有不同的硬件特性,具体细节只有设备的厂家才知道。因此厂家需要根据设备的硬件特性设计并提供相应的驱动程序。 - 设备独立性软件 - 与设备的硬件特性无关的功能几乎都在这层实现。 - 他的主要功能有: - 向上层提供统一的调用接口,如read/write系统调用 - 设备的分配与回收 - 差错处理 - 数据缓冲区管理 - 建立逻辑设备名到物理设备名的映射关系:根据设备类型选择调用相应的驱动程序 - 用户层软件 - 实现了与用户交互的接口,用户可直接使用该层提供的、与I/O操作相关的库函数对设备进行操作。 ### 系统接口 - 块设备接口 - 块设备:用于存储信息。对于信息的存取总是以数据块为单位。典型例子是磁盘。该类设备基本特征是传输速率较高,另一特征是可寻址。工作方式常采用DMA方式。 - 隐藏了磁盘的二维结构。 - 将抽象命令映射为低层操作。 - 流设备接口 - 字符设备:用于数据的输入和输出。基本单位是字符。如交互式终端、打印机等。 - 其基本特征是传输速率较低,另一特征是不可寻址。 - 工作方式常采用中断方式。 - get和put操作。 - in-control指令。 - 网络通信接口 - 通过某种方式把计算机连接到网络上。同时操作系统也必须提供相应的网络软件和网络通信接口,使计算机能通过网络与网络.上的其它计算机进行通信或上网浏览。 ## I/O设备 - 部分 - I/O设备的机械部件主要用来执行具体I /O操作。如我们看得见摸得着的鼠标/键盘的按钮;显示器的LED屏;移动硬盘的磁臂、磁盘盘面。 - I/ O设备的电子部件通常是一块插入主板扩充槽的印刷电路板 - 分类 - 按使用特性分类 - 存储设备,也称外存或后备存储器、辅助存储器。 - 输入/输出设备 - 输入设备,如键盘、鼠标、扫描仪、视频摄像、各类传感器等。 - 输出设备,如打印机、绘图仪、显示器、音箱等。 - 交互式设备,集成上述两类设备,利用输入设备接收用户命令信息,并通过输出设备同步显示用户命令以及命令执行的结果。 - 按传输速率分类 - 低速设备,每秒钟几个字节至数百个字节 - 键盘、鼠标器、语音的输入和输出设备 - 中速设备,每秒钟数千个字节至数万个字节。 - 行式打印机、激光打印机 - 高速设备,数十万个字节至数千字节。 - 磁盘机、光盘机 ### 设备控制器 - I/O设备与CPU之间通过设备控制器通信 - 三种信号线 - 数据信号线 - 控制信号线 - 状态信号线 - ![](../../../../assets/default.png) - 设备控制器的基本功能 - 接收和识别命令 - 数据交换 - 标识和报告设备的状态 - 地址识别 - 数据缓冲区 - 差错控制 - 组成部分 - 设备控制器与处理机的接口 - 设备控制器与设备的接口 - I/O逻辑 ### 内存映像I/O ## 设备驱动程序 - 设备处理程序通常又称为设备驱动程序,它是I/O系统的高层与设备控制器之间的通信程序 - 其主要任务是接收上层软件发来的抽象I/O要求,如read或write命令,再;把它转换为具体要求后,发送给设备控制器,启动设备去执行; - 反之,它也将由设备控制器发来的信号传送给上层软件。 - 由于驱动程序与硬件密切相关,故通常应为每一类设备配置一种驱动程序。例如,打印机和显示器需要不同的驱动程序。 - 设备驱动程序的功能 - 接收由与设备无关的软件发来的命令和参数,并将命令中的抽象要求转换为与设备相关的低层操作序列。 - 检查用户I/O请求的合法性,了解I/O设备的工作状态,传递与I/O设备操作有关的参数,设置设备的工作方式。 - 发出I/O命令,如果设备空闲,便立即启动I/O设备,完成指定的I/O操作;如果设备忙碌,则将请求者的请求块挂在设备队列上等待。 - 及时响应由设备控制器发来的中断请求,并根据其中断类型,调用相应的中断处理程序进行处理。 - 处理过程 - 将抽象要求转换为具体要求 - 检查I/O请求的合法性 - 读出和检查设备的状态 - 传送必要的参数 - 启动I/O设备 - 控制方式 - 宗旨:尽量减少主机对I/O控制的干预,把主机从繁杂的IO控制事务中解脱出来 - 忙——等待方式 - CPU向控制器发出I/O指令,启动输入设备。 - 状态寄存器忙/闲标志busy置1。 - 循环测试busy, busy= 1输入未完成。 - busy=0输入完成,将数据从控制器的数据寄存器读到内存 - 由于CPU高速,I/O设备低速致使CPU极大浪费。 - 使用中断的可编程I/O方式 - CPU向控制器发出I/O指令,CPU返回继续原来的工作。 - 设备控制器控制I/O设备。CPU与I/O并行工作。 - 数据输入寄存器,控制器向CPU发出中断。 - CPU检查数据正确性,数据写入内存。 - 优点 - CPU与I/O并行工作, 提高了资源利用率和吞吐量。 - 缺点 - CPU每次处理的数据量少(通常不超过几个字节),只适于传输率较低的设备 - 直接存储器访问(Direct Memory Access) - 特点 - 数据传输的基本单位是数据块。 - 数据从设备直接送入内存,或者相反。 - 仅在传送一个或多个数据块的开始和结束时,才需CPU干预,整块数据的传送是在控制器的控制下完成的。 - DMA控制器 - 三部分 - 主机与DMA控制器的接口 - DMA控制器与块设备的接口 - I/O控制逻辑 - 四类寄存器 - 数据寄存器DR - 命令/状态寄存器CR - 内存地址寄存器MAR - 数据计数器DC - DMA工作过程 - CPU发出指令,存入CR - 内存起始目标地址送入MAR。 - 读取字节数送DC。 - 源地址送DMA的I/O控制逻辑。 - 启动DMA控制器,CPU处理其他任务。 - DMA控制读入一个字(节)到DR。 - 将该字(节)送入MAR指向的内存单元。 - MAR加1,DC减1。 - DC<> 0继续传输,DC=0发出中断。 - 中断方式是在数据缓冲寄存区满后,发中断请求,CPU进行中断处理。 - DMA方式则是在所要求传送的数据块全部传送结束时要求CPU进行中断处理,大大减少了CPU进行中断处理的次数。 - 中断方式的数据传送是由CPU控制完成的,而DMA方式则是在DMA控制器的控制下不经过CPU控制完成的。 - I/O通道控制方式 - 目的:CPU的I/O任务由通道来承担。 - 一种特殊的处理机,属于硬件技术。它具有执行I/O指令的能力,并通过执行通道程序来控制I/O操作。 - 指令类型单一、 即由于通道硬件比较简单,其所能执行的指令,主要为与I/O有关的指令 - 通道没有自己的内存,与CPU共享内存 - CPU一次读(或写)多个数据块。 - 多个数据块送入不同内存区域。 - CPU、通道和I/O设备三者的并行操作。 - 工作过程: - CPU向通道发送一条I/O指令。 - 给出通道程序首址和要访问的I/O设备。 - 通过执行通道程序完成I/O任务。 - 通道程序由一系列通道指令(通道命令)构成。 - 每条通道指令包含的信息: - 操作码 - 内存地址 - 计数 - 通道程序结束位P (P= 1表示程序结束) - 记录结束标志R (R=0表示与下一条指令处理的数据属于同一记录;R= 1表示某记录的最后一条指令) - 字节多路通道(Byte Multiplexor Channel) - 字节多路通道以字节为单位传输信息 - 含有许多非分配型子通道 - 子通道按时间片轮转方式共享通道 - 只要扫描每个子通道的速度足够快,而连接到子同上的设备的速率较小的时,不丢数据 - 主要连接以字节为单位的低速I/O设备,如:打印机、终端 ## 与设备无关的I/O软件 设备独立性又叫设备无关性,应用程序中所使用的设备,不局限于使用某个具体的物理设备 应用程序中使用逻辑设备名称来请求使用某类设备;系统将其转换为物理设备名称。 - 好处 - 设备分配时的灵活性 - 易于实现I/O重定向 - 设备独立性的实现 - 系统有专门从逻辑设备到物理设备的转换机制,类似于存储器管理中所介绍的逻辑地址和物理地址的概念 - 功能 - 执行所有设备的公有操作。 - 设备驱动程序的统一接口, 对设备进行保护,禁止用户直接访问设备 - 缓冲管理 - 差错控制 - 对独立设备的分配与回收 - 独立于设备的逻辑数据块 - 将逻辑设备名映射为物理设备名,找到相应物理设备的驱动程序 ### 设备分配 一个通道可控制多个设备控制器每个设备控制器可控制多个设备。 - 设备分配中的数据结构 - 设备控制表DCT - 每个物理设备有一张,反映设备特性、设备和I/O控制器的连接情况,在设备和系统连接时创建,动态修改 - ![](../../../../assets/default.png) - 设备分配时考虑的因素 - 设备的固有属性 - 独享设备 - 共享设备 - 虚拟设备 - 设备分配算法 - 先来先服务 - 优先级高者优先 - 设备分配中的安全性 - 安全分配方式 - 不安全分配方式 - 独占设备的分配程序 - 分配设备 - 分配控制器 - 分配通道 - 增加设备的独立性 - 使用逻辑设备名 - 逻辑设备表(LUT) - 逻辑设备表(LUT)建立了逻辑设备名与物理设备名之间的映射关系。 - 某用户进程第一次使用设备时使用逻辑设备名向操作系统发出请求 操作系统根据用户进程指定的设备类型(逻辑设备名)查找系统设备表,找到一个空闲设备分配给进程,并在LUT中增加相应表项。 - 如果之后用户进程再次通过相同的逻辑设备名请求使用设备,则操作系统通过LUT表即可知道用户进程实际要使用的是哪个物理设备了,并且也能知道该设备的驱动程序入口地址 ## 用户层I/O软件 - 系统调用 - 系统调用,应用程序可以通过它间接调用OS中的I/0过程,对I/O设备进行操作。 - 库函数 ### 假脱机系统(spooling) - 假脱机技术 - 在多道程序技术下,专门利用一道程序来模拟脱机输入操作,把低速I/O设备上的数据传送到高速磁盘上 - 再用另一道程序来模拟脱机输出操作,把数据从磁盘传送到输出设备上。 - 此时I/O设备与CPU并行工作。 - 组成 - 输入井和输出井。是磁盘上开辟的两个大存储空间。 - 输入缓冲区和输出缓冲区。在内存中开辟两个缓冲区,输入缓冲区暂存由输入设送来的数据,后送输入井 - 输出缓冲区暂存从输出井送来的数据,后送输出设备。 - 输入进程和输出进程。利用两个进程模拟脱机I/O时的外围处理机。 - 假脱机打印机 - 打印机是经常用到的输出设备,属于独占设备。、 - 利用假脱机技术可将它改造为一台可供多个用户共享的打印设备 - 假脱机打印系统主要有以下3三部分 - 磁盘缓冲区。 - 打印缓冲区。 - 假脱机管理进程和假脱机打印进程 - 特点 - 提高了I/O的速度 - 将独占设备改造为共享设备 - 实现了虚拟设备功能 ## 缓冲区管理 - 缓冲的引入 - 缓和CPU与I/O设备间速度不匹配的矛盾。 - 减少对CPU的中断频率,放宽对CPU中断响应时间的限制。 - 解决数据粒度不匹配的问题 - 提高CPU和1/O设备之间的并行性。 - 单缓冲区(Single Buffer) - 进程发出一个I/O请求时,操作系统便在主存中为之分配一缓冲区。 - ![](../../../../assets/default.png) - 双缓冲区 - 在设备输入时,先将数据送入第一缓冲区,装满后便转向第二缓冲区。此时OS可 以从第二缓冲区中移出数据,并送入用户进程。接着由CPU对数据进行计算。 - 为了实现两台机器间的双向数据传输,必须在两台机器中都设置两个缓冲区,一个用作发送缓冲区,另外一个用作接收缓冲区。 - 环形缓冲区 - CPU和外设的处理速度可能相差较大。 - 在主存中分配一组大小相等的缓冲区, 并用指针将这些缓冲区-个循环链表。 - 多个缓冲区:空缓冲区R;满缓冲区G;工作缓冲区C。 - 多个指针:下一个可用缓冲区G的指针Nextg;下一个输入缓冲区R的指针Nexti;当前计算进程正在使用的缓冲区C的指针Current。 ## 磁盘 - 结构 - 磁盘设备可包括一个或多个物理盘片,每个磁盘片分一个或两个存储面(Surface) - 每个盘面上有若干个磁道(Track),磁道之间留有必要的间隙(Gap)。为使处理简单起见,在每条磁道上可存储相同数目的二进制位。 - 磁盘密度即每英寸所存储的位数 - 每条此道从逻辑上划分位若干扇区 - 磁盘格式化 - 磁盘低级格式化(温切斯特盘) - 将空白的磁盘划分出柱面和磁道,再将磁道划分为若干个扇区, - 每个扇区又划分出标识部分ID,间隔区GAP和数据区DATA等。 - 磁盘分区 - 每个分区是一个独立的逻辑磁盘分区情况记录在磁盘的主引导扇区中的分区表(MBR)中 - 高级格式化 - 设置引导块,空闲和已分配空间表,构件文件系统,在磁盘上初始化文件系统数据结构,根目录等 - 类型 - 硬盘、软盘 - 单片盘、多片盘 - 固定磁头盘、移动磁头盘 - 磁盘访问时间 - 寻道时间T<sub>s</sub> :在读/写数据前,将磁头移动到指定磁道所花的时间。 - 启动磁头臂是需要时间的。假设耗时为s ; - 移动磁头也是需要时间的。假设磁头匀速移动,每跨越一个磁道耗时为m ,总共需要跨越n条磁道。则: - $$ T_s=s+m*n $$ - 延迟时间Tt : - 通过旋转磁盘,使磁头定位到目标扇区所需要的时间。设磁盘转速为r (单位:转/秒,或转/分),则平均所需的延迟时间 - $$ T_t=\frac{1}{2}*\frac{1}{r}=\frac{1}{2r} $$ - 传输时间Tt - 从磁盘读出或向磁盘写入数据所经历的时间,假设磁盘转速为r,此次读/写的字节数为b,每个磁道上的字节数为N - $$ T_t=\frac{b}{rN} $$ - 总的平均存取时间 - $$ T_a=T_s+\frac{1}{2r}+\frac{b}{rN} $$ ### 磁盘调度算法 - 先来先服务 - 根据进程请求访问磁盘的先后顺序进行调度。 - 优点 - 公平,简单。 - I/O负载较轻且每次读写多个连续扇区时,性能较好。 - 适用于l/O进程较少的场合。 - 最短寻道优先算法 - SSTF算法会优先处理的磁道是与当前磁头最近的磁道。 - 可以保证每次的寻道时间最短,但是并不能保证总的寻道时间最短。(贪心算法) - 可能会有进程处于“饥饿”状态。 - 扫描算法 - 只有磁头移动到最外侧磁道的时候才能往内移动,移动到最内侧磁道的时候才能往外移动。这就是扫描算法(SCAN)的思想。由于磁头移动的方式很像电梯,因此也叫电梯算法。 - 性能较好,平均寻道时间较短 - 防止“饥饿”现象。 - 被广泛应用。 - SCAN算法对于各个位置磁道的响应频率不平均 - 循环扫描算法 - 磁头单向移动,磁头朝某个特定方向移动时才处理磁道访问请求,而返回时直接快速移动至起始端而不处理任何请求。 - 比起SCAN来,对于各个位置磁道的响应频率很平均。 - 比起SCAN算法来,平均寻道时间更长。 - NStepSCAN算法 - 在高密度磁盘.上容易出现“磁臂粘着”情况。 - 将磁盘请求队列分成若干个长度为N的子队列。 - 队列之间使用FCFS算法。 - 队列内部使用SCAN算法。 - 新的I/O请求,放入其他队列,避免粘着现象。 - 当N值很大时,性能接近于SCAN算法。 - 当N=1时,蜕化为FCFS算法。 - FSCAN算法 - 是N步SCAN算法的简化。 - 磁盘请求队列分成两个子队列。 - 一个是由当前所有请求磁盘I/O的进程形成的队列,按SCAN算法进行处理。 - 新出现的所有请求磁盘I/O的进程,放入另- -个等待处理的请求队列。

操作系统复习 第七章

# 第七章 文件管理 ## 文件和文件系统 现代OS中是通过文件系统来组织和管理计算机中存储的数据 文件则是指具有文件名的若干相关元素的集合 基于文件系统的概念,**可以把数据组成分为数据项、记录和文件三级** - 文件名 - 文件名 - 扩展名 - 文件类型 - 按用途分类:系统文件、用户文件和库文件 - 按文件中数据的形式分类:源文件、目标文件和可执行文件 - 按存取控制属性分类:只执行文件、只读文件和读写文件 - 组织形式和处理方式分类:普通文件、目录文件、和特殊文件 - 文件系统模型 - 对象及其属性。文件管理系统的对象有:文件、目录和磁盘存储空间。 - 对对象操纵和管理的软件集合。是文件管理的核心部分。实现了文件系统的大部分功能——对文件存储空间的管理、对文件目录的管理、将文件的地址转换机制、对文件读写管理以及对文件的共享和保护。 - 文件系统的接口。命令接口(用户与文件系统)和程序接口(用户程序和文件系统)。 - 文件操作 - 用户通过文件系统所提供的系统调用实施对文件的操作。最基本的文件操作有:创建文件、删除文件、读文件、写文件和设置文件的读/写位置。 - 但对于一个实际的OS,为了方便用户使用文件而提供了更多地对文件的操作,如打开和关闭一一个文件及改变文件名等操作。 ## 文件的逻辑结构 - 类型 - 按文件是否有结构分类 - 有结构文件:是指由-一个以上的记录构成的文件,又把它称为记录式文件; - 无结构文件,这是指由字符流构成的文件,故又称为是流式文件。 - 根据文件的组织方式,可把有结构文件分为三类: - 顺序文件。由一系列记录按某种顺序排列所形成的文件。通常是定长记录 - 逻辑记录的排序 - 串结构:各记录之间的顺序与关键字无关。通常由时间来决定(从头开 始逐个查找) - 顺序结构:文件中的所有记录按关键字排列。可以按关键字的长短或英文字母书写排序。顺序结构的检索效率更高(可利用折半查找、插值查找法等) - 优点: - 顺序文件的最佳应用场合是在对文件中的记录进行批量存取时(即每次要读或写一大批记录)。 - 对于顺序存储设备(如磁带),也只有顺序文件才能被存储并能有效地工作。 - 缺点: - 查找和增删记录比较困难 - 顺序寻址 - 隐性寻址 - 确定下一个记录的逻辑地址 - 显性寻址 - 可对定长记录实现直接或随机访问 - 通过文件中记录的位置 - 定长记录文件,可实现随机存储 - 变长记录文件,无法实现随机存储 - 通过关键字 - 索引文件。当记录可变长时,通常为之建立一张索引表,并为每个记录设置一个表项以加快对记录检索的速度。 - 按关键字建立索引 - 索引表本身是定长记录的顺序文件。因此可以快速找到第i个记录对应的索引项。 - 可将关键字作为索引号内容若按关键字顺序排列,则还可以支持按照关键字折半查找。 - 每当要增加/删除一个记录时,需要对索引表进行修改。 - 具有多个索引表的索引文件 - 可以用不同的数据项建立多个索引表 - 索引顺序文件。上述两种方式的结合。为文件建立一张索引表,为每一组记录中的第一个记录设置一个表项。 - 将变长记录顺序文件中的所有记录分为若干个组,如50个记录为一个组。然后为顺序文件建立一张索引表,并为每组中的第一个记录在索引表中建立一个索引项,其中含有该记录的关键字和指向该记录的指针。 - 若一个顺序文件有10000个记录,则根据关键字检索文件,只能从头开始顺序 查找(这里指的并不是定长记录),平均须查找5000(N/2)个记录。 - 若采用索引顺序文件结构,可把10000个记录分为100组,每组100个记录。则需要先顺序查找索引表找到分组(共1 00个分组,因此索引表长度为100,平均需要查50次),找到分组后,再在分组中顺序查找记录(每个分组100个记录,因此平均需要查50次)。可见,采用索引顺序文件结构后,平均查找次数减少为50+50= 100次(根号N) - 二级索引顺序文件 - 为了进一步提高检索效率,可以为顺序文件建立多级索引表。例如,对于一个含10<sup>6</sup>个记录的文件,可先为该文件建立- -张低级索引表,每 100个记录为一组,故低级索引表中共有10000个表项(即10000个定长记录),再把这10000个定长记录分组,每组100个,为其建立顶级索引表,故顶级索引表中共有100个表项。 - 直接文件 - 可根据给定的关键字直接获得指定记录的物理地址。换而言之, - 关键字本身就决定了记录的物理地址。 - 哈希(Hash)文件 - 这是目前应用最为广泛的一种直接文件。 - 它利用Hash函数(或称散列函数)可将关键字转换为相应记录的地址。 ## 文件目录 通常在现代计算机系统中,都要存储大量的文件。为了能对这些文件实施有 效的管理,必须对它们加以妥善组织 - 实现"按名存取” - 提高对目录的检索速度 - 文件共享 - 允许文件重名 - 文件控制块 - 为了能对一个文件进行正确的存取,必须为文件设置用于描述和控制文件的数据结构,称之为"文件控制块(FCB) - FCB通常含有三类信息: - 基本信息类。包括:文件名,文件物理位置,文件逻辑结构,文件的物理结构 - 存取控制信息类。包括:文件主的存取权限,核准用户的存取权限和一般用户的存取权限 - 使用信息类。包括:文件的建立日期和时间、文件上次修改的日期和时间及当前使用信息。 - 文件目录 - 把所有的FCB组织在一-起,就构成了文件目录,即文件控制块的有序集合 - 目录文件 - 为了实现对文件目录的管理,通常将文件目录以文件的形式保存在外存,这个文件就叫目录文件 - 索引节点 - 文件目录通常是存放在磁盘上的,当文件很多时,文件目录要占用大量的盘块。在检索目录文件的时候,需要将目录调入内存后比较文件名,但是只用到文件名,而不需要其它那些对文件的描述信息。所以便把文件名与文件信息分开,使文件描述信息单独形成-个索引结点。 - 磁盘索引结点 - 存放在磁盘上的索引结点。每个文件有唯一-的一 个磁盘索引结点,主要包括以下内容: - 文件主标识符 - 文件类型 - 文件存取权限 - 文件物理地址 - 文件长度 - 文件链接计数 - 文件存取时间 - 内存索引结点、 - 放在内存中的索引结点。当文件被打开后,将磁盘索引结点拷贝到内存索引 结点中以便使用。 - 比磁盘索引结点增加了以下内容: - 索引结点编号 - 状态 - 访问计数; - 文件所属文件系统的逻辑设备号 - 链接指针。 - 读取文件的流程 - 根据文件名找到其所在目录中的目录项,获取该目录的对应文件的inode - 根据文件inode号,找到inode在磁盘的位置 - 根据inode中的对应关系,找到对应文件的盘块block; - 读取文件 - 文件目录 - 目录结构的组织,关系到文件系统的存取速度,也关系到文件的共享性和安全性。因此,组织好文件的目录是设计好文件系统的重要环节。 - 单级目录 - 最简单的目录结构。整个文件系统中只建立一张目录表, 每个文件一个目 录项,目录项含有文件相关信息。状态位表明每个目录项是否空闲。 - 优点 - 简单且能实现目录管理的基本功能 - 实现了"按名存取" - 缺点 - 查找速度慢 - 不允许重名。多用户环境下重名难以避免 - 不便于实现文件共享 - 两级目录 - 为了克服单级目录所存在的缺点,可以为每个用户建立一个单独的用户文件目录UFD。由该用户所有文件的文件控制块组成。 - 在系统中再建立一个主文件目录MFD。在主文件目录中每个用户目录文件都占有一个目录项,其中包括用户名和指向该用户文件的指针。 - 基本克服了单级目录的缺点,并具有以下优点: - 提高了检索目录的速度。 - 在不同的目录中可以有相同的文件名。 - 不同用户还可以使用不同的文件名来访问系统中的同一个共享文件。 - 用户不能对自己的文件进行分类 - 多级目录 - 现代操作系统通常采用三级或三级以上的目录结构,以提高目录的检索速度和文件系统的性能。多级目录结构又称为树型目录结构,主目录称为根目录,数据文件为树叶,其它目录为结点。 - 路径名 - 用户(或用户进程)要访问某个文件时要用文件路径名标识文件,文件路径名是个字符串。各级目录之间用"/"隔开。从根目录出发的路径称为绝对路径 - 当前目录 - 很多时候,用户会连续访问同一目录内的多个文件。显然,每次都从根目录开始查找是很低效的因此可以设置一个"当前目录"。 当用户想要访问某个文件时,可以使用从当前目录出发的相对路径 - 目录操作 - 创建目录 - 删除目录 - 不删除非空目录 - 可删除非空目录 - 改变目录 - 移动目录 - 链接(Link)操作 - 查找 - 目录查询技术 - 当用户要访问一个已存文件时,系统首先利用用户提供的文件名对目录进行查询,找出该文件控制块或对应索引结点; - 然后根据FCB或索引结点中所记录的文件物理地址,换算出文件在磁盘上的物理位置; - 最后通过磁盘驱动程序,将所需文件读入内存 - 线性检索法 - Hash方法 - 建立了一张Hash索引文件目录,利用Hash方法进行查询,即系统利用用户提供的文件名并将它变换为文件目录的索引值,再利用该索引值到目录中去查找,显著地提高检索速度。 - 文件打开过程 - 用户访问某文件时,调用open(),系统的工作过程: - 查找目录,找到指定的文件目录; - 核对访问权限; - 将文件目录项复制到“打开文件表(open-file table) "中 - “打开文件表”是open()系统调用关联的主要数据结构,用于记录系统中所有已打开的文件的信息。当用户再次需要访问文件时,不需要重复查找目录,而是通过返回的文件指针,直接找到“打开文件表”对应表项,进而得到文件在外存的地址。这样大大的减少了检索目录所带来的开销,提高了系统工作效率。 - 返回用户该文件在“打开文件表”中的指针fd。 - 文件关闭过程 - 当一个文件暂不使用时,就应撤消该文件在“已打开表”中的相应表目,以释放所占内存空间,这就是文件的关闭。及时关闭不用的文件,一方面节约了内存的开支, 另一方面把FCB的内容及时写回外存, 以免被意外情况破坏。 - 当用户调用close系统调用时,系统的工作过程: - 核对用户的使用权限,一般只有文件的建立者和打开者才有权关闭文件; - 根据fd查找“用户打开文件表”,释放该文件占用的表目; - 检查读入内存的文件目录和文件索引节点是否已被修改,若已被修改,则需将该文件的文件目录项和文件索引节点重新写回外存,以保存做过的修改。 ## 文件共享 操作系统为用户提供文件共享功能,可以让多个用户共享地使用同一个文件 注意:多个用户共享同一个文件,意味着系统中只有"一份"文件数据。并且只要某个用户修改了该文件的数据,其他用户也可以看到文件数据的变化。 如果是多个用户都"复制"了同一个文件,那么系统中会有"好几份"文件数据。 其中一个用户修改了自己的那份文件数据,对其他用户的文件数据并没有影响。 - 基于有向无环图的文件共享 - 有多个属于不同用户的多个目录,同时指向同-个文件,这样虽会破坏树的特性,但这些用户可用对称的方式实现文件共享,而不必再通过其属主目录来访问。 - 在文件目录中只设置文件名及指向相应索引结点的指针 - 索引结点中设置一个链接计数变量count ,用于表示链接到本索引结点上的用户目录项数。 - 利用符号链接实现文件共享 - 利用符号链接实现文件共享的基本思想,是允许一个文件或子目录有多个父目录,但其中仅有一个作为主(属主)父目录,其它的几个父目录都是通过符号链接方式与之相链接的(简称链接父目录)。 - 为使链接父目录D5能共享文件F8,可以由系统创建一个LINK类型的新文件, 也取名为F8,并将F8写入链接父目录D5中,以实现D5与文件F8的链接。在新文件F中只包含被链接文件F8的路径名。这样的链接方法被称为符号链接。新文件F中的路径名则只被看做是符号链。 - 优点 - 在利用符号链方式实现文件共享时,只是文件主才拥有指向其索引结点的 指针;而共享该文件的其他用户则只有该文件的路径名,不会出现指针悬 空的情况。 - 问题 - 当其他用户去读共享文件时,系统是根据给定的文件路径名逐个分量(名)地去查找目录,直至找到该文件的索引结点。因此,在每次访问共享文件时,都可能要多次地读盘。这使每次访问文件的开销甚大,且增加了启动磁盘的频率。 - 要为每个共享用户建立一条符号链,而由于链本身实际上是一个文件,尽管该文件非常简单,却仍要为它配置一个索引结点,这也要耗费一定的磁盘空间。 - ## 文件保护 - 访问权 - 我们把一个进程能对某对象执行操作的权力,称为访问权(Access right)。 - 保护域 - "域”是进程对一组对象访问权的集合,进程只能在指定域内执行操作 - “域”规定了进程所能访问的对象和能执行的操作 - 进程和域间的静态联系 - 在进程和域之间可以一对应,即一个进程只联系着一个域。这意味着,在进程的整个生命期中,其可用资源是固定的,我们把这种域称为'静态域” - 进程和域间的动态联系方式 - 在进程和域之间,也可以是一对多的关系,即一个进程可以联系着多个域 - 可将进程的运行分为若干个阶段,其每个阶段联系着一个域,这样便可根据运行的实际需要来规定在进程运行的每个阶段中所能访问的对象。 - 基本的访问矩阵 - 访问矩阵中的行代表域,列代表对象,矩阵中的每一项是由一组访问权组成的。 - 访问控制表(Access Control List) - 对访问矩阵按列(对象)划分,为每一列建立一张访问控制表ACL - 在该表中,已把矩阵中属于该列的所有空项删除,此时的访问控制表是由一有序对(域,权集)所组成的。 - 使用访问控制表可以显著地减少所占用的存储空间,并能提高查找速度。 - 在每个文件的FCB (或索引结点)中增加一个访问控制列表(Access-Control List, ACL)该表中记录了各个用户可以对该文件执行哪些操作。 - 精简的访问列表:以“组”为单位,标记各“组”用户可以对文件执行哪些操作。 - 如果把访问矩阵按行(即域)划分,便可由每一行构成一张访问权限表。换言之,这是由一个域对每一个对象可以执行的一组操作所构成的表。

软件工程复习 第十章

# 第十章 软件实现 ## 编程语言 在软件设计阶段,得到了实现目标系统的解决方案,并用模型图、伪代码等设计语言表述出来。编码的过程就是把软件设计阶段得到的解决方案转化为可以在计算机上运行的软件产品的过程。 选择合适的编程语言是编码过程的关键。可以说,编程语言是人与计算机交互的基本工具,它定义了计算机的一组语法规则,通过这些语法规则可以把人的意图、思想等转化为计算机可以理解的指令,进而让计算机帮助人类完成某些任务。软件开发人员使用编程语言来实现目标系统的功能。 ### 编程语言的发展与分类 - 机器语言 - 汇编语言 - 高级语言 - 超高级语言 ### 选择编程语言需要考虑的因素 - 待开发系统的应用领域,即项目的应用范围 - 用户的要求 - 将使用何种工具进行软件开发 - 软件开发人员的喜好和能力 - 软件的可移植性要求 - 算法和数据结构的复杂性 - 平台支持 ## 编程风格 编程风格是指源程序的书写习惯,比如变量的命名规则、代码的注释方法、缩进等。具有良好编程风格的源程序具有较强的可读性、可维护性,还能提高团队开发的效率。 良好的个人编程风格是优秀程序员素质的一部分,项目内部相对统一的编程风格也使得该项目的版本管理、代码评审等软件工程相关工作更容易实现。在大型软件开发项目中,为了控制软件开发的质量,保证软件开发的一致性,遵循一定的编程风格尤为重要。 ### 如何做到良好的编程风格 - 版权和版本声明应该在每个代码文件的开头声明代码的版权和版本,主要内容如下: - 版权信息 - 文件名称、标识符、摘要 - 当前版本号、作者/修改者、完成日期 - 版本历史信息。 - 在程序编写过程中应该注意代码的版式,使代码更加清晰易读。对空行、空格的使用及对代码缩进的控制与程序的视觉效果密切相关。编程人员基本积累了一些程序版式规则 - 在每个类声明之后、每个函数定义结束之后都要加空行 - 在一个函数体内,逻辑上密切相关的语句之间不加空行,其他地方应加空行分隔 - 一行代码只做一件事情,如只定义一个变量,或只写一条语句 - if、for、while、do等语句独占一行,执行语句不得紧跟其后,不论执行语句有多少都要加{} - 尽可能在定义变量的同时初始化该变量 - 关键字之后要留空格,函数名之后不要留空格,“,”之后要留空格 - 赋值操作符、比较操作符、算术操作符、逻辑操作符、位域操作符等二元操作符的前后应当加空格,一元操作符前后不加空格 - 程序的分界符“{”和“}”应独占一行并且位于同一列,同时与引用它们的语句左对齐 - 代码行最大长度宜控制在70~80个字符 - 长表达式要在低优先级操作符处拆分成新行,操作符放在新行之首 - 注释注释阐述了程序的细节,是软件开发人员之间以及开发人员和用户之间交流的重要途径。做好注释工作有利于日后的软件维护。注释也需要遵循一定的规则,比如注释需要提供哪些方面的信息、注释的格式、注释的位置等。 - 注释的分类 - 序言注释位于模块的起始部分,说明模块的详细信息,如模块的用途、模块的参数描述、模块的返回值描述、模块内捕获的异常类型、实现该模块的软件开发人员及实现时间、对该模块做过修改的开发人员及修改日期等 - 行内注释位于模块内部,用于解释较难理解、逻辑性强或比较重要的代码,提高代码的可理解性。 - 注释的作用: - ①版本、版权声明 - ②函数接口说明 - ③重要的代码行或段落提示。 - 使用注释的基本规则 - 注释是对代码的“提示”,而不是文档,注释的花样要尽量少 - 注释应当准确、易懂,防止注释有二义性 - 注释的位置应与被描述的代码相邻,可以放在代码的上方或右方,不可放在下方 - 当代码比较长,特别是有多重嵌套时,应当在一些段落的结束处加注释,以便于阅读。 - 命名规则 - 按照标识符的实际意义命名,使其名称具有直观性,能够体现标识符的语义。这样可以帮助开发人员理解和记忆标识符 - 标识符的长度应当符合“最小长度与最大信息量”原则 - 命名规则尽量与采用的操作系统或开发工具的风格一致,如缩写的使用、字母大小写的选择、对常量和变量命名的区分等 - 变量名不要过于相似,这样容易引起误解 - 在定义变量时,最好注释其含义和用途 - 程序中不要出现仅靠大小写区分的相似的标识符 - 尽量避免名称中出现数字编号,除非逻辑上的确需要编号 - 数据说明 - 在数据说明时应该遵循一定的次序 - 当在同一语句中说明相同数据类型的多个变量时,变量一般按照字母顺序排列 - 对于复杂数据结构的说明,为了容易理解,需要添加必要的注释 - 语句构造 - 不要为了节省空间而把多条语句写在一行 - 合理利用缩进来体现语句的不同层次结构 - 在含有多个条件语句的算术表达式或逻辑表达式中使用括号来清晰地表达运算顺序 - 将经常使用并且具有一定独立功能的代码封装为一个函数或公共过程 - 避免使用goto语句 - 避免使用多层嵌套语句 - 避免使用复杂的判定条件。 ## 面向对象实现 面向对象实现主要是指把面向对象设计的结果翻译成用某种程序语言书写的面向对象程序。 采用面向对象方法开发软件的基本目的和主要优点是通过重用提高软件的生产率。因此,应该优先选用能够最完善、最准确地表达问题域语义的面向对象语言。

软件工程复习 第一章

# 第一章 软件与软件工程 ## 软件 软件包括程序、程序的处理对象——数据,以及与程序开发、维护和使用有关的图文资料(文档) - 特点 - (1)软件是一种逻辑实体,而不是具体的物理实体,因而它具有抽象性。 - (2)软件没有明显的制造过程 - (3)在软件的运行和使用期间,不会出现硬件中出现的机械磨损、老化问题,然而它存在退化问题 - (4)计算机的开发与运行对计算机系统有着不同程度的依赖性。 - (5)软件开发至今尚未完全摆脱人工的开发方式。 - (6)软件本身是复杂的。 - (7)软件成本相当昂贵。 - (8)相当多的软件工作涉及社会因素。 - 分类 - ![](../../../../assets/default.png) ## 软件危机 软件危机是指计算机软件在开发和维护过程中遇到的一系列严重问题 - 表现 - (1)开发出来的软件产品不能满足用户的需求 - (2)相比越来越廉价的硬件,软件代价过高。 - (3)软件质量难以得到保证,且难以发挥硬件潜能。 - (4)难以准确估计软件开发、维护的费用以及开发周期 - (5)难以控制开发风险,开发速度赶不上市场变化。 - (6)软件产品修改维护困难,集成遗留系统更困难。 - (7)软件文档不完备,并且存在文档内容与软件产品不符的情况。 - 出现的原因 - (1)忽视软件开发前期的需求分析。 - (2)开发过程缺乏统一的、规范化的方法论的指导。 - (3)文档资料不齐全或不准确。 - (4)忽视与用户之间、开发组成员之间的交流。 - (5)忽视测试的重要性。 - (6)不重视维护或由于上述原因造成维护工作困难。 - (7)从事软件开发的专业人员对这个产业认识不充分,缺乏经验 - (8)没有完善的质量保证体系 - 启示:使我们更加深刻地认识到软件的特性以及软件产品开发的内在规律。 - (1)软件产品是复杂的人造系统,具有复杂性、不可见性和易变性,难以处理。 - (2)个人或小组在开发小型软件时使用到的非常有效的编程技术和过程,在开发大型、复杂系统时难以发挥同样的作用。 - (3)从本质上讲,软件开发的创造性成分很大,发挥的余地也很大,很接近于艺术。它介于艺术与工程之间,并逐步向工程一段漂移,但很难发展到完全的工程。 - (4)计算机和软件技术的快速发展,提高了用户对软件的期望,促进了软件产品的演化,为软件产品提出了新的、更多的需求,难以在可接受的开发进度内保证软件的质量。 - (5)几乎所有的软件项目都是新的,而且是不断变化的。项目需求在开发过程中会发生变化,而且很多原来预想不到的问题会出现,适当调整设计和实现手段是不可避免的。 - (6)“人月神化”现象——生产力与人数并不成正比。 ## 软件工程 1968年,在北大西洋公约组织举行的一次学术会议上,将其定义为“为了经济地获得可靠的和能在实际机器上高效运行的软件,而建立和使用的健全的工程规则”。 IEEE(Institute of Electrical and Electronics Engineers,电气和电子工程师协会)对软件工程的定义为: (1)将系统化、严格约束的、可量化的方法应用于软件的开发、运行和维护,即将工程化应用于软件。 (2)对(1)中所述方法的研究。 过程、方法和工具是软件工程的3个要素 - 软件工程研究的内容 - (1)软件开发技术。主要研究软件开发方法、软件开发过程、软件开发工具和环境。 - (2)软件开发过程管理。主要研究软件工程经济学和软件管理学。 - 目标和原则 - (1)达到要求的软件功能。 - (2)取得较好的软件性能。 - (3)开发出高质量的软件。 - (4)付出较低的开发成本。 - (5)需要较低的维护费用。 - (6)能按时完成开发工作,及时交付使用。 - 7条基本原则 - 用分阶段的生命周期计划严格管理 - 坚持进行阶段评审 - 实行严格的产品控制 - 采用现代程序设计技术 - 软件工程结果应能清楚地审查 - 开发小组的人员应该少而精 - 承认不断改进软件工程实践的必要性 - 15个知识领域 - 软件需求 - 软件设计 - 软件构建 - 软件测试 - 软件维护 - 软件配置管理 - 软件工程管理 - 软件工程过程 - 软件工程模型和方法 - 软件质量 - 软件工程职业实践 - 软件工程经济学 - 计算基础 - 数学基础 - 工程基础 ## 软件开发方法 - 结构化方法 - 面向数据结构方法 - 面向对象方法 - 形式化方法 ## 软件工程工具 - (1)按照功能划分:功能是对软件进行分类最常用的标准,按照功能划分,软件工程工具可分为可视化建模工具、程序开发工具、自动化测试工具、文档编辑工具、配置管理工具、项目管理工具等。 - (2)按照支持的过程划分:软件工程工具可分为设计工具、编程工具、维护工具等 - (3)按照支持的范围划分:软件工程工具可以分为窄支持、较宽支持和一般支持工具。窄支持工具支持软件工程过程中的特定任务,一般将称之为工具;较宽支持工具支持特定的过程阶段,一般由多个工具集合而成,称之为工作台;一般支持工具支持覆盖软件过程的全部或大部分阶段,包含多个不同的工作台,称之为环境。

操作系统复习 重点提纲

# 操作系统关键部分摘要 ## 引论 ### 操作系统的作用 - 作为用户与计算机硬件系统之间的接口 - 作为计算机系统资源的管理者 - 实现了对计算机资源的抽象 ### 操作系统的种类 - 单道批处理系统: - 批处理是指计算机系统对一批作业自动进行处理的一种技术。 - 为实现对作业的连续处理,需要先把一批作业以脱机方式输入到磁带上,并在系统中配上监督程序(Monitor) ,在它的控制下,使这批作业能一个接一地连续处理 - 多道批处理系统 - 在多道批处理系统中,用户所提交的作业都先存放在外存上并排成一个队列,称为“后备队列”; 然后,由作业调度程序按一定的算法从后备队列中选择若干个作业调入内存,使它们共享CPU和系统中的各种资源。 - 分时系统 - 采用时间片轮转的方法,同时为许多终端用户服务,对每个用户能保证足够快的响应时间,并提供交互会话的功能。 - 时间片:将CPU的时间划分成若干个片段,称为时间片,操作系统以时间片为单位,轮流为每个终端用户服务关键问题 - 微机操作系统 - 微型计算机操作系统 微型计算机操作系统简称微机操作系统,常用的有Windows、Mac OS、Linux。 ### 现代操作系统的特性 <mark>并发性</mark>、<mark>共享性</mark>、虚拟性、异步性 ### 操作系统程序接口 由一组系统调用组成,每一个系统调用都是一个能完成特定功能的子程序,每当应用程序要求OS提供某种服务时,便调用具有相应功能的系统调用。 ### 操作系统内核态与用户态 <mark>内核态(管态)和用户态(目态)将内核程序和用户程序隔离</mark> - <font color=red>特权指令</font> - 涉及外部设备的输入/输出指令 - 存取用于内存保护的寄存器 - 内存清零 - 置时钟 - 允许/禁用中断 <mark>中断指令</mark>是用户程序发起的调用内核代码的唯一方式 - 中断机制 - 提高多道程序环境下CPU利用率 - 外中断:中断信号来源于外部设备 - 内中断:中断信号来源于当前指令内 - 内中断的三种情况 - 陷阱/陷入:由应用程序主动引发 - 故障:由错误条件引发 - 终止:由致命错误引发 - 系统调用的核心 - 用户程序中包含一段含有int指令的代码 - 操作系统写中断处理,获取想调用程序的编号 - int指令将使CPL改成0 ,“进入内核” - 操作系统根据编号执行相应代码 ## 进程控制 ### 进程的概念 程序段、数据段、**PCB**三部分构成了进程实体,简称"进程”。 ### 进程的三种状态 - 就绪状态(Ready) - 进程已获得除CPU之外的所有必需的资源,一旦得到CPU控制权,立即可以运行 - 运行状态(Running) - 进程已获得运行所必需的资源,它正在处理机上执行。 - 阻塞状态(Blocked) - 正在执行的进程由于发生某事件而暂时无法执行时,便放弃处理机而处于暂停状态,称该进程处于阻塞状态或等待状态。 ### PCB的定义 PCB是内存中的一种数据结构,PCB的作用是使一个在多道程序环境下不能独立运行的程序(含数据) ,成为一个能独立运行的基本单位, 一个能与其他进程并发执行的进程 <mark>PCB是进程存在的唯一标志</mark> ### PCB的内容 | 类型 | 内容 | 作用 | |--------------|-----------------------------------------------------------|------------------| | 标识信息 | 1 )外部标识为方便用户<br/>2 )内部标识为方便系统 | 标识一个进程 | | 处理机状态(现场信息 ) | 1 ) CPU通用/指令寄存器<br/>2 ) CPU程序状态字PSW<br/>3 )用户栈指针 | 记录处理机现场信息,以备恢复之用 | | 调度信息 | 1 )进程状态<br/>2 )进程优先级<br/>3 )调度所需信息<br/>4)事件 | 用户进程的调度管理 | | 控制信息 | 1 )程序和数据地址<br/>2 )进程同步和通信机制<br/>3 )资源清单<br/>4 )指向下一个进程的指针 | 用于进程的控制管理 | ### 进程的创建 - 引起创建进程的事件 - 用户登录 - 作业调度 - 提供服务 - 应用请求 - 创建过程 - 申请进程标识,即申请空白PCB - 为新进程分配内存和其它资源 - 初始化进程控制块 - 将创建的进程置于就绪队列 ### 进程控制的原语 - 进程创建原语 - 进程撤销原语 - 阻塞原语 - 唤醒原语 - 挂起原语 - 激活原语 ### 临界区的定义 临界区:进程中访问临界资源的那段代码 ### <font color=red>信号量</font> - 定义:把整型信号量定义为一个用于表示资源数目的整型量S ,除初始化外仅能通过两个原子操作wait(S),signal(S)(低级原语)来访问 - 原子操作P : - 分配一个单位资源 - wait(S) - 原子操作V : - 释放一个单位资源 当信号量sign 大于0时,表示该资源该有sign个。当sign小于0时,表示有sign个进程正在等待 ### 管程 管程是由若干个公共变量和所有访问这些变量的过程所组成的一个特殊的模块或软件包 ### 其他进程同步机制(有各种各样的问题) - 关中断法(开关中断指令)也称为"硬件锁”,在进入锁测试之前关闭中断,直到完成锁测试并上锁之后才能打开中断。 - 利用Test and Set指令实现互斥:这是一种借助一条硬件指令一“测试并建立”指令TS(Test- and-Set)以实 现互斥的方法。在许多计算机中都提供了这种指令。 - 利用swap指令实现线程互斥 ### 管道的定义 - 管道:指用于连接一个读进程和一个写进程以实现他们之间通信的一个打开的共享文件,又名pipe文件。 - 管道只能采取半双工通信,某一时间段内只能实现单向的传输。如果要实现双向同时通信,则需要设置两个管道各个进程要互斥的访问管道 - 数据以字节流的形式写入管道,当管道写满时,写进程的write()系统调用将会被阻塞,等待读进程将数据取走。当读进程将数据全部取走后,管道变空,此时读进程的read()系统调用将会被阻塞 ### 线程 线程(thread)是一个可执行的实体单元。<mark>它代替以往的进程,成为现代操作系统中处理机调度的基本单位。 **调度的基本单位** - 同一进程中的线程切换不会引起进程切换 - 不同进程中的线程切换必然引起进程切换 **用户级线程** - 用户级线程仅存在于用户空间中。对于这种线程的创建、撤消、线程之间的同步与通信等功能,都无须利用系统调用来实现。 - 对于用户级线程的切换,通常是发生在一个应用进程的诸多线程之间,无须内核的支持。 - 切换的规则远比进程调度和切换的规则简单 **内核支持线程KST** - 在内核的支持下运行的,即无论是用户进程中的线程,还是系统进程中的线程,他,们的创建、撤消和切换等,也是依靠内核实现的。 - **在内核空间还为每一个内核支持线程设置了一个线程控制块** ,内核是根据该控制块而感知某线程的存在的,并对其加以控制。 线程控制块TCB - 线程标识符; - 组寄存器,它包括程序计数器PC、状态寄存器和通用寄存器; - 线程运行状态,用于描述线程正处于何种运行状态; - 优先级,描述线程执行的优先程度; - 线程专有存储区,用于线程切换时存放现场保护信息,和相关统计信息; - 信号屏蔽,即对某些信号加以屏蔽。 - 堆栈,用来保存局部变量和返回地址。 - 用户栈和核心栈 ## 调度机制与死锁 ### 作业调度——先来先服务算法(First Come First Serve) 基本原则是按照作业到达系统的先后次序来选择,或者说它是优先考虑在系统中等待时间最长的作业,而不管该作业所需执行时间的长短。 ### 作业调度——<font color=red>短作业优先(Short Job First)调度算法</font> SJF算法是以作业的长短来计算优先级,作业越短,其优先级越高。 ### 作业调度——高响应比优先调度算法 - 为每个作业引入一个动态优先级,即优先级是可以改变的,令它随等待时间延长而增加,这将使长作业的优先级在等待期间不断地增加,等到足够的时间后,必然有机会获得处理机。该优先级的变化规律可描述为: $$ R_p=\frac{等待时间+要求服务时间}{要求服务时间}=\frac{响应时间}{要求服务时间} $$ ### 响应比 (等待时间+执行时间)/执行时间 ### [进程调度算法](https://charlesix59.github.io/2023/02/07/subject/operate_system/chapter3/#%E8%B0%83%E5%BA%A6%E7%AE%97%E6%B3%95) 考得不大具体,了解即可 ### 死锁的概念 死锁( Deadlock ) 是指多个进程在运行过程中因争夺资源而造成的一种僵局 **死锁原因** - 竞争不可抢占性资源 - 竞争可消耗资源 - 进程推进顺序不当 **产生死锁的必要条件** - 互斥条件 - 请求和保持条件 - 不可抢占条件 - 循环等待条件 #### [死锁的预防、避免、检查与解除](https://charlesix59.github.io/2023/02/07/subject/operate_system/chapter3/#%E9%A2%84%E9%98%B2%E6%AD%BB%E9%94%81) 这一块内容很多还挺重要的,慢慢看吧 ## 存储器管理 ### 目的 存储器管理的目的:提高内存利用率、方便用户 ### 程序的装入 **重定位**: 在装入时对目标程序中指令和数据的修改过程称为重定位。 **绝对装入方式**: 在编译时,如果知道程序驻留在内存的什么位置,那么编译程序将产生绝对地址的目标代码。 **可重定位装入方式(Relocation Loading Mode)**: 在多道程序环境下,可重定位装入方式,根据内存的当前情况,将装入模块装入到内存的适当位置。 **动态重定位**: - 在把装入模块装入内存后,并不立即把装入模块中的相对地址转换为绝对地址,而是把这种地址转换推迟到程序真正要执行时(访问内存之前)才进行。 ### 连续分配存储方式 - 单一连续分配:系统区加用户区,连续的分配 - 固定分区分配:将内存用户空间划分为若干个固定大小的区域,在每个分区中只装入一道作业,便可以有多道作业并发执行。 - 动态分区分配:动态分区法在作业执行前并不建立分区,分区的建立是在作业的处理过程中进行的,且其大小可随作业或进程对内存的要求而改变。<mark>分区分配算法有</mark>: - 首次适应算法:要求按地址递增的次序组织空闲区表(链)。 - 循环首次适应算法(Next Fit):每次分配不再从空闲分区链(表)的开始找起,而是从上次找到的空闲分区的下一个找起,找到一个能满足要求的空闲区。 - <font color=red>最佳适应算法(Best Fit)</font>:把能满足要求的最小空闲分区分配给作业,避免“大材小用” - 最坏适应算法(Worst Fit):总是挑选最大的空闲分区分割给作业使用 - 快速适应算法:将空闲分区按大小分类,每类具有相同容量,放入一个空闲分区链表 - 伙伴系统:无论已分配分区或空闲分区,分区大小必须是2的k次幂,k为整数, I≤k≤m - 哈希算法:哈希算法就是利用哈希快速查找优点,以及空闲分区在可利用空间表中的分布规律,建立哈希函数,构造一张以空闲分区大小为关键字的哈希表,该表的每一个表项记录了一个对应的空闲分区链表表头指针。 ### 分页存储 **页面** - 把进程的逻辑地址空间划分成若干大小相等的区域,每个区域称作**页面**或**页**。每个页都有一个编号,叫做页号。页号一般从0开始编号,如0 , 1, 2, ...等。 - 把内存空间划分成若干和页大小相同的物理块,这些物理块叫**页框**(frame)或(物理)块。同样,每个物理块也有一个编号,块号从0开始依次顺序排列。 - 以**页**为单位进行内存分配,并按进程的页数多少来分配。逻辑上相邻的页,物理上不一定相邻。 ## 虚拟存储器 虚拟存储器:是指具有请求调入功能和置换功能,能从逻辑.上对内存容量加以扩充的一种存储器系统。 <mark>虚拟内存的实际容量 = min(内存与外存之和, CPU寻址范围)</mark> <mark>虚拟存储器的实现都是建立在离散分配的存储管理方式的基础上。</mark> ### 请求分页系统 在分页系统的基础上,增加了请求调页功能和页面置换功能所形成的页式虚拟存储系统。置换时以页面为单位。 硬件支持: - 请求分页的页表机制 - 缺页中断机构 - 地址变换机构 ### 物理块分配策略 在请求分页系统中,可采取两种内存分配策略: - 固定分配策略:为每个进程分配一定数目的物理块,在整个运行期间不再改变 - 可变分配策略:先为每个进程分配一定数量的物理块,在整个运行期间可适当增多或减少。 在进行置换时,也可采取两种策略 - 全局置换:可以将操作系统保留的空闲物理快分配给进程,也可以将别的进程持有的物理块置换到外存,再分配给缺页进程。 - 局部置换:发生缺页时,只选进程自己的物理块置换 组合出的三种策略:(不能采用固定分配全局置换) - 固定分配局部置换(Fixed Allocation , Local Replacement) - 为每个进程分配一定数目的物理块,在整个运行期间不再改变。 - 采用该策略时,如果进程在运行中发现缺页,只能从该进程在内存中的n个页面中选出一页换出,然后再调入一页。 - 困难:应为每个进程分配多少个物理块难以确定。 - 可变分配全局置换(Variable Allocation , Global Replacement) - 在采用这种策略时,先为系统中的每个进程分配一定数目的物理块,而OS自身也保持一个空闲的物理块队列。 - 如果某进程发生缺页时,由系统从空闲的物理块队列中,取出一个物理块分配给该进程,并将欲调入的页装入其中。 - 当空闲物理块队列中的物理块用完后, OS才能从系统中的任一进程中选择一页调出。 - 可变分配局部置换(Variable Allocation , Local Replacement) - 为每个进程分配一定数目的物理块,如果某进程发生缺页时,只允许从该进程在内存的页面中选出一页换出,不会影响其他进程执行。 - 如果进程在运行中频繁发生缺页中断,则系统再为进程分配若干物理块 - 如果进程在运行中缺页率特别低,则适当减少分配给该进程的物理块 **交换(swap)分区**: Swap分区在系统的物理内存不够用的时候,把硬盘内存中的一部分空间释放出来,以供当前运行的程序使用。那些被释放的空间可能来自一些很长时间没有什么操作的程序,这些被释放的空间被临时保存到Swap分区中,等到那些程序要运行时,再从Swap分区中恢复保存的数据到内存中。 ### 页面置换算法 - 最佳置换算法 - 算法无法实现,但可评价其他算法。 - 先入先出页面(FIFO)置换算法 - 算法总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面予以淘汰。 - **Belady现象** - 采用FIFO算法时,如果对一个进程未分配它所要求的全部页面,有时就会出现分配的页面数增多但缺页率反而提高的异常现象。 - <font color=red>最近最久未使用(LeastRecently Used)算法</font> - 算法根据页面调入内存后的使用情况进行决策。由于无法预测各页面将来的使用情况,只能利用“最近的过去”作为“最近的将来”的近似,因此,LRU置换算法是选择最近最久未使用的页面予以淘汰。 - 该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间t ,当需淘汰一个页面时,选择现有页面中其t值最大的,即最近最久未使用的页面予以淘汰。 - 需有以下两类硬件之一的支持: - 寄存器 - 栈 - 最少使用置换(Least Frequently Used)算法 - 在采用LFU算法时,应为在内存中的每个页面设置一个移位寄存器,用来记录该页面被访问的频率。该置换算法选择在最近时期使用最少的页面作为淘汰页。 - 简单的Clock置换算法 - 当采用简单Clock算法时,只需为每页设置一位访问位,再将内存中的所有页面都通过链接指针链接成一个循环队列。 - 当某页被访问时,其访问位被置1。 - 置换算法在选择一页淘汰时,只需检查页的访问位。如果是0 ,就选择该页换出;若为1 ,则重新将它置0 ,暂不换出,而给该页第二次驻留内存的机会 - 再按照FIFO算法检查下一个页面。 - 当检查到队列中的最后一个页面时,若其访问位仍为1 ,则再返回到队首去检查第一个页面。 - 因此简单的CLOCK算法选择一个淘汰页面最多会经过两轮扫描 - <font color=red>改进型CLock算法</font> - 在将一个页面换出时,如果该页已被修改过,便须将该页重新写回到磁盘上;但如果该页未被修改过,则不必将它拷回磁盘。 - 在改进型Clock算法中,除须考虑页面的使用情况外,还须再增加一个因素,即置换代价,这样,选择页面换出时,既要是未使用过的页面,又要是未被修改过的页面。 - 把同时满足这两个条件的页面作为首选淘汰的页面。 - 由访问位A和修改位M可以组合成下面四种类型的页面: - 1类(A=0 , M=0) :表示该页最近既未被访问,又未被修改,是最佳淘汰页。 - 2类(A=0 , M=1) :表示该页最近未被访问,但已被修改,并不是很好的淘汰页。 - 3类(A=1 , M=0) :表示该页最近已被访问,但未被修改,该页有可能再被访问。 - 4类(A=1 , M=1) :表示该页最近已被访问且被修改,该页可能再被访问。 - (1)从指针所指示的当前位置开始,扫描循环队列,寻找A=0且M=0的第一类页面,将所遇到的第一个页面作为所选中的淘汰页。在第一次扫描期间不改变访问位A。 - (2)如果第一步失败,则开始第二轮扫描,寻找A=0且M= 1的第二类页面,将所遇到的第一个这类页面作为淘汰页。在第二轮扫描期间,将所有扫描过的页面的访问位都置0。 - (3)如果第二步也失败,则将指针返回到开始的位置,然后回到第一步重新开始,一定能找到被淘汰的页。 - 该算法与简单Clock算法比较,可减少磁盘的I/O操作次数。但为了找到一个可置换的页,可能须经过几轮扫描。换言之,实现该算法的开销有所增加。 ### 预防抖动 <mark>刚被淘汰的页面又马上被调回内存,调回内存不久后又被淘汰出去,如此频繁进行,这种现象称为抖动(或称颠簸)</mark> **所谓工作集,是指在某段时间间隔△里,进程实际所要访问页面的集合。** <font color=red>预防抖动的策略</font> - 采取局部置换策略 - 把工作集算法融入到处理机调度中 - 利用"L=S"准则调节缺页率 - 选择暂停的进程 - 当多道程序度偏高时,已影响到处理机的利用率,为了防止发生“抖动”,系统必须减少多道程序的数目,以便腾出内存空间分配给那些缺页率偏高的进程。 ## 输入输出设备 ### I/O 系统 (四个层级从低到高) - 中断处理程序 - 当I/O任务完成时,I/O控制器会发送一个中断信号,系统会根据中断信号类型找到相应的中断处理程序并执行。 - 设备驱动程序 - 驱动程序一般会以一个独立进程的方式存在。 - 主要负责对硬件设备的具体控制,将上层发出的一系列命令(如read/write) 转化成特定设备“能听得懂”的一系列操作。包括设置设备寄存器;检查设备状态等 - 设备独立性软件 - 他的主要功能有: - 向上层提供统一的调用接口,如read/write系统调用 - 设备的分配与回收 - 差错处理 - 数据缓冲区管理 - 建立逻辑设备名到物理设备名的映射关系:根据设备类型选择调用相应的驱动程序 - 用户层软件 - 实现了与用户交互的接口,用户可直接使用该层提供的、与I/O操作相关的库函数对设备进行操作。 ### 设备驱动设备的控制方式 控制方式 - 宗旨:尽量减少主机对I/O控制的干预,把主机从繁杂的IO控制事务中解脱出来 - 忙——等待方式 - CPU向控制器发出I/O指令,启动输入设备。 - 状态寄存器忙/闲标志busy置1。 - 循环测试busy, busy= 1输入未完成。 - busy=0输入完成,将数据从控制器的数据寄存器读到内存 - 由于CPU高速,I/O设备低速致使CPU极大浪费。 - 使用中断的可编程I/O方式 - CPU向控制器发出I/O指令,CPU返回继续原来的工作。 - 设备控制器控制I/O设备。CPU与I/O并行工作。 - 数据输入寄存器,控制器向CPU发出中断。 - CPU检查数据正确性,数据写入内存。 - <font color=red>直接存储器访问(Direct Memory Access)</font> - 特点 - 数据传输的基本单位是数据块。 - 数据从设备直接送入内存,或者相反。 - 仅在传送一个或多个数据块的开始和结束时,才需CPU干预,整块数据的传送是在控制器的控制下完成的。 - DMA控制器 - 三部分 - 主机与DMA控制器的接口 - DMA控制器与块设备的接口 - I/O控制逻辑 - 四类寄存器 - 数据寄存器DR - 命令/状态寄存器CR - 内存地址寄存器MAR - 数据计数器DC - DMA工作过程 - CPU发出指令,存入CR - 内存起始目标地址送入MAR。 - 读取字节数送DC。 - 源地址送DMA的I/O控制逻辑。 - 启动DMA控制器,CPU处理其他任务。 - DMA控制读入一个字(节)到DR。 - 将该字(节)送入MAR指向的内存单元。 - MAR加1,DC减1。 - DC<> 0继续传输,DC=0发出中断。 - 中断方式是在数据缓冲寄存区满后,发中断请求,CPU进行中断处理。 - DMA方式则是在所要求传送的数据块全部传送结束时要求CPU进行中断处理,大大减少了CPU进行中断处理的次数。 - 中断方式的数据传送是由CPU控制完成的,而DMA方式则是在DMA控制器的控制下不经过CPU控制完成的。 - I/O通道控制方式 - 目的:CPU的I/O任务由通道来承担。 - 一种特殊的处理机,属于硬件技术。它具有执行I/O指令的能力,并通过执行通道程序来控制I/O操作。 - 指令类型单一、 即由于通道硬件比较简单,其所能执行的指令,主要为与I/O有关的指令 - 通道没有自己的内存,与CPU共享内存 - CPU一次读(或写)多个数据块。 - 多个数据块送入不同内存区域。 - CPU、通道和I/O设备三者的并行操作。 - 工作过程: - CPU向通道发送一条I/O指令。 - 给出通道程序首址和要访问的I/O设备。 - 通过执行通道程序完成I/O任务。 - 通道程序由一系列通道指令(通道命令)构成。 - 每条通道指令包含的信息: - 操作码 - 内存地址 - 计数 - 通道程序结束位P (P= 1表示程序结束) - 记录结束标志R (R=0表示与下一条指令处理的数据属于同一记录;R= 1表示某记录的最后一条指令) - 字节多路通道(Byte Multiplexor Channel) - 字节多路通道以字节为单位传输信息 - 含有许多非分配型子通道 - 子通道按时间片轮转方式共享通道 - 只要扫描每个子通道的速度足够快,而连接到子同上的设备的速率较小的时,不丢数据 - 主要连接以字节为单位的低速I/O设备,如:打印机、终端 ### 设备独立性 <font color=red>用户编程时使用的硬件名称与实际使用的设备名称不同</font> ### 假脱机系统(spooling) 在多道程序技术下,专门利用一道程序来模拟脱机输入操作,<font color=red>把低速I/O设备上的数据传送到高速磁盘上</font>, 再用另一道程序来模拟脱机输出操作,把数据从磁盘传送到输出设备上。 - 此时I/O设备与CPU并行工作。 ### 缓冲区管理 单缓冲区(Single Buffer) - 进程发出一个I/O请求时,操作系统便在主存中为之分配一缓冲区。 双缓冲区 - 在设备输入时,先将数据送入第一缓冲区,装满后便转向第二缓冲区。此时OS可以从第二缓冲区中移出数据,并送入用户进程。接着由CPU对数据进行计算。 - 为了实现两台机器间的双向数据传输,必须在两台机器中都设置两个缓冲区,一个用作发送缓冲区,另外一个用作接收缓冲区。 ## 文件管理 文件逻辑结构是为了方便用户而设计的 ### 文件的逻辑结构 顺序文件:由一系列记录按某种顺序排列所形成的文件。通常是定长记录 索引文件:当记录可变长时,通常为之建立一张索引表,并为每个记录设置一个表项以加快对记录检索的速度。 索引顺序文件:上述两种方式的结合。为文件建立一张索引表,为每一组记录中的第一个记录设置一个表项。 二级索引顺序文件:为了进一步提高检索效率,可以为顺序文件建立多级索引表。 ### 文件控制块 - 为了能对一个文件进行正确的存取,必须为文件设置用于描述和控制文件的数据结构,称之为"文件控制块(FCB) - FCB通常含有三类信息: - 基本信息类。包括:文件名,文件物理位置,文件逻辑结构,文件的物理结构 - 存取控制信息类。包括:文件主的存取权限,核准用户的存取权限和一般用户的存取权限 - 使用信息类。包括:文件的建立日期和时间、文件上次修改的日期和时间及当前使用信息。 ### 文件目录 文件目录通常是存放在磁盘上的,当文件很多时,文件目录要占用大量的盘块。在检索目录文件的时候,需要将目录调入内存后比较文件名,但是只用到文件名,而不需要其它那些对文件的描述信息。所以便把文件名与文件信息分开,使文件描述信息单独形成一个索引结点。 ### 软连接与硬链接 硬链接 - 软链接相当于Windows的快捷方式 - 软链接里面存放的是源文件的路径,指向源文件 - 删除源文件,软链接文件依然存在,但是无法通过软链接访问源文件,已经失效,并且白字红底闪烁 - 软链接和源文件是不通的文件,iNode号不同,文件类型也不同 - 所有连接文件的权限都是777,而实际权限是由链接指向的源文件权限决定的 软连接 - 具有相同iNode节点号的多个文件,互为硬链接文件 - 删除硬链接文件或者源文件任意之一,文件实体并未被删除,只有删除了所有硬链接文件和源文件,文件实体才被删除 - 硬链接文件只是文件的另一个入口 - 链接文件和源文件属性相同 - 不能跨分区,不能对目录使用 ## 硬盘存储器管理 ### 外存组织方式(文件的物理结构) - 顺序组织方式 - 每个文件在磁盘上占有一组连续的块 - 链接组织方式 - 可通过在每个盘块上的链接指针,将同属于一个文件的多个离散的盘块链接成一个链表 - 显式链接:把用于链接文件各物理块的指针显式地存放在一张表中。 即文件分配表(FATFile Allocation Table) - 索引组织方式 - 索引分配允许文件离散地分配在各个磁盘块中,系统会为每个文件建立一张索引表 - 索引表中记录了文件的各个逻辑块对应的物理块(索引表的功能类似于内存管理中的页表)。 - 索引表存放的磁盘块称为索引块。文件数据存放的磁盘块称为数据块。 ### 文件存储空间管理 存储空间的管理实际上是对外存未占用空间的管理 - 连续分配方式 - 空闲表法:为每个文件分配一块连续的存储空间。系统为外存上的所有空闲区建立一张空闲表, 每个空闲区对应于一个空闲表项,再将所有空闲区按其起始盘块号递增的次序排列 - 离散分配方式 - 空闲盘块链:磁盘上的所有空闲空间以盘块为单位拉成一条链,其中的每一个盘块都有指向后继盘块的指针。 - 空闲盘区链:将磁盘上的所有空闲盘区拉成一条链。 在每个盘区上除含有用于指示下一个空闲盘区的指针外,还应有能指明本盘区大小(盘块数)的信息。 - <font color=red>位示图法(连续离散都适用)</font> - 利用二进制的一位来表示磁盘中一个盘块的使用情况。当其值为0时表示对 应的盘块空闲,为1时表示已分配(Linux)。 有的系统则相反。 - 磁盘上的所有盘块都有一个二进制位与之对应,这样由所有盘块所对应的位构成一个集合,称为位示图。 - 通常可用`m*n`个位数来构成位示图,并使`m*n`等磁盘的总块数。

软件工程复习 第十一章

# 第十一章 软件测试 **软件测试**是发现软件中错误和缺陷的主要手段。为了保证软件产品的质量,软件开发人员通过软件测试发现产品中存在的问题,并及时修改 **软件缺陷**是指软件产品中存在的问题,具体表现为用户所需的功能没有实现,无法满足用户的需求。 在软件开发过程的任何阶段都可能引入缺陷。缺陷被引入的阶段越早,在软件开发后期修复这些缺陷造成的成本损失就越大。 **软件测试工作应该贯穿于整个开发过程。** - 原则 - 完全测试是不可能的 - 测试中存在风险 - 软件测试只能表明缺陷存在,而不能证明软件产品已经没有缺陷 - 软件产品中潜在的错误数与已发现的错误数成正比 - 让不同的测试人员参与到测试工作中 - 让开发小组和测试小组分立,开发工作和测试工作不能由同一部分人来完成 - 尽早并不断地进行测试,使测试工作贯穿于整个软件开发的过程中 - 在设计测试用例时,应包括输入数据和预期的输出结果两个部分,并且输入数据不仅包括合法的情况,还应该包括非法的输入情况 - 要集中测试容易出错或错误较多的模块 - 应该长期保留所有的测试用例 - 软件测试模型 - 要素 - 测试的时间 - 测试的步骤 - 如何计划测试 - 不同阶段的测试中应该关注哪些测试对象 - 测试过程中应该考虑哪些问题 - 测试需要达到的目标等。 - 模型 - V - W - H - 按照质量因素划分的软件测试 - 功能测试。,检验最终的软件产品是否实现了需求规格说明书中的所有功能需求 - 可靠性测试。关注于程序输出结果的准确性 - 可用性测试。用来衡量处理服务请求时,应用程序的可用频率 - 性能测试 - 安全性测试 - 配置测试。考察软件系统是否能在多种硬件平台上正常运行 - 兼容性测试.主要关注软件的运行平台和应用系统的版本、标准和规范、数据的共享性 - 安装测试 - 文档测试 - 软件国际化测试和本地化测试 - α测试和β测试。它们都属于验收测试的范畴,是在系统测试之后,产品发布之前进行的测试过程的最后一个阶段。 ## 测试用例 为达到最佳的测试效果或高效地揭露隐藏的错误而精心设计并执行的少量测试数据,称为测试用例。 我们不可能进行穷举测试,为了节省时间和资源,提高测试效率,必须从数量极大的可用测试数据中精心挑选出具有代表性或特殊性的测试数据来进行测试。 测试用例=测试数据+预期测试结果( +测试环境) 测试结果=测试数据+期望结果+实际结果 <mark>一个好的测试用例是在于它能发现至今未发现的错误。</mark> ## 软件测试方法 ### 静态审查 - 自查 - 会审 - 走查 ### 动态审查 #### 黑盒测试 - 定义 - 在黑盒测试中,测试人员把被测试的软件系统看成是一个黑盒子,不需要关心盒子的内部结构和内部特性,只关注软件产品的输入数据和输出结果,从而检查软件产品是否符合它的功能说明。 - 等价类划分法 - 把被测对象的输入域划分为有限个等价区段——“等价类”,以有针对性的等价类少量测试,代替漫无边际的、数量较大的“穷尽”测试或随机测试。 - 分类 - 有效等价类是指对程序的规格说明是有意义的、由合理的输入数据构成的集合 - 无效等价类是指对程序的规格说明是无意义的、由不合理的输入数据构成的集合 - 原则 - 如果输入条件规定了取值范围或个数,则可确定一个有效等价类和两个无效等价类 - 如果输入条件规定了输入值的集合或是规定了“必须如何”的条件,则可确定一个有效等价类和一个无效等价类 - 如果输入条件是布尔表达式,则可以分为一个有效等价类和一个无效等价类 - 如果输入条件是一组值,且程序对不同的值有不同的处理方式,则每个允许的输入值对应一个有效等价类,所有不允许的输入值的集合为一个无效等价类 - 如果规定了输入数据必须遵循的规则,则可以划分出一个有效的等价类(符合规则)和若干无效的等价类(从不同的角度违反规则) - 如已划分的等价类各元素在程序中的处理方式不同,则应将此等价类进一步划分成更小的等价类 - 边界值分析法 - 定义 - 经验表明,处理边界情况时程序最容易发生错误 - 边界类型:下标、数据结构、循环、选择等的边界附近 - 通常选用等价类边界值作为边界值测试的数据 - 一般边界值分析法作为等价类划分法的补充与细化。 - 原则 - 以输入条件的边界的值作为测试用例 - 若规定了值的数量的边界作为测试用例 - 针对每个输出条件 - 输入或输出范围是有序的集合,应注意选取有序集的第一个和最后一个元素作为测试用例 - 分析规格说明,找出其他的可能边界条件 - 错误推测法 - 错误推测法在很大程度上靠直觉和经验进行。它的基本想法是列举出程序中可能有的错误和容易发生错误的特殊情况,并且根据它们选择测试方案。 - 因果图法 - 定义 - 等价类划分法和边界值分析法都主要考虑输入条件,而没有考虑输入条件的各种组合以及各个输入条件之间的相互制约关系。因此,必须考虑描述多种条件的组合,相应地产生多个动作的形式来考虑设计测试用例。这就需要利用因果图法。 - 因果图法是一种黑盒测试方法,它从用自然语言书写的程序规格说明书中寻找因果关系,即利用输入条件与输出和程序状态的改变,由因果图产生判定表。它能够帮助人们按照一定的步骤高效地选择测试用例,还能指出程序规格说明书中存在的问题。 - 使用 - 用C表示原因,E表示结果 - 各节点表示状态 - 取值0表示某状态不出现,取值1表示某状态出现 - 四种关系符号 - ![](../../../../assets/default.png) - 表示约束的符号 - ![](../../../../assets/default.png) - E约束(互斥):表示a和b两个原因不会同时成立,最多有一个可以成立 - I约束(包含):表示a和b两个原因至少有一个必须成立 - O约束(唯一):表示a和b两个条件必须有且仅有一个成立 - R约束(要求):表示a出现时,b也必须出现。 - M约束(强制)表示a是1时,b必须为0。 - 步骤 - 分析程序规格说明书的描述中,哪些是原因,哪些是结果 - 分析程序规格说明书中描述的语义内容,并将其表示成连接各个原因与各个结果的因果图 - 有些原因和结果的组合情况是不可能出现的,为表明这些特定的情况,在因果图上使用若干特殊的符号标明约束条件 - 把因果图转化为决策表 - 为决策表中每一列表示的情况设计测试用例 - 决策表法 - 定义 - 在一些数据处理问题中,某些操作是否实施依赖于多个逻辑条件的取值。在由这些逻辑条件取值的组合构成的多种情况下,分别执行不同的操作。处理这类问题的一个非常有力的工具就是决策表 - 决策表(也称判定表)是分析和表达多逻辑条件下执行不同操作的情况的工具,可以比较明确地表达复杂的逻辑关系和多种条件组合的情况 - 组成 - 条件桩:列出问题的所有条件 - 条件项:列出所列条件下的取值,以及在所有可能情况下的真假值 - 动作桩:列出问题规定可能采取的动作 - 动作项:列出在条件项的各种取值情况下应采取的动作 - 在简化并得到最终决策表后,只要选择适当的输入,满足决策表每一列的输入条件,即可生成测试用例。 - 场景法 - 定义 - 现在很多软件都是用事件触发来控制流程,事件触发时的情形变形成场景,而同一事件不同的触发顺序和处理结果就形成了事件流。这种在软件设计中的思想也可以应用到软件测试中,可生动地描绘出事件触发时的情形,有利于测试者执行测试用例,也更容易理解和执行测试用例。 - 组成 - 基本流:采用黑直线表示,是经过用例的最简单路径,表示无任何差错,程序从开始执行到结束 - 采用不同颜色表示,一个备选流可以从基本流开始,在某个特定条件下执行,然后重新加入基本流中,也可以起源于另一个备选流,或终止用例,不再加入基本流中。 - 步骤 - 根据规格说明,描述出程序的基本流和各个备选流 - 根据基本流和各个备选流生成不同的场景 - 对每一个场景生成相应的测试用例 - 复审生成的所有测试用例,去掉多余的测试用例,确定每一个测试用例的测试数据。 - 选择 - 在任何情况下都必须选择边界值分析方法。经验表明用这种方法设计出的测试用例发现程序错误的能力最强 - 必要时用等价类划分法补充-些测试用例 - 用错误推测法再追加一些测试用例 - 如果程序的功能说明中含有输入条件的组合情况,则可选用因果图法和决策表法 #### 白盒测试 白盒测试有时也被称为玻璃盒测试,它关注软件产品的内部细节和逻辑结构,即把被测的程序看成是一个透明的盒子。 白盒测试利用构建层设计的一部分而描述控制结果来生成测试用例。白盒测试需要清楚了解系统内部结构和工作原理。 - 逻辑覆盖法 - 逻辑覆盖法以程序内在的逻辑结构为基础,根据程序的流程图设计测试用例 - 测试步骤 - 选择逻辑覆盖标准 - 按照覆盖标准列出所有情况 - 选择确定测试用例 - 验证分析运行结果与预期结果 - 语句覆盖:指选择足够的测试用例,使被测语句的每个语句至少执行一次 - 判定覆盖:指选择足够的测试用例,使每个判定的所有可能结果至少出现一次。 - 条件覆盖:指选择足够的测试用例,使判定中的每个条件的所有可能结果至少出现一次 - 判定/条件覆盖:指选择足够的测试用例,使判定中的每个条件的所有可能结果至少出现一次,并且每个判定中条件结果的所有可能组合也至少出现一次。 - 条件组合覆盖:指选择足够的测试用例,使每个判定中条件结果的所有可能组合至少出现一次。 - 路径覆盖:指选择足够的测试用例,使流程图中的每条路径至少经过一次。 - 基本路径法 - 基本路径法是在程序控制流图的基础上,通过分析控制构造的环路复杂性,导出基本可执行的路径集合,从而设计测试用例的方法。**使用基本路径法设计出的测试用例要保证在测试中程序的每条可执行语句至少执行一次。** - 步骤 - 画出控制流图 - 计算环路复杂度 - 导出测试数据 - 准备测试用例 - 圈复杂度的计算 - 给定流图G的圈复杂度=流图中边的数量,-流图中结点的数量 - 给定流图G的圈复杂度=流图G中判定结点的数量+1 - 白盒方法的选择 - 白盒测试还有静态质量度量、域测试、Z路径覆盖等方法 - 选择方法的几条经验 - 在测试中,可采取先静态再动态的组合方式,先进行代码检查和静态结构分析,再进行覆盖测试 - 将静态分析的结果作为引导,通过代码检查和动态测试的方式进一步确认静态分析的结果 - 覆盖测试是白盒测试的重点,一般可使用基本路径法达到语句覆盖标准,对于软件的重点模块,应使用多种覆盖标准衡量测试的覆盖率 - 不同测试阶段的测试重点不同,在单元测试阶段,以代码检查、覆盖测试为主,在集成测试阶段,需要增加静态结构分析等,在系统测试阶段,应根据黑盒测试的结果,采用相应的白盒测试方法。 - 白盒与黑盒的比较 - | 白盒测试 | 黑盒测试 | | --- | --- | | 考察程序逻辑结构 | 不涉及程序结构 | | 用程序结构信息生成测试用例 | 用软件规格说明书生成测试用例 | | 主要适用于单元测试和集成测试 | 可适用于从单元测试到系统验收测试 | | 测试所有逻辑路径 | 某些代码段得不到测试 | #### 灰盒测试 灰盒测试是介于白盒测试和黑盒测试之间的测试方法,它关注输出对于输入的正确性,也关注内部表现,但是不像白盒测试那样详细、完整,只是通过一些表征性的现象、事件、标志来判断内部的运行状态。有时候输出是正确的,但是程序内部已经是错误的,这种情况非常多,如果每次都通过白盒测试来操作,效率会很低,因此可采取灰盒测试这种方法。 灰盒测试结合了白盒测试和黑盒测试的要素,考虑了用户端、特定的系统知识和操作环境。它在系统组件的协同性环境中评价应用软件的设计。可以认为,集成测试就是一类灰盒测试。 ## 测试的步骤 ### 单元测试 在进行单元测试时,被测试的单元本身不是独立的程序,需要为其开发驱动模块和桩模块。 **驱动模块**是用来模拟待测试模块的上级模块。驱动模块在集成测试中接受测试数据,将相关的数据传送给待测模块,启动待测模块,并打印出相应的结果 **桩模块**也称为存根程序,用以模拟待测模块工作过程中调用的模块。 桩模块由待测模块调用,它们一般只进行很少的数据处理,例如打印入口和返回,以便于检验**待测模块与下级模块**的接口。 ### 集成测试 - 组装测试也称集成测试,是在单元测试的基础上,将所有模块按照软件设计要求组装成执行子系统、功能子系统直至应用系统并进行测试的过程。 - 测试内容:主要是模块间的结构和通信,发现软件设计阶段产生的错误 - 测试方法:黑盒测试 - 注意问题 - 接口数据丢失:连接各模块时,穿越模块接口的数据是否会丢失 - 模块功能干扰:一个模块的功能是否对其他模块的功能产生不利影响。 - 组合成功:各个子功能组合起来,能否达到预期的父功能。 - 整体数据结构:全局数据结构是否有问题 - 误差积累:单个模块的误差是否会累积、放大 - 影响数据库:单个模块的错误是否会导致数据库错误 - ~~非增量组装测试方式~~ - 一次组装,然后测试 - 不使用 - 增量组装测试方式 - 增量式集成测试中单元的集成是逐步实现的,集成测试也是逐步完成的 - 一边测试一边组装 - 自顶向下增量式集成测试 - 这种组装方式是将模块按系统程序结构,沿控制层次自项向下进行组装。 - 这种方式在测试过程中较早地验证了主要的控制点和判断点。在一个功能划分合理的程序结构中,判断常出现在较高的层次,因而能较早地遇到。如果主要控制有问题,尽早发现能够大大减少以后的返工。 - 优点:能够尽早发现系统主控方面的问题,驱动真实,上层测试充分。 - 缺点:需要设计大量桩模块、进行大里回归测试,测试用例设计麻烦。 - 自底向上增量式集成测试 - 这种组装方式从程序结构的最底层模块开始组装和测试。 - 由于模块是由底向.上进行组装的,对于一个给定层次的模块,它的子模块(包括子模块的所有下属模块)已经组装并测试完成,以不再要桩模块。在模块的测试过程中需要从子模块得到的信息可以直接得到。 - 基本增殖步骤 - 编写驱动模块,把最底层的模块组合成子功能模块族。 - 用实际模块替换驱动模块,把子功能族组合起来形成更大的功能族。 - 为子系统编写驱动模块,进行新的测试过程。 - 重复步骤②、③,直到完成所有的模块组装测试。 - 优点:桩模块真实,驱动模块和测试用例容易编写;能够尽早查出底层涉及较复杂的算法和实际的I/0模块中的错误。 缺点:系统结构建立晚,系统协调、功能接口问题发现的晚。 - 深度优先与宽度优先 - 无论是自顶向下还是由底向上的方式,都可以选择深度优先或者宽度优先增量方式 - 混合方式(实际使用) ### 确认测试 - 确进一步验证软件的有效性,即验证软件的功能、性能及其他特性是否与用户的要求一致。 - 测试依据:需求规格说明书 - 测试人员:专门测试部门、专业用户、典型用户、专家 - 有效性测试:制定测试计划,运用黑盒法验证软件特性是否与需求符合。 - 软件配置复查:软件配置指软件工程过程中所产生的所有信息项一一文档、报告、程序、表格、数据。随着软件工程过程的进展,软件配置项(SCI software Configuration Item)快速增加和变化,应复查SCI是否齐全。 - 确认测试结果 - 在全部确认测试的测试用例运行完后,所有的测试结果可以分为两类: - 测试结果与预期的结果相符-一这说明软件的这部分功能或性能特征与需求说明书相符合,从而这部分程序可以接受。 - 测试结果与预期的结果不符一-这说明软件的这部分功能或性能特征与需求说明书不一致,因此需要开列一张软件各项缺陷表或软件问题报告,通过与用户的交流,解决所发现的缺陷和错误。 - 测试类型 - 功能测试:根据需求规格说明书和测试需求列表,验证产品的功能是否符合需求规格 - 性能测试:用来测试软件系统在实际的集成系统中的运行性能 - 安装测试:用来确保软件在正常情况和异常情况的不同条件下都不丢失数据或者功能,具体测试活动包括首次安装、升级、完整安装、自定义安装、卸载等 - 可用性测试:检验其是否达到可用性标准 - 压力测试:不是在常规条件下运行手动或自动测试,而是长时间或超大负荷地运行测试软件来测试被测系统的性能、可靠性、稳定性等 - 容量测试:目的是通过测试预先分析出反映软件系统应用特征的某项指标的极限值(如最大并发用户数、数据库记录数等),系统在该极限值下没有出现任何软件故障或还能保持主要功能正常运行 - 安全性测试:目的是验证系统的保护机制是否能够在实际的环境中抵御非法入侵、恶意攻击等非法行为 - 健壮性测试:指在故障存在的情况下,软件还能正常运行的能力 - 图形用户界面测试:包含两方面内容,一是界面实现与界面设计是否吻合,二是界面功能是否正确 - 文档测试:文档包括开发文档、管理文档和用户文档3种 ### 验收测试 验收测试是在系统测试之后进行的测试,目的是验证新建系统产品是否能够满足用户的需要,产品通过验收测试工作才能最终结束。具体说来,验收测试就是根据各自需求说明书的标准,利用工具进行的一项检查工作,其中包括对进程的验收、进程质量是否达到需求说明书的要求,以及是否符合工程的设计要求等,验收测试可分为前阶段验收和竣工验收两个阶段。 验收测试是依据软件开发商和用户之间的合同、软件需求说明书以及相关行业标准、国家标准、法律法规等的要求对软件的功能、性能、可靠性、易用性、可维护性、可移植性等特性进行严格的测试,验证软件的功能、性能及其他特性是否与用户需求一致。 α测试:是用户在开发环境下的测试,或者是开发公司组织内部人员模拟各类用户行为,对即将面市的软件产品进行的测试,它是由开发人员或测试人员进行的测试。在α测试中,主要是确认使用的功能和任务,测试的内容由用户需求说明书决定。α测试是试图发现软件产品的错误的测试,它的关键在于尽可能逼真地模拟实际运行环境和用户对软件产品的操作,并尽最大努力涵盖所有可能的用户操作方式。 β测试:β测试由最终用户实施,通常开发(或其他非最终用户)组织对其的管理很少或不管理。β测试是所有验收测试策略中最主观的:测试员负责创建自己的环境、选择数据,并决定要研究的功能、特性或任务,采用的方法完全由测试员决定。 ### 回归测试 回归测试是指软件系统被修改或扩充后重新进行的测试,回归测试是为了保证软件修改后,没有引入新的错误而重复进行的测试 ## 面向对象的软件测试 在基于面向对象思想的软件开发中,由于面向对象的软件工程方法与传统的软件工程方法有诸多不同,所以传统的软件测试模型对面向对象的软件系统已经不再适用。 在面向对象的软件开发中,人们已经抛弃了传统的测试模型。针对面向对象的开发模型中的面向对象分析(OOA)、面向对象设计(OOD)、面向对象实现(OOP)3个阶段 ### 面向对象分析的测试 结构化需求分析把目标系统看成是一个由若干功能模块组成的集合,而面向对象需求分析以现实世界中的概念为模型结构。前者关注系统的行为,即功能结构,后者更关注于系统的逻辑结构。对面向对象需求分析的测试,要考虑以下方面: - 对认定的对象或类的测试 - 对定义的属性和操作的测试 - 对类之间层次关系的测试 - 对对象之间交互行为的测试 - 对系统逻辑模型的测试等 ### 面向对象设计的测试 与传统的软件工程方法不同的是,面向对象分析和面向对象设计之间并没有严格的界限。实际上,面向对象设计是对面向对象分析结果的进一步细化、纠正和完善。对面向对象设计的测试涉及了面向对象分析的测试内容,但是会更加关注对类及其类之间关系的测试和对类库支持情况的测试。 ### 面向对象实现的测试 面向对象的程序具有封装、继承和多态的特性。测试多态的特性时要尤为注意,因为它使得同一段代码的行为复杂化,测试时需要考虑不同的执行情况和行为。由于系统功能的实现分布在类中,所以本阶段的测试中还要重点评判类是否实现了要求的功能。 ### 面向对象的单元测试 面向对象的单元测试以类或对象为单位。由于类包含一组不同的操作,并且某些特殊的操作可能被多个类共享,因此单元测试不能孤立地测试某个操作,而是将操作作为类的一部分。 ### 面向对象的集成测试 面向对象的集成测试采用基于线程或者基于使用的测试方法。基于线程的测试是指把回应系统外界输入的一组相关的类集成起来,对线程进行集成并测试。基于使用的测试方法按照类对服务器的依赖以及对其他类的依赖程度,把类划分为独立类和依赖类。 独立类是指那些几乎不使用服务器的类。在进行基于使用的测试时,先测试独立类。 依赖类是使用独立类的类,即它们对独立类存在某种程度的依赖。 在测试完独立类后,就可以测试依赖类了。依赖类可能还划分为多个层次,测试时按照逐层向下的顺序,直到测试完整个系统。 ### 面向对象的系统测试及验收测试 在系统测试的过程中,软件开发人员要尽量搭建与用户的实际使用环境相同的平台,检测和评估目标系统是否能作为一个整体,满足用户在性能、功能、安全性、可靠性等各个方面的要求。面向对象的系统测试要以面向对象需求分析的结果为依据,验证需求分析中描述的对象模型、交互模型等各种分析模型。 ## 软件调试 调试(也称为纠错)是在测试发现错误之后排除错误的过程。 虽然调试可以而且应该是一个有序的过程,但是在很大程度上它仍然是一项技巧。软件工程师在评估测试结果时,往往仅面对软件问题的症状,也就是说,错误的外部表现和它的内在原因之间可能并没有明显的联系。调试就是把症状和原因联系起来的尚未被人很好理解的智力过程。 - 强行排错 - 适合于结构比较简单的程序。是使用较多,效率较低的方法。 - 在程序中插入打印语句 - 将内存和寄存器的内容打印或显示出来,然后从中找出错误的原因 - 屏蔽部分程序 - 把不需要执行的语句段加上注释符号,使其不再运行 - 在不需要执行的语句段前加上判断值为假的if语句,使其不再运行 - 调试完成后再恢复 - 借助于调试工具 - 回溯排错 - 演绎排错

软件工程复习 第三章

# 第三章 可行性研究与软件开发计划 ## 项目立项 任何一个完整的软件工程项目都是从项目立项开始的。 - 项目立项包括项目发起、项目论证、项目审核和项目立项4个过程 - 在发起一个项目时,<mark>项目发起</mark>人或单位为寻求他人的支持,要以书面材料的形式递交给项目的支持者和领导,使其明白项目的必要性和可行性。 <mark>项目论证</mark>过程,也就是可行性研究过程。可行性研究就是指在项目进行开发之前,根据项目发起文件和实际情况,对该项目是否能在特定的资源、时间等制约条件下完成做出评估,并且确定它是否值得去开发。 项目经过可行性研究并且认为可行后,还需要报告主管领导或单位,以获得<mark>项目</mark>的进一步<mark>审核</mark>,并得到他们的支持。 项目通过可行性研究和主管部门的批准后,将其列入项目计划的过程,叫做<mark>项目立项</mark>。 ## 可行性研究的任务 可行性研究需要从多个方面进行评估,主要包括:战略可行性、操作可行性、计划可行性、技术可行性、社会可行性、市场可行性、经济可行性和风险可行性等。 - (1)战略可行性研究主要从整体的角度考虑项目是否可行,如提出的系统对组织目标具有怎样的贡献、新系统对目前的部门和组织结构有何影响、系统将以何种方式影响人力水平和现存雇员的技术、它对组织整个人员开发策略有何影响,等等。 - (2)操作可行性研究主要考虑系统是否能够真正解决问题;系统一旦安装后,是否有足够的人力资源来运行系统;用户对新系统具有抵触情绪是否可能使操作不可行;人员的可行性等问题。 - (3)计划可行性研究主要估计项目完成所需的时间并评估项目的时间是否足够。 - (4)技术可行性研究主要考虑项目使用技术的成熟程度;与竞争者的技术相比,所采用技术的优势及缺陷;技术转换成本;技术发展趋势及所采用技术的发展前景;技术选择的制约条件等。 - (5)社会可行性研究主要考虑项目是否满足所有项目涉及者的利益;是否满足法律或合同的要求等。 - (6)市场可行性研究主要包括研究市场发展历史与发展趋势,说明本产品处于市场的什么发展阶段;本产品和同类产品的价格分析;统计当前市场的总额、竞争对手所占的份额,分析本产品能占多少份额;分析产品消费群体的特征、消费方式以及影响市场的因素;分析竞争对手的市场状况;分析竞争对手在研发、销售、资金、品牌等方面的实力;分析自己的实力等。 - (7)经济可行性研究主要是研究系统开发和运行需要的成本与得到的效益,分析成本效益。 - (8)风险可行性研究主要是考虑项目在实施过程中可能遇到的各种风险因素,以及每种风险因素可能出现的概率和出现后的影响程度。 ## 技术可行性 技术可行性主要研究待开发系统的功能、性能和限制条件,确定现有技术能否实现有关的解决方案,在现有的资源条件下实现新系统的技术风险有多大。这里的资源条件是指已有的或可以得到的软硬件资源、现有开发项目人员的技术水平和已有的工作基础。 在评估技术可行性时,需要考虑以下情况:了解当前最先进的技术,分析相关技术的发展是否支持新系统;确定资源的有效性,如新系统的软硬件资源是否具备,开发项目的人员在技术和时间上是否可行等;分析项目开发的技术风险,即能在给定的资源和时间等条件下,设计并实现系统的功能和性能等。 <mark>技术可行性研究往往是系统开发过程中难度最大的工作,是可行性研究的关键。</mark> ## 操作可行性 - 操作可行性是对开发系统在一个给定的工作环境中能否运行或运行好坏程度的衡量。操作可行性研究决定在当前的政治意识形态、法律法规、社会道德、民族意识以及系统运行的组织机构或人员等环境下,系统的操作是否可行。 - 操作可行性往往最容易被忽视或被低估,或者认为它一定是可行的。 ## 经济可行性 成本-效益分析是可行性研究的重要内容,它用于评估基于项目的经济合理性,给出项目开发的成本论证,并将估算的成本与预期的利润进行对比。 一般说来,基于项目的成本由4个部分组成:购置并安装软硬件及有关设备的费用,项目开发费用,软硬件系统安装、运行和维护费用,人员的培训费用。在项目的分析和设计阶段只能得到上述费用的预算,即估算成本。在项目开发完毕并将系统交付用户运行后,上述费用的统计结果就是实际成本。 项目开发效益包括经济效益和社会效益两部分。 - 经济效益是指所使用系统为用户增加的收入,可以通过直接的或统计的方法估算。 - 社会效益只能用定性的方法估算。 - 成本估算 - 代码行技术 - 代码行技术是比较简单的定量估算方法,它将开发每个软件功能的成本和实现这个功能需要使用的源代码行数联系起来。通常根据经验和历史数据估算实现一个功能所需的源代码行数。一旦估算出源代码行数后,用每行代码的平均成本乘以行数即可确定软件的成本。每行代码的平均成本主要取决于软件的复杂程度和薪资水平。 - 任务分解技术 - 首先将开发项目分解为若干相对独立的任务,再分别估算每个任务单独开发的成本,最后累加起来就可得出开发项目的总成本。 - 如果项目比较复杂,如由若干子系统组成,则可以将若干子系统再按开发阶段进一步划分成更小的任务。 - ![](../../../../assets/default.png) - 成本——效益分析 - 分析 - 开发成本:用代码行技术或任务分解技术进行估算。 - 运行费用:取决于系统操作的费用(操作员人数、工作时间和消耗物资等),以及维护费用。 - 系统的经济效益:为使用新系统而增加的收入加上使用新系统可以节省的运行费用。 - 四个考虑方面 - 货币的时间价值 - 投资回收期:累计的经济效益等于最初投资所需要的时间,也就是达到估计开发总成本加_上运行维护费用所需要的时间。 - 纯收入=累计经济效益(折合成现在值)一投资额 - 投资回收率=年经营净现金流量或年均经营净现金流量/原始投资额 - 货币的时间价值 - 通常使用利率的形式表示货币的时间价值。假设年利率为i,如果现在存入P元,则n年后可以得到的价值为: $$ F=P(1+i)^n $$             F就是P元在n年后的价值。反之,如果n年后能收入F元,那么这些钱的现在价值就是: $$ P=\frac{F}{(1+i)^n} $$ - 投资回报期 - 投资回收期是衡量项目价值的常用方法。投资回收期就是使累计的经济效益等于最初投资需要的时间。很明显,投资回收期越短,获得利润的速度就越快,该项目就越值得开发。 - 纯收入 - 纯收入是衡量项目价值的另一项经济指标。纯收入就是在软件生命周期中软件系统的累计经济效益(折合成现在值)与投资之差。 ## 可行性研究步骤 - 步骤 - 明确系统的目标在这一步,可行性分析人员要访问相关人员,阅读分析可以掌握的材料,确认用户需要解决问题的实质,进而明确系统的目标以及为了达到这些目标系统所需的各种资源。 - 分析研究现行系统现行系统是新系统重要的信息来源。新系统应该完成现行系统的基本功能,并在此基础上对现行系统中存在的问题进行改善或修复。可以从3个方面分析现有系统:系统组织结构定义、系统处理流程分析和系统数据流分析。 - 设计新系统的高层逻辑模型这一步从较高层次设想新系统的逻辑模型,概括地描述开发人员对新系统的理解和设想。 - 获得并比较可行的方案开发人员可根据新系统的高层逻辑模型提出实现此模型的不同方案。在设计方案的过程中要从技术、经济等角度考虑各方案的可行性,然后从多个方案中选择出最合适的方案。 - 撰写可行性研究报告可行性研究的最后一步就是撰写可行性研究报告。此报告包括项目简介、可行性分析过程和结论等内容。 - 结论 - (1)可以按计划进行软件项目的开发。 - (2)需要解决某些存在的问题(如资金短缺、设备陈旧和开发人员短缺等)或者需要对现有的解决方案进行一些调整或改善后才能进行软件项目开发。 - (3)一旦待开发的软件项目不具有可行性,就立即停止该软件项目。 ## 制定开发计划 - 项目概述。说明项目的各项主要工作;说明软件的功能和性能;为完成项目应具备的条件;甲方和乙方应承担的工作、完成期限和其他限制条件;应交付软件的名称,所使用的开发语言及存储形式;应交付的文档等。 - 实施计划。说明任务的划分,各项任务的责任人;说明项目开发进度,按阶段应完成的任务,用图表说明每项任务的开始时间和完成时间;说明项目的预算,各阶段的费用支出预算等。 - 人员组织及分工。说明开发该项目所需人员的类型、组成结构和数量等。 - 交付期限。说明项目应交付的日期等。

软件工程复习 第二章

# 第二章 软件工程 ## 软件过程 软件的诞生和生命周期是一个过程,我们总体上称这个过程为软件过程 ## 软件生命周期 软件产品的生命周期是指从设计该产品的构想开始,到软件需求的确定、软件设计、软件实现、产品测试与验收、投入使用以及产品版本的不断更新,到最终该产品被市场淘汰的全过程。 - 生命周期的划分原则 - 各阶段的任务应尽可能相对独立; - 同一阶段各项任务的性质尽可能相同。 - 划分生命周期的优点 - 有利于软件开发工程的组织和管理 - 降低了整个软件开发过程的困难程度 - 对每个阶段都可选用最优的管理方法 - 保证软件质量、提高生产效率. - 划分 - 软件定义 - 问题的定义与可行性研究 - 需求分析 - 软件开发 - 软件设计 - 程序编码 - 软件测试 - 软件维护 ## 软件过程模型 人们通过建立抽象的软件开发模型(也称软件过程模型或软件生命周期模型),把软件生命周期中的各个活动或步骤安排到一个框架中,将软件开发的全过程清晰、直观地表达出来 软件开发模型的内在特征有以下4点: - (1)软件开发模型描述了主要的开发阶段 - (2)软件开发模型定义了每个阶段要完成的主要任务和活动 - (3)软件开发模型规范了每个阶段的输入和输出 - (4)软件开发模型提供了一个框架,把必要的活动映射到这个框架中 ### 瀑布模型 - ![](../../../../assets/default.png) - 优点 - 过程模型简单,执行容易 - 缺点 - 无法适应变更。 - 适用情况 - (1)在软件开发的过程中,需求不发生或很少发生变化,并且开发人员可以一次性获取到全部需求 - (2)软件开发人员具有丰富的经验,对软件应用领域很熟悉。 - (3)软件项目的风险较低。瀑布模型不具有完善的风险控制机制。 - 变体 - v模型 - ![](../../../../assets/default.png) ### 快速原型模型 快速原型的基本思想是快速建立一个能反映用户主要需求的原型系统,让用户在计算机上试用它,通过实践来了解目标系统的概貌。 - ![](../../../../assets/default.png) - 优点 - 不带反馈环 - 适用情况 - (1)已有产品或产品的原型(样品),只需客户化的工程项目。 - (2)简单而熟悉的行业或领域。 - (3)有快速原型开发工具。 - (4)进行产品移植或升级。 ### 增量模型 增量模型是把待开发的软件系统模块化,将每个模块作为一个增量组件,从而分批次地分析、设计、编码和测试这些增量组件 - ![](../../../../assets/default.png) - 优点 - (1)将待开发的软件系统模块化,可以分批次提交软件产品,使用户可以及时了解软件项目的进展。 - (2)以组件为单位进行开发降低了软件开发的风险。一个开发周期内的错误不会影响到整个软件系统。 - (3)开发顺序灵活。开发人员可以对构件的实现顺序进行优先级排序,先完成需求稳定的核心组件。当组件的优先级发生变化时,还能及时调整实现顺序。 - 缺点 - 要求待开发的软件系统可以被模块化。 - 适用情况 - (1)软件产品可以分批次地交付。 - (2)待开发的软件系统能够被模块化。 - (3)软件开发人员对应用领域不熟悉,难以一次性地开发系统。 - (4)项目管理人员把握全局的水平较高。 ### 螺旋模型 螺旋模型是一种用于开发风险较大的大型软件项目的开发模型。该模型将瀑布模型与快速原型模型结合起来,并且加入了这两种模型忽略了的风险分析。 ![](../../../../assets/default.png) - 优点 - 将风险分析扩展到各个阶段中,大幅度降低了软件开发的风险。 - 缺点 - 控制和管理较为复杂 - 可操作性不强 - 对项目管理人员的要求较高。 ### 喷泉模型 在分析阶段,定义类和对象之间的关系,建立对象-关系和对象-行为模型。在设计阶段,从实现的角度对分析阶段模型进行修改或扩展。在编码阶段,使用面向对象的编程语言和方法实现设计模型。在面向对象的方法中,分析模型和设计模型采用相同的符号标示体系,各阶段之间没有明显的界限,而且常常重复、迭代地进行。 ![](../../../../assets/default.png) - 适用情况 - 喷泉模型主要用于面向对象的软件项目 - 软件的某个部分通常被重复多次 - 相关对象在每次迭代中随之加入渐进的软件成分。 ### 基于组件的开发模型 基于组件的开发模型使用现有的组件以及系统框架进行产品开发,由于现有组件大多已经历实际应用的反复检验,因此其可靠性相对新研发组件高出很多。 ![](../../../../assets/default.png) - 优点 - 极大地提高了产品开发效率 - 质量也得到了提高 ### 统一软件开发过程模型 统一软件开发过程(Rational Unified Process,RUP)模型是基于UML(统一建模语言)的一种面向对象软件开发模型。采用迭代和增量递进的开发策略,并以用例驱动为特点,集中了多个软件开发模型的优点。RUP模型是迭代模型的一种。 ![](../../../../assets/default.png) ### 敏捷过程与极限编程 敏捷方法是一种轻量级的软件工程方法,相对于传统的软件工程方法,它更强调软件开发过程中各种变化的必然性,通过团队成员之间充分的交流与沟通以及合理的机制来有效地响应变化。 - 四个价值观 - 个体与交互高于过程和工具 - 可运行软件高于详尽的文档 - 与客户协作高于合同(契约)谈判 - 对变更及时响应高于遵循计划 - 12条原则 - (1)首先要做的是通过尽早和持续交付有价值的软件来让客户满意。 - (2)需求变更可以发生在整个软件的开发过程中,即使在开发后期,我们也欢迎客户对于需求的变更。敏捷过程利用变更为客户创造竞争优势。 - (3)经常交付可工作的软件。交付的时间间隔越短越好,最好2~3周一次。 - (4)在整个的软件开发周期中,业务人员和开发人员应该天天在一起工作。 - (5)围绕受激励的个人构建项目,给他们提供所需的环境和支持,并且信任他们能够完成工作。 - (6)在团队的内部,最有效果和效率的信息传递方法是面对面交谈。 - (7)可工作的软件是进度的首要度量标准。 - (8)敏捷过程提倡可持续的开发速度。责任人、开发人员和用户应该能够保持一种长期稳定的开发速度。 - (9)不断地关注优秀的技能和好的设计会增强敏捷能力。 - (10)尽量使工作简单化。 - (11)好的架构、需求和设计来源于自组织团队。 - (12)每隔一定时间,团队应该反省如何才能有效地工作,并相应调整自己的行为。 - 实践方式 - 极限编程(eXtreme Programming,XP) - 自适应软件开发(Adaptive Software Development,ASD) - 动态系统开发方法(Dynamic System Development Method,DSDM) - ScrumCrystal和特征驱动开发(Feature Driven Development,FDD) - 极限编程 - 极限编程是一种实践性较强的规范化的软件开发方法,它强调用户需求和团队工作。 - 适用情况 - 软件需求模糊且容易改变 - 开发团队少于10人 - 开发地点集中 - ![](../../../../assets/default.png) - ![](../../../../assets/default.png) ### 选择软件开发模型 - (1)符合软件自身的特性,如规模、成本和复杂性等 - (2)满足软件开发进度的要求 - (3)对软件开发的风险进行预防和控制 - (4)具有计算机辅助工具的支持。 - (5)与用户和软件开发人员的知识和技能相匹配 - (6)有利于软件开发的管理和控制

软件工程复习 第四章

# 第四章 结构化分析 ## 需求分析 - 作用 - 为了开发出真正满足用户需要的软件产品,明确了解用户需求是关键。 - 需求分析就是要回答“系统必须做什么” - 在需求中会存在大量的错误,这些错误若未及时发现和更正,就会造成软件开发费用增加、软件质量降低,严重时,会造成软件开发失败 - 需求分析是非常重要的过程,它完成的好坏直接影响后续软件开发的质量。 - 方面 - **确定系统的运行环境要求系统运行时的环境要求包括** - 硬件环境要求,如对计算机的CPU、内存、存储器、输入/输出方式 - 通信接口和外围设备等的要求 - 软件环境要求,如操作系统、数据库管理系统和编程语言等的要求。 - **确定系统的功能性需求和非功能性需求** - 功能需求是软件系统最基本的需求表述,包括对系统应该提供的服务,如何对输入做出反应以及系统在特定条件下的行为描述。 - 非功能性需求包括对系统提出的性能需求、可靠性和可用性需求、系统安全以及系统对开发过程、时间、资源等方面的约束和标准等。 - 进行有效的需求分析 - 原则 - 需求分析是一个过程,它应该贯穿于系统的整个生命周期中,而不是仅仅属于软件生命周期早期的一项工作。 - 需求分析应该是一个迭代的过程。通常情况下,需求是随着项目的深入而不断变化的。 - 为了方便评审和后续的设计,需求的表述应该具体、清晰,并且是可测量的、可实现的。最好能够对需求进行适当的量化 - 两个任务 - 需求分析的建模阶段,即在充分了解需求的基础上,建立起系统的分析模型。 - 需求分析的描述阶段,就是把需求文档化,用软件需求规格说明书的方式把需求表达出来。 - 软件需求规格说明书 - 软件需求规格说明书是需求分析阶段的输出,它全面、清晰地描述了用户需求,因此是开发人员进行后续软件设计的重要依据。软件需求规格说明书应该具有清晰性、无二义性、一致性和准确性等特点。同时,它还需通过严格的需求验证、反复修改的过程才能最终确定。 - 步骤 - **需求获取** - 观察 - 体验 - 问卷调查 - 访谈 - 单据分析 - 报表分析 - 需求调研会 - 分析建模 - 获取需求后,下一步就应该对开发的系统建立分析模型了。模型就是为了理解事物而对事物做出的一种抽象,通常由一组符号和组织这些符号的规则组成。对待开发系统建立各种角度的模型有助于人们更好地理解问题 - 需求描述 - 需求描述就是指编制需求分析阶段的文档。一般情况下,复杂的软件系统在需求阶段会产生3个文档:**系统定义文档(用户需求报告)、系统需求文档(系统需求规格说明书)、软件需求文档(软件需求规格说明书)**。而对简单的软件系统而言,需求阶段只需要输出<mark>软件需求文档</mark>就可以了。 - 需求验证 - 需求分析阶段的工作成果是后续软件开发的重要基础,为了提高软件开发的质量,降低软件开发的成本,必须对需求的正确性进行严格的验证,确保需求的一致性、完整性、现实性、有效性,确保设计与实现过程中的需求可回溯性,并进行需求变更管理 - 需求管理 - 为了更好地进行需求分析并记录需求结果,需要进行需求管理。 - 需求管理是一种用于查找、记录、组织和跟踪系统需求变更的系统化方法。可用于: - (1)获取、组织和记录系统需求。 - (2)使客户和项目团队在系统变更需求上达成并保持一致。 - 有效需求管理的关键在于维护需求的阐述足够明确、每种需求类型适用的属性,以及与其他需求和其他项目工件之间的可追踪性。 - 需求管理实际上是项目管理的一部分,它涉及以下3个主要问题 - (1)识别、分类、组织需求,并为需求建立文档。 - (2)需求变化,即带有建立对需求不可避免的变化是如何提出、如何协商、如何验证以及如何形成文档的过程。 - (3)需求的可跟踪性,即带有维护需求之间以及与系统的其他制品之间依赖关系的过程。 - 需求分析的常用方法 - 功能分解方法 - 功能分解方法是将一个系统看成是由若干功能模块组成的,每个功能又可分解为若干子功能及接口,子功能再继续分解,即功能、子功能和功能接口为功能分解方法的3个要素。功能分解方法采用自顶向下、逐步求精的理念。 - 结构化分析方法 - 结构化分析方法是一种从问题空间到某种表示的映射方法,其逻辑模型由数据流图和数据词典构成并表示。它是一种面向数据流的需求分析方法 - 信息建模方法 - 模型是用某种媒介对相同媒介或其他媒介中的一些事物进行模拟表现的形式。从一个建模角度出发,模型就是要抓住事物最重要的方面而简化或忽略其他方面。简而言之,模型就是对现实的简化。建立模型的过程称为建模。 - 建模可以帮助理解正在开发的系统,这是需要建模的一个基本理由,并且,人对复杂问题的理解能力是有限的。建模可以帮助开发者缩小问题的范围,每次着重研究一个方面,进而对整个系统产生更加深刻的理解。可以明确地说,越大、越复杂的系统,建模就越重要。 - 面向对象的分析方法 - 面向对象的分析方法的关键是识别问题域内的对象,分析它们之间的关系,并建立3类模型。 - 它们分别是 - 描述系统静态结构的对象模型 - 描述系统控制结构的动态模型 - 描述系统计算结构的功能模型 - 其中,对象模型是最基本、最核心、最重要的。面向对象主要考虑类或对象、结构与连接、继承和封装、消息通信,只表示面向对象分析中几项最重要的特征。类的对象是对问题域中事物的完整映射,包括事物的数据特征(即属性)和行为特征(即服务) ## 结构化分析概述 一种考虑数据和处理的需求分析方法被称为结构化分析(Structured Analysis,SA)方法,它是20世纪70年代由Yourdon Constaintine及DeMarco等人提出和发展,并得到广泛应用的。它基于“分解”和“抽象”的基本思想,逐步建立目标系统的逻辑模型,进而描绘出满足用户要求的软件系统。 结构化分析的具体步骤如下。 - 建立当前系统的“具体模型”。 - 抽象出当前系统的逻辑模型。 - 建立目标系统的逻辑模型。 - 为了完整地描述目标系统,还需要考虑人机界面和其他一些问题。 ## 结构化分析方法 ![](../../../../assets/default.png) - 此模型的核心是“数据字典”,它描述软件使用或产生的所有数据对象。 - 围绕这个核心有3种图 - “数据流图”指出当数据在软件系统中移动时怎样变换,以及描绘变换数据流的功能和子功能,用于功能建模 - “实体-关系图”(E-R图)描绘数据对象之间的关系,用于数据建模 - “状态转换图”指明作为外部事件结果的系统行为,用于行为建模。 - 结构化分析方法必须遵守下述准则。 - (1)必须定义软件应完成的功能,这条准则要求建立功能模型。 - (2)必须理解和表示问题的信息域,根据这条准则建立数据模型。 - (3)必须表示作为外部事件结果的软件行为,这条准则要求建立行为模型。 - (4)必须对描述功能、信息和行为的模型进行分解,用层次的方式展示细节。 - (5)分析过程应该从要素信息移向实现细节。 - 不同的模型往往表述系统需求的某一方面,而模型之间又相互关联,相互补充。 ### 功能建模 功能建模的思想就是用抽象模型的概念,按照软件内部数据传递和变换的关系,自顶向下逐层分解,直到找到满足功能要求的可实现的软件为止。<mark>功能模型用数据流图来描述。</mark> 数据流图(简称DFD图)就是采用图形方式来表达系统的逻辑功能、数据在系统内部的逻辑流向和逻辑变换过程,是结构化系统分析方法的主要表达工具及用于表示软件模型的一种图示方法。 - 数据流图 - 4种符号 - (1)外部实体:表示数据的源点或终点,它是系统之外的实体,可以是人、物或者其他系统。 - (2)数据流:表示数据流的流动方向。数据流可以从加工流向加工、从加工流向文件、从文件流向加工。 - (3)数据变换:表示对数据进行加工或处理,比如对数据的算法分析和科学计算。 - (4)数据存储:表示输入或输出文件。这些文件可以是计算机系统中的外部或者内部文件,也可以是表、账单等。 - Yourdon表示法 - (1)矩形表示数据的外部实体。 - (2)圆形泡泡表示变换数据的处理逻辑。 - (3)两条平行线表示数据的存储。 - (4)箭头表示数据流。 - 环境图 - 环境图也称为系统顶层数据流图(或0层数据流图),它仅包括一个数据处理过程,也就是要开发的目标系统。 - 环境图的作用是确定系统在其环境中的位置,通过确定系统的输入和输出与外部实体的关系确定其边界。 - 根据结构化需求分析采用的“自顶向下,由外到内,逐层分解”的思想,开发人员要先画出系统顶层的数据流图,然后再逐层画出低层的数据流图。顶层的数据流图要定义系统范围,并描述系统与外界的数据联系,它是对系统架构的高度概括和抽象。底层的数据流图是对系统某个部分的精细描述。 - 遵守的原则 - (1)第0层的数据流图应将软件描述为一个泡泡。 - (2)主要的输入和输出应该仔细标记。 - (3)通过分离在下一层表示的候选处理过程、数据对象和数据存储,开始求精过程。 - (4)应使用有意义的名称标记所有的箭头和泡泡。 - (5)当从一个层转移到另一个层时要保持信息流的连续性。 - (6)一次精化一个泡泡。 - 数据流图的分层 - 对于稍微复杂一些的实际问题,在数据流图上常常出现十几个甚至几十.个加工,这样的数据流图看起来不直观,不易理解,分层的数据流图能很好地解决这一问题。 - 按照系统的层次结构进行逐步分解,并以分层的数据流图反映这种结构关系,能清楚地表达和容易理解整个系统。 - 原则 - 数据守恒与数据封闭原则 - 所谓数据守恒是指加工的输入输出数据流是否匹配,即每一-个加工既有输入数据流又有输出数据流。或者说一个加工至少有一 个输入数据流,一个输出数据流。 - 分解加工的原则 - 自然性:概念上合理、清晰; - 均匀性:理想的分解是将一个问题分解成大小均匀的几个部分; - 分解度:每个加工每次分解一般不超过7士2个子加工;分解到基本加工为止。 - 子图与父图的“平衡” - 父图中某个加工的输入输出数据流应该同相应的子图的输入输出相同(或相对应),分层数据流图的这种特点称为子图与父图“平衡” - 合理使用文件 - 当文件作为某些加工之间的交界面时,文件必须画出来,一旦文件作为数据流图中的一个独立成份画出来了,那么同其他成份之间的联系也应同时表达出来。 ### 数据建模 - 数据模型中包含3种相互关联的信息 - 数据对象 - 数据对象是对软件必须理解的复合信息的抽象。数据对象可以是外部实体、事物、行为、事件、角色、单位、地点或结构等。总之,可以由一组属性来定义的实体都可以被认为是数据对象 - 数据对象的属性 - 属性定义了数据对象的性质 - 必须把一个或多个属性定义为“标识符”,也就是说,当人们希望找到数据对象的一个实例时,用标识符属性作为“关键字”(通常简称为“键”) - 数据对象彼此间相互连接的关系 - 客观世界中的事物彼此间往往是有联系的 - 数据对象彼此之间相互连接的方式称为联系,也称为关系 - 关系用菱形表示,并用无向边分别与有关实体连接起来,以此描述实体之间的关系 - 关联数量的表示 - ![](../../../../assets/default.png) - 关系本身也可能有属性, - 关系属性的表示 - 在表示关系的无向边上再加一个菱形框,并在菱形框中标明关系的名字,关系的属性同样用椭圆形或圆角矩形表示,并用无向边将关系与其属性连接起来。 ### 行为建模 状态转化图 - 状态转换图是一种描述系统对内部或外部事件响应的行为模型。它描述系统状态和事件,事件引发系统在状态间的转换,而不是描述系统中数据的流动。这种模型尤其适合用来描述实时系统,因为这类系统多是由外部环境的激励而驱动的。 - 优点 - 状态之间的关系能够直观地捕捉到 - 由于状态转换图的单纯性,能够机械地分析许多情况,可以很容易地建立分析工具。 - 状态转换图能够很方便地对应状态转换表等其他描述工具 - 并不是所有的系统都需要画状态转换图,有时系统中的某些数据对象在不同状态下会呈现不同的行为方式,此时应分析数据对象的状态,画出状态转换图,才可正确认识数据对象的行为,并定义其行为。对这些行为规则较复杂的数据对象需要进行如下分析。 - 找出数据对象的所有状态 - 分析在不同的状态下,数据对象的行为规则是否不同,若无不同,则可将其合并成一种状态 - 分析从一种状态可以转换成哪几种状态,是数据对象的什么行为导致这种状态的转换。 - 状态 - 状态是任何可以被观察到的系统行为模式,一个状态代表系统的一种行为模式 - 在状态转换图中定义的状态主要有 - 初态(即初始状态) - 终态(即最终状态) - 中间状态 - **一张状态图中只能有一个初态,而终态可以没有,也可以有多个** - 状态中的活动表的语法格式如下 - 事件名(参数表)/动作 - 表达式其中,“事件名”可以是任何事件的名称。 - 事件 - 事件是在某个特定时刻发生的事情,它是对引起系统做动作或(和)从一个状态转换到另一个状态的外界事件的抽象。 - 状态变迁通常是由事件触发的,在这种情况下,应在表示状态转换的箭头线上标出触发转换的事件表达式。 - 事件表达式的语法如下 - `事件说明[守卫条件]/动作表达式` - 其中,事件说明的语法为:`事件名(参数表)` - 守卫条件是一个布尔表达式。如果同时使用事件说明和守卫条件,则当且仅当事件发生且布尔表达式为真时,状态转换才发生。如果只有守卫条件没有事件说明,则只要守卫条件为真,状态转换就发生。 - 动作表达式是一个过程表达式,当状态转换开始时执行该表达式。 ### 数据字典 - 数据字典是关于数据的信息的集合,也就是对数据流图中包含的所有元素的定义的集合。 - 数据字典可以把不同的需求文档和分析模型紧密结合在一-起,如果所有的开发人员在数据字典上取得一致意见, 那么就可以缓和集成性问题。为了避免冗余和不一致性,应该在项目中创建一个独立的数据字典,而并不是在每个需求出现的地方定义每一个数据项。 - 六类条目 - 数据项 - 数据结构 - 数据流 - 数据存储 - 加工逻辑 - 外部实体 ### 加工规格说明 - 过程设计语言 - 过程设计语言(Procedure Design Language,PDL),也称为伪代码,在某些情况下,在加工规格说明中会用到。但一般说来,最好将用PDL来描述加工规格说明的工作推迟到过程设计阶段进行比较好。 - 判定表 - 在某些数据处理中,某个数据处理(即加工)的执行可能需要依赖于多个逻辑条件的取值,此时可用判定表。判定表能够清晰地表示复杂的条件组合与应做的动作之间的对应关系。 - 判定树 - 判定树是判定表的变种,也能清晰地表示复杂的条件组合与应做的动作之间的对应关系。判定树也是用来表述加工规格说明的一种工具。判定树的优点在于,它的形式简单到不需要任何说明,一眼就可以看出其含义,因此易于掌握和使用 ## 结构化分析的图形工具 - 层次方框图 - 层次方框图由树形结构的一系列多层次的矩形组成,用来描述数据的层次结构。 - 方框之间的关系是组成关系,而不是调用关系。 - Warnier图 - 与层次方框图相似,也用树形结构来描绘数据结构,但提供了更详细的描绘手段 - 能指出某一类数据或某一数据元素重复出现的次数,并能指明某一特定数据在某一类数据中是否是有条件地出现。 - IPO图 - IPO图是输入-处理-输出(Input-Process-Output)图的简称。 - 能够方便地描绘输入数据、对数据的处理和输出数据之间的关系。

软件工程复习 第五章

# 第五章 结构化设计 - 目标 - 回答系统应该“怎么做”这个问题。 - 意义 - 软件设计在软件开发过程中处于核心地位,它是保证质量的关键步骤。 - 设计为我们提供了可以用于质量评估的软件表示、 - 设计是我们能够将用户需求准确地转化为软件产品或系统的唯一方法 - 软件设计是所有软件工程活动和随后的软件支持活动的基础。 - 软件设计是一个迭代的过程,通过设计过程,需求被变换为用于构建软件的“蓝图”。 - 良好设计演化的三个特征 - 设计必须实现所有包含在分析模型中的明确需求,而且必须满足用户期望的所有隐含需求。 - 对于程序员、测试人员和维护人员而言,设计必须是可读的、可理解的指南。 - 设计必须提供软件的全貌,从实现的角度说明数据域、功能域和行为域。 - 以上每一个特征实际上都是设计过程应该达到的目标。 - 原则 - 模块化 - 模块是数据说明、可执行语句等程序对象的集合,是构成程序的基本构件,可以被单独命名并通过名字来访问。在面向过程的设计中,过程、函数、子程序、宏都可以作为模块;在面向对象的设计中,对象是模块,对象中的方法也是模块。 - 模块化就是把系统或程序划分为独立命名并且可以独立访问的模块,每个模块完成一个特定的子功能。模块集成起来可以构成-一个整体,完成特定的功能,进而满足用户需求。 - 模块的公共属性: - 接口:指模块的输入、输出。 - 功能:指模块的逻辑功能。 - 状态:指模块的运行环境,即模块的调用和被调用关系 - 逻辑:描述内部如何实现要求的功能及所需的数据。 ### 内聚的分类 内聚的种类由紧到松(越紧越好)依次为: 1. **功能内聚**:指模块内的所有元素共同作用完成一个功能,缺一不可。 2. **顺序内聚**:指一个模块中的各个处理元素都密切相关于同一功能且必须顺序执行,前一功能元素的输出就是下一个功能元素的输入。 3. **通信内聚**:指模块内所有处理元素都在同一个数据结构上。 4. **过程内聚**:指一个模块完成多个任务,这些任务必须按指定的过程执行。 5. **瞬时内聚**:把需要同时执行的任务或动作组合在一起(如初始化模块)。 6. **逻辑内聚**:模块完成逻辑上相关的一组任务。 7. **偶然内聚**:指一个模块内的各处理元素之间没有任何联系或有松散的联系。 ### 耦合的分类 耦合的种类从高到低(越低越好)依次为: 1. **内容耦合**:一个模块直接使用另一个模块的内部数据,或通过非正常入口转入另一个模块内部时,这种耦合关系就是内容耦合。 2. **公共耦合**:指一组模块访问一个公共数据环境,如全局数据结构。 3. **外部耦合**:指一组模块访问一个公共变量,这里指基本数据类型而不是数据结构(或者说对象)。 4. **控制耦合**:指一个模块调用另一个模块时,传递的是控制变量,被调用模块通过该控制变量的值选择执行模块内某一功能。那么也就是说,被调用的模块应具有多个功能。 5. **标记耦合**:耦合模块之间以数据结构传递(比如在 java 程序中,传递的就是一个对象)。 6. **数据耦合**:耦合模块之间有调用关系,传递的是简单数据类型的值(比如在 java 程序中,传递的就是一个基本数据类型的值)。 7. **无直接耦合**:指两个模块之间没有直接的关系,它们分别从属于不同模块的控制与调用,它们之间不传递任何信息。

软件工程复习 第六章

# 面向对象方法与UML ## 面向对象的软件工程方法 - 基本观点 - 客观世界是由对象组成的,任何客观的事物或实体都是对象,复杂的对象可以由简单的对象组成。 - 具有相同数据和相同操作的对象可以归并为一个类,对象是对象类的一个实例。 - 类可以派生出子类,子类继承父类的全部特性(数据和操作) ,又可以有自己的新特性。子类父类形成类的层次结构。 - 对象之间通过消息传递相互联系。类具有封装性,其数据和操作等对外界是不可见的,外界只能通过消息请求进行某些操作,提供所需要的服务。 - 基本概念 - 面向对象:按人们认识客观世界的系统思维方式,采用基于对象的概念建立模型,模拟客观世界分析、设计、实现软件的办法。通过面向对象的理念使计算机软件系统能与现实世界中的系统一一对应。 - 对象:即指现实世界中各种各样的实体。它可以指具体的事物,也可以指抽象的事物。在面向对象概念中我们把对象的内部状态称为属性,把运动规律称为方法或事件。 - 类:类是具有相似内部状态和运动规律的实体的集合。对于一个具体的类,它有许多具体的个体,我们就管这些个体叫作“对象”。类的内部状态是指类集合中对象的共同状态;类的运动规律是指类集合中对象的共同运动规律。 - 消息:消息是指对象间相互联系和相互作用的方式。一个消息主要由5部分组成:发送消息的对象、接收消息的对象、消息传递办法、消息内容、反馈。 - 包:现实世界中不同对象间的相互联系和相互作用构成了各种不同的系统,不同系统间的相互联系和相互作用构成了更庞大的系统,进而构成了整个世界。在面向对象概念中把这些系统称为包 - 接口:在系统间相互作用时为了蕴藏系统内部的具体实现,系统通过设立接口界面类或对象来与其他系统进行交互;让其他系统只看到这个接口界面类或对象,这个类在面向对象中称为接口类。 - 类的特性 - 抽象:类的定义中明确指出类是一组具有内部状态和运动规律对象的抽象,抽象是一种从一般的观点看待事物的方法,它要求我们集中于事物的本质特征,而非具体细节或具体实现。 - ②继承:继承是类不同抽象级别之间的关系。在计算机软件开发中采用继承性,提供了类的规范的等级结构;通过类的继承关系,使公共的特性能够共享,提高了软件的重用性 - ③封装:对象间的相互联系和相互作用过程主要通过消息机制得以实现。对象之间并不需要过多地了解对方内部的具体状态或运动规律。面向对象的类是封装良好的模块,类定义将其说明与实现显式地分开,其内部实现按其具体定义的作用域提供保护。类是封装的最基本单位。封装防止了程序相互依赖而带来的变动影响。在类中定义的接收对方消息的方法称为类的接口。 - 多态:多态是指同名的方法可在不同的类中具有不同的运动规律。在父类演绎为子类时,类的运动规律也同样可以演绎,演绎使子类的同名运动规律或运动形式更具体,甚至子类可以有不同于父类的运动规律或运动形式。不同的子类可以演绎出不同的运动规律 - 重载:重载指类的同名方法在给其传递不同的参数时可以有不同的运动规律。在对象间相互作用时,即使接收消息对象采用相同的接收办法,但消息内容的详细程度不同,接收消息对象内部的运动规律也可能不同。 - 特征 - 把数据和操作封装在一起,形成对象。对象是构成软件系统的基本构件 - 把特征相似的对象抽象为类 - 类之间可以存在继承或被继承的关系,形成软件系统的层次结构 - 对象之间通过发送消息进行通信 - 将对象的私有信息封装起来。外界不能直接访问对象的内部信息,而必须是发送相应的消息后,通过有限的接口来访问。 - 优势 - 符合人类的思维习惯 - 稳定性好 - 可复用性好 - 可维护性好 - 实施步骤 - 面向对象分析:从问题陈述入手,分析和构造所关心的现实世界问题域的模型,并用相应的符号系统表示。 - 确定问题域,包括定义论域、选择论域、根据需要细化和增加论域 - 区分类和对象,包括定义对象、定义类、命名 - 区分整体对象以及组成部分,确定类的关系以及结构 - 定义属性,包括确定属性、安排属性 - 定义服务,包括确定对象状态、确定所需服务、确定消息联结 - 确定附加的系统约束 - 面向对象设计 - 应用面向对象分析,改善和完善用其他方法得到的系统分析结果 - 设计交互过程和用户接口 - 设计任务管理,根据前一步骤确定是否需要多重任务,确定并发性,确定以何种方式驱动任务,设计子系统以及任务之间的协调与通信方式,确定优先级 - 设计全局资源,确定边界条件,确定任务或子系统的软、硬件分配 - 面向对象实现:使用面向对象语言实现面向对象的设计相对比较容易。用非面向对象语言实现面向对象的设计时,特别需要注意和保留程序的面向对象结构 - 面向对象测试:对面向对象实现的程序进行测试,包括模型测试、类测试、交互测试、系统(子系统)测试、验收测试等 ## 统一建模语言(Unify Modeling Language) 统一建模语言(Unified Modeling Language,UML)是一种通用的可视化建模语言,可以用来描述、可视化、构造和文档化软件密集型系统的各种工件。它是由信息系统和面向对象领域的3位著名的方法学家GradyBooch、James Rumbaugh和Ivar Jacobson提出的。它记录了与被构建系统有关的决策和理解,可用于对系统的理解、设计、浏览、配置、维护以及控制系统的信息。这种建模语言已经得到了广泛的支持和应用,并且已被ISO组织发布为国际标准。 - UML是一种标准的图形化建模语言,它是面向对象分析与设计的一种标准表示 - 它不是一种可视化的程序设计语言,而是一种可视化的建模语言 - 它不是工具或知识库的规格说明,而是一种建模语言规格说明,是一种表示的标准 - 它不是过程,也不是方法,但允许任何一种过程和方法使用它。 - 特点 - 统一标准 - 面向对象 - 可视化,表达能力强大 - 独立于过程 - 容易掌握使用 - 与编程语言的关系 - 应用范围 - UML以面向对象的方式来描述系统。UML最广泛的应用是对软件系统进行建模,但它同样适用于许多非软件系统领域的系统。从理论上来说,任何具有静态结构和动态行为的系统都可以使用UML建模。当UML应用于大多数软件系统的开发过程时,它从需求分析阶段到系统完成后的测试阶段都能起到重要作用。 - 组成 - UIL符号为开发者或开发工具使用这些图形符号和文本语法为系统建模提供了标准 - 这些图形符号和文字所表达的是应用级的模型,在语义上它是U0元模型的实例 - UIL模型由事物、关系和图组成 - [UML概述_w3cschool](https://www.w3cschool.cn/uml_tutorial/uml_tutorial-c1gf28pd.html) ## 静态建模机制 任何建模语言都以静态建模机制为基础,UML也不例外。<mark>UML的静态建模机制包括用例图、类图、对象图、包图等。</mark> ### 用例图 用例图是从用户的角度描述系统的功能,由用例(Use Case)、参与者(Actor)以及它们的关系连线组成。 用例的特征用例是从用户角度描述系统的行为,它将系统的一个功能描述成一系列的事件,这些事件最终对操作者产生有价值的观测结果。参与者(也称为操作者或执行者)是与系统交互的外部实体,可能是使用者,也可能是与系统交互的外部系统、基础设备等。用例是一个类,它代表一类功能而不是使用该功能的某一具体实例。 - 包含关系 - 如果系统用例较多,不同的用例之间存在共同行为,可以将这些共同行为提取出来,单独组成一个用例。当其他用例使用这个用例时,它们就构成了包含关系。 - 扩展关系 - 在用例的执行过程中,可能出现一些异常行为,也可能会在不同的分支行为中选择执行,这时可将异常行为与可选分支抽象成一个单独的扩展用例,这样扩展用例与主用例之间就构成了扩展关系。一个用例常常有多个扩展用例。 - 泛化关系 - 用例之间的泛化关系描述用例的一般与特殊关系,不同的子用例代表了父用例的不同实现。 ### 类图和对象图 类图使用类和对象描述系统的结构,展示了系统中类的静态结构,即类与类之间的相互关系。类之间有多种联系方式,如关联(相互连接)、依赖(一个类依赖于或使用另一个类)、泛化(一个类是另一个类的特殊情况)。一个系统有多幅类图,一个类也可以出现在几幅类图中。 对象图是类图的实例,它展示了系统在某一时刻的快照。对象图使用与类图相同的符号,只是在对象名下面加上下画线。 ### 包图 包是一种对元素进行分组的机制。如果系统非常复杂,常常包含大量的模型,为了便于理解以及将模型独立出来用于复用,对这些元素进行分组组织,从而作为一个个集合进行整体命名和处理。 ## 动态建模机制 系统中的对象在执行期间的不同时间点如何通信以及通信的结果如何,就是系统的动态行为,也就是说,对象通过通信相互协作的方式以及系统中的对象在系统生命期中改变状态的方式,是系统的动态行为。<mark>UML的动态建模机制包括顺序图、协作图、状态图和活动图。</mark> ### 顺序图 顺序图描述了一组对象的交互方式,它表示完成某项行为的对象和这些对象之间传递消息的时间顺序。顺序图由对象(参与者的实例也是对象)、生命线、控制焦点、消息等组成。生命线是一条垂直的虚线,表示对象的存在时间;控制焦点是一个细长的矩形,表示对象执行一个操作经历的时间段;消息是作用于控制焦点上的一条水平带箭头的实现,表示消息的传递。 - 绘制顺序图的步骤如下 - 列出启动该用例的参与者 - 列出启动用例时参与者使用的边界对象 - 列出管理该用例的控制对象 - 根据用例描述的所有流程,按时间顺序列出分析对象之间进行消息传递的序列 - 绘制顺序图需要注意以下问题。 - 如果用例的事件流包含基本流和若干备选流,则应当对基本流和备选流分别绘制顺序图 - 如果备选流比较简单,可以合并到基本流中 - 如果事件流比较复杂,可以在时间方向上将其分成多个顺序图 - 实体对象一般不会访问边界对象和控制对象。 ### 协作图 协作图显示多个对象及它们之间的关系,对象间的箭头显示消息的流向。消息上也可以附带标签,表示消息的其他信息,如发送顺序、显示条件、迭代和返回值等。开发人员熟识消息标签的语法之后,就可以读懂对象之间的通信,并跟踪标准执行流程和消息交换顺序。但是,如果不知道消息的发送顺序,就不能使用协作图来表示对象关系。图6-21为某个系统的“登录”交互过程的简要协作图。 ### 状态图 状态图由状态机扩展而来,用来描述对象对外部对象响应的历史状态序列,即描述对象所有可能的状态,以及哪些事件将导致状态改变。状态图包括对象在各个不同状态间的跳转以及这些跳转的外部触发事件,即从状态到状态的控制流。状态图侧重于描述某个对象的动态行为,是对象的生命周期模型。并不是所有的类都需要画状态图,只有明确意义的状态、在不同状态下行为有所不同的类,才需要画状态图。状态图在4.3.3节中已经介绍,这里不再赘述。 ### 活动图 活动图是展示整个计算步骤的控制流(及其操作数)的节点和流的图。执行的步骤可以是并发的或顺序的。 ## 描述物理架构的机制 系统架构分为逻辑架构和物理架构两大类。逻辑架构完整地描述系统的功能,把功能分配到系统的各个部分,详细说明它们是如何工作的。物理架构详细描述系统的软件和硬件,描述软件和硬件的分解。在UML中,用于描述逻辑架构的图有:用例图、类图、对象图、状态图、活动图、协作图和顺序图;<mark>用于描述物理架构的图有:构件图、部署图。</mark> ### 构件图 构件图根据系统的代码构件显示系统代码的物理结构。 ### 部署图

软件工程复习 第八章

# 第八章 软件体系结构 体系结构是研究系统各部分组成及相互关系的技术学科。它包括以下几个部分: - 软件的组成元素(组件) - 这些(组件)元素的外部可见特性 - 这些元素(组件)之间的相互关系。 ## 体系结构模式 ### 分层模式 将软件系统按照抽象级别逐层递增或递减的顺序划分为若干层次,每层由一-些抽象级别相同的构件组成。 每层的构件仅为其上的层次提供服务,并且它们仅使用其下层提供的服务。 一般而言, 顶层直接面向用户提供软件系统的交互界面,底层则负责提供基础性、公共性的技术服务,比较接近于硬件计算环境、操作系统或数据库管理系统。 - 层次之间的连接有两种形态: - 高层构件向低层构件发出服务请求,低层构件在计算完成后向请求者发送服务应答。 - 低层构件主动探测或被动获知计算环境的变化事件后通知高层构件。 - 优势 - 松耦合。通过软件层次的划分和层间接口的规整,有效降低耦合度,系统各构件之间依赖关系的局部化。 - 可替换性。一个层次可被替换。 - 可复用性。具有良好定义的抽象级别和对外服务接口。 - 劣势 - 高层功能需要逐层调用下层服务,返回值、报错信息又需逐层上传,耗时 - 若低层服务还完成了最初的服务请求者不需要的冗余功能,性能损耗更严重。 ### 管道过滤器模式 将软件系统的功能实现为一-系列的处理步骤,每个步骤封装在一个过滤器构件中,相邻过滤器之间由管道连接。一个过滤器的输入数据借助管道流向后续过滤器,作为其输入数据。 输入由数据源提供,它通过管道与过滤器相连。最终输出由源自某个过滤器的管道流向数据汇。数据源和汇通常为数据库、文件、其他软件系统和物理设备。 采用管道过滤器模式,可以通过升级、更换部分过滤器构件以及处理步骤的充足来实现软件系统的扩展和进化。此模式适合于采用批处理方式的软件系统,不适合与交互式、事件驱动的系统 ### 黑板模式 - 将软件系统划分为黑板、知识源和控制器3类构件 - 黑板负责保存问题求解过程中的状态数据,并提供这些数据的读写服务 - 知识源负责根据黑板中存储的问题求解状态评价其自身的可应用性,进行部分问题求解工作,并将此工作的结果数据写入黑板 - 控制器负责监视黑板中不断更新的状态数据,安排知识源的活动 - 适合于没有确定的求解方法的复杂问题 - 优势: - 知识源和控制器可灵活更换、升级。 - 知识源之间没有交互,知识源与控制器和黑板之间均通过接口交互,知识源可复用性好。 - 知识源的求解动作是探索性的,允许失败和试错。 - 劣势 - 问题求解性能较低,有时甚至无法预测求解时间。 - 不能确保得到最优解。 - 问题求解路径不确定,造成软件测试较为困难。 - 知识源和控制器两种构件的开发相当困难。 ### 分布式体系结构 - 优势 - 资源共享。分布式系统允许硬件、软件等资源共享使用 - 经济性。 - 性能与可扩展性。 - 固有分布性。 - 健壮性。 - 多处理机体系结构 - 分布式系统的一个最简单的模型是多处理器系统,系统由许多进程组成,这些进程可以在不同的处理器上并行运行,可以极大地提高系统的性能。 - 由于大型实时系统对响应时间要求较高,这种模型在大型实时系统中比较常见。大型实时系统需要实时采集信息,并利用采集到的信息进行决策,然后发送信号给执行机构。虽然,信息采集、决策制定和执行控制这些进程可以在同一台处理器上统一 调度执行,但使用多处理器能够提高系统性能。 - 客户/服务器模式 - 客户机/服务器( client/server , C/S )体系结构是基于资源不对等且为实现共享而提出来的,由服务器、客户机和网络三部分组成。 - 在C/S体系结构中,客户机可以通过远程调用来获取服务器提供的服务,因此,客户机必须知道可用的服务器的名字及它们所提供的服务,而服务器不需要知道客户机的身份,也不需要知道有多少台服务器在运行。 - 瘦客户机模型 - 在瘦客户机模型中,数据管理部分和应用逻辑都在服务器上执行,客户机只负责表示部分。 - 瘦客户机模型的主要缺点: - 它将繁重的处理负荷都放在了服务器和网络上,服务器负责所有的计算,这将增加客户机和服务器之间的网络流量。 - 目前个人计算机所具有的处理能力在瘦客户机模型中用不上。 - 胖客户机模型 - 在这种模型中,服务器只负责对数据的管理。客户机_上的软件实现应用逻辑和与系统用户的交互。 - 胖客户机模型能够利用客户机的处理能力,比瘦客户机模型在分布处理上更有效。 - 缺点: - 开发成本较高 - 用户界面风格不一,使用繁杂,不利于推广使用 - 软件移植困难 - 软件维护和升级困难 - 三层C/S体系 - 为了解决以上问题,三层C/S体系结构应运而生。三层C/S体系结构中增加了应用服务器。可以将整个应用逻辑驻留在应用服务器上,而只有表示层存在于客户机上。 - B/S体系 - 浏览器/服务器( browser/server , B/S )风格是三层体系结构的一种实现方式,其具体结构为浏览器/Web服务器/数据库服务器。B/S体系结构如下图所示。 - B/S体系结构主要是利用不断成熟的WWW浏览器技术,结合浏览器的多种脚本语言,用通用浏览器就实现了原来需要复杂的专用软件才能实现的强大功能,并节约了开发成本。从某种程度上来说, B/S结构是一种全新的软件体系结构。 - B/S体系结构具有以下优点: - 基于B/S体系结构的软件,系统安装、修改和维护全在服务器端解决。 - B/S体系结构还提供了异种机、异种网、异种应用服务的联机、联网和统一服务的最现实的开放性基础。 -