精华内容
下载资源
问答
  • 4 存储管理

    2019-12-23 22:52:39
    存储管理的功能: 分配和去配 抽象和映射 隔离和共享 存储扩充 存储器层次:寄存器、缓存、内存、磁盘、磁带 地址转换和存储保护: 编译程序负责记录引用发生的位置,编译或汇编的结果产生相应的多目标...

    4 存储管理

    1 存储器工作原理

    存储管理的功能:

    • 分配和去配
    • 抽象和映射
    • 隔离和共享
    • 存储扩充

    存储器层次:寄存器、缓存、内存、磁盘、磁带

    地址转换和存储保护:

     

    • 编译程序负责记录引用发生的位置,编译或汇编的结果产生相应的多个目标代码模块,每个都附有供引用使用的内部符号表和外部符号表。符号表中依次给出每个符号名及在本目标代码模块中的名字地址,在模块被链接时进行转换
    • 链接需要解析内部和外部符号表,把对符号名字引用转换为数值引用,要转换每个涉及名字地址的程序入口点和数据引用点成为数值地址
      • 链接程序(linker)的作用是根据目标模块之间的调用和依赖关系,将主调模块、被调模块、以及所用到的库函数装配和链接成一个完整的可装载执行模块
    • 装入时根据指定的内存块首地址,再次修改和调整被装载模块中的每个逻辑地址,将逻辑地址绑定到物理地址
    • 根据程序链接发生的时刻和链接方式,可分成三种:
      • 静态链接
      • 动态链接
      • 运行时链接
    • 装载程序(loader)把可执行程序装入内存方式有三种: 
      • 绝对装载。装载模块中的指令地址始终与其内存中的地址相同,即在模块中出现的所有地址都是内存绝对地址
      • 可重定位装载。根据内存当时使用情况,决定将装载代码模块放入内存的物理位置。模块内使用的地址都是相对地址
      • 动态运行时装载。为提高内存利用率,装入内存的程序可换出到磁盘上,适当时候再换入到内存中,对换前后程序在内存中的位置可能不同,即允许进程的内存映像在不同时候处于不同位置,此时模块内使用的地址必为相对地址
    • 可执行程序逻辑地址转换 (绑定)为物理地址的过程称地址重定位 、地址映射或地址转换,基于上述程序装载方式,可区分三种地址重定位
      • 静态地址重定位
      • 动态地址重定位
      • 运行时链接地址重定位
    • 存储保护:防止地址越界和控制正确存取
      • 各道程序只能访问自己的内存区而不能互相干扰,必须对内存中的程序和数据进行保护,以免受到其他程序有意或无意的破坏。可对进程执行时所产生的所有内存访问地址进行检查,确保进程仅访问它自己的内存区,这就是地址越界保护,越界保护依赖于硬件设施,常用的有:界地址和存储键
      • 进程访问分配给自己的内存区时,要对访问权限进行检查,如允许读、写、执行等,从而确保数据的安全性和完整性,防止有意或无意的误操作而破坏内存信息,这就是信息存取保护

    2 连续存储管理

    固定分区存储管理:

    • 基本思想:内存空间被划分成数目固定不变的分区,各分区大小不等,每个分区只装入一个作业,若多个分区中都装有作业,则它们可以并发执行,这是支持多道程序设计最简单的存储管理技术
    • 数据结构:
      • 一张内存分配表:指出各分区起始地址和长度,占有标志用来指示此分区是否被使用
    • 排队策略:
      • 一是每个分区有单独的作业等待队列,调度程序选中作业后,创建用户进程并将其排入一个能装入它的最小分区等待队列尾部,当分区空闲时,装入队首进程执行
      • 二是所有等待处理的作业排成一个等待队列,每当有分区空闲时,就从队首依次搜索分区长度所能容纳的作业以便装入执行
    • 优点:解决单道程序运行在并发环境不能与CPU速度匹配的问题
    • 缺点:
      •  由于预先已规定分区大小,大作业无法装入,用户不得不采用覆盖技术加以补救,加重用户负担,极不方便
      • 内存空间利用率不高,作业很少会填满分区
      • 无法动态扩充运行中进程的内存空间
      • 分区数目确定,限制多道程序的道数

    可变分区存储管理:

    • 按作业的实际大小来划分分区,且分区个数随机,实现多个作业对内存的共享,进一步提高内存资源利用率
    • 内存分配表可由两张表组成:
      • 已分配区表
      • 未分配区表
    • 分配算法:
      • 最先适应:
      • 下次适应:从为分配区的上次扫描结束处顺序查找
      • 最优适应:扫描整个未分配分区,挑选最小分区进行分配
      • 最坏适应:挑选最大的
      • 快速适应:为经常用到的长度的空闲区设置独立的空闲区链表
    • 地址转换与存储保护:
      • 固定分区采用静态地址重定位,进程使用绝对地址,由加载程序进行地址越界检查
      • 可变分区采用动态地址重定位,硬件设置两个专用控制寄存器:基址寄存器和限长寄存器(进程占有的连续空间的长度)
    • 内存不足的存储管理技术:
      • 移动技术
      • 对换技术:将阻塞的进程暂时移除内存,腾出空间
        • 把时间片耗尽或优先级较低的进程换出,因为短时间内它们不会被投入运行
        • 数据区和堆栈是进程运行时创建和修改的,可通过文件系统把这些可变信息作为特殊文件移出
        • 批处理系统中,当有进程要求动态扩充内存且得不到满足时可触发对换;分时系统中,对换可与调度结合在一起,每个时间片结束或执行I/O操作时实施
      • 覆盖技术:程序运行过程中程序的不同模块在内存中相互替代,以达到最小内存执行最大程序的目的
        • 实现技术:把用户空间分成固定区和一个或多个覆盖区,把控制或不可覆盖部分放在固定区,其余按调用结构及先后关系分段并保存在磁盘上,运行时依次调入覆盖区

    产生碎片,移动开销大

    3 分页存储管理

    优点:允许将程序存放在不相邻的空闲块中,即可免除移动信息工作,又可充分利用内存空间,消除动态分区中的碎片问题,提供内存利用率

    基本原理:

    • 页面:进程逻辑地址划分为大小相等的区,每个区称为页面或页
    • 页框:把内存物理空间划分为大小相等的区,大小与与页面大小相等
    • 逻辑地址:页号+页内位移
    • 内存页框表:长度取决于内存划分的物理块数
    • 页表:操作系统为进程建立的,是程序页面与内存页框的对照表
      • 页表基址寄存器:存放页表起始地址,整个系统只有一个

    快表

    • 在硬件中设置相联寄存器,提供运算速度
    • 相联寄存器:存放进程最近访问的部分页表项,也称翻译快表

    分配和去配:

    • 位示图:a、b
    • 链表方法:c
    • 分配算法:
      • 进行内存分配时,先查找空闲块能不能满足用户进程的需求,若不能则令进程等待;若能则查找位示图,找出0的那些位,占用标志,从空闲块中减去本次占用块数,按所找到的位的位置计算对应页框号,填入此进程的页表。进程执行结束归还内存,根据页框号计算出对应位在位示图的位置,将占有标志清零,并将归还快熟加入空闲块数中

    页面共享和保护:

    • 程序共享--由于指令包含指向其他指令或数据的地址,进程依赖于这些地址才能执行,不同进程中正确执行共享代码页面,必须为它们在所有逻辑地址空间中指定同样页号
    • 实现信息共享必须解决共享信息保护问题。通常的做法是在页表中增加标志位,指出此页的信息只读/读写/只可执行/不可访问等,进程访问此页时核对访问模式。例如,欲向只读块写入信息则指令停止执行,产生违例异常信号

    多级页表:

    • 系统为每个进程建一张页目录表,它的每个表项对应一个页表页,而页表页的每个表项给出了页面和页框的对应关系,页目录表是一级页表,页表页是二级页表
    • 逻辑地址结构有三部分组成:页目录、页表页和位移
    • 解决页表页占用内存空间的问题:
      • 进程运行涉及页面的页表页应放在内存,其他页表页使用时再调入,
      • 在页目录表中增加特征位,指示对应的页表页是否已调入内存,
      • 地址转换机构根据逻辑地址中的dir,去查页目录表对应表项,如未调入,应产生一个”缺页表页”中断信号,请求操作系统将页表页调入内存
    • 多级页表结果本质:
      • 多级不连续,导致多级索引
      • 以二级页表为例,用户程序的页面不连续存放,要有页面地址索引,该索引是进程页表;进程页表又是不连续存放的多个页表页,故页表页也要页表页地址索引,该索引就是页目录
      • 页目录项是页表页的索引,而页表页项是进程程序的页面索引

    反置页表:

    • 为内存中的每一个物理块建立一个页表并按照块号排序
    • 该表每个表项包含正在访问该页框的进程标识、页号及特征位,用来完成内存页框到访问进程的页号、即物理地址到逻辑地址的转换
    • 逻辑地址给出进程标识和页号,用它们去比较IPT,若整个反置页表中未能找到匹配的页表项,说明该页不在内存,产生请页中断,请求操作系统调入;否则,该表项的序号便是页框号,块号加上位移,便形成物理地址

    4 分段存储

    主要目的:满足用户编程和使用上的要求

    基于可变分区存储管理原理

    基本原理:

    • 两维逻辑地址:段号+段内地址

    管理共享和保护:

    • 多对基址/限长寄存器 
    • 段的共享,是通过不同作业段表中的项指向同一个段基址来实现
    • 几道作业共享的例行程序就可放在一个段中,只要让各道作业的共享部分有相同的基址/限长值
    • 对共享段的信息必须进行保护,保护位用来对共享段实施保护,如禁写、禁修改等

    分段和分页的比较:

    • 分段是信息的逻辑单位,由源程序的逻辑结构所决定,用户可见,
    • 段长可根据用户需要来规定,段起始地址可从任何内存地址开始。
    • 分段方式中,源程序(段号,段内位移)经连结装配后地址仍保持二维结构。 

    分段和分页的比较:

    • 分页是信息的物理单位,与源程序的逻辑结构无关,用户不可见,
    • 页长由系统确定,页面只能以页大小的整倍数地址开始。
    • 分页方式中,源程序(页号,页内位移)经连结装配后地址变成了一维结构

    5 虚拟存储管理

    定义:在具有层次结构存储器的计算机系统中,采用自动实现部分装入和部分对换功能,为用户提供一个比物理内存容量大得多的,可寻址的一种“内存储器”

    程序局部性原理:指程序在执行过程中的一个较短时间内,所执行的指令地址或操作数地址分别局限于一定的存储区域中。又可细分时间局部性和空间局部性

    • 第一,程序中只有少量分支和过程调用,大都是顺序执行的指令;
    • 第二,程序含有若干循环结构,由少量代码组成,而被多次执行;
    • 第三,过程调用的深度限制在小范围内,因而,指令引用通常被局限在少量过程中;
    • 第四,涉及数组、记录之类的数据结构,对它们的连续引用是对位置相邻的数据项的操作;
    • 第五,程序中有些部分彼此互斥,不是每次运行时都用到

    实现虚拟存储器必须解决的问题:

    • 内存外存统一管理问题、

    • 逻辑地址到物理地址的转换问题、

    • 部分装入和部分对换问题

    实现技术:

    • 请求分页虚拟存储管理
    • 请求段页式虚拟存储管理

    请求分页虚拟存储管理

    硬件支撑:内存管理单元MMU完成逻辑地址到物理地址的转换功能,它接受逻辑地址作为输入,物理地址作为输出,直接送到总线上,对内存单元进行寻址主要功能:

     

      • (1)管理硬件页表基址寄存器。

        (2)分解逻辑地址。

        (3)管理快表TLB。

        (4)访问页表。

        (5)发出缺页中断或越界中断,并将控制权交给内核存储管理处理。

        (6)设置和检查页表中各个特征位。

     缺页中断处理过程:

    • 步1 挂起请求缺页的进程;
    • 步2 根据页号查外页表,找到该页存放的磁盘物理地址;
    • 步3 查看内存是否有空闲页框,如有则找出一个,修改内存管理表和相应页表项内容,转步6;,
    • 步4 如内存中无空闲页框,按替换算法选择淘汰页面,检查它曾被写过或修改过吗?若未则转步6;若是则转步5;
    • 步5 该淘汰页面被写过或修改过,则把它的内容写回磁盘原先位置;
    • 步6 进行调页,把页面装入内存所分配的页框中,同时修改进程页表项;
    • 步7 返回进程断点,重新启动被中断的指令。

    请求分页虚存管理基本原理:

    • 分页式虚存不把作业信息(程序和数据)全部装入内存,仅装入立即使用的页面,在执行过程中访问到不在内存的页面时,产生缺页中断,再从磁盘动态地装入 
    • 扩充页表的内容,增加驻留标志位等信息,来发现页面是否在内存中。
    • 外页表:页面与磁盘物理地址的对应表,由操作系统管理,进程启动运行前系统为其建立外页表,并把进程程序页面装入外存。该表按进程页号的顺序排列,为节省内存,外页表可存放在磁盘中,当发生缺页中断需要查用时才被调入
    • 请求分页虚存地址转换过程:

     

    • 请求分页虚存系统优缺点:
      • 优点:作业的程序和数据可按页分散存放在内存中,减少移动开销,有效解决了碎片问题;既有利于改进内存利用率,又有利于多道程序运行
      • 缺点:要有硬件支持,要进行缺页中断处理,机器成本增加,系统开销加大
    • 页面装入内存策略:
      • 请页式调度
      • 预调式调度
    • 页面清除策略:
      • 请页式清除
      • 预清除

    页面分配策略:

    • 分配内存时需要考虑的因素:

      ①分给进程的空间越小,同一时间处于内存的进程就越多,至少有一个进程处于就绪态的可能性就越大

      ②如果进程只有小部分在内存里,即使局部性很好,缺页中断率还会相当

      ③因程序的局部性原理,分给进程的内存超过一定限度后,再增加内存空间,不会明显降低进程的缺页中断率。

    • 固定分配:
      • 进程保持页框数固定不变,称固定分配
      • 进程创建时,根据进程类型和程序员的要求决定页框数,只要有一个缺页中断产生,进程就会有一页被替换
    • 可变分配:
      • 进程分得的页框数可变, 称可变分配
      • 进程执行的某阶段缺页率较高,说明目前局部性较差,系统可多分些页框以降低缺页率,反之说明进程目前的局部性较好,可减少分给进程的页框数 

     页面替换策略:

    • 全局替换:如果页面替换算法的作用范围是整个系统,称全局页面替换算法,它可以在运行进程间动态地分配页框。
    • 局部替换:如果页面替换算法的作用范围局限于本进程,称为局部页面替换算法,它实际上需要为每个进程分配固定的页框

    固定分配与局部替换配合使用:

    • 进程分得的页框数不变,发生缺页中断,只能从进程的页面中选页替换,保证进程的页框总数不变
    • 系统把页框分配给进程:
      • 平均分配
      • 按比例分配
      • 优先权分配

    可变分配和全局替换配合使用:

    • 先每个进程分配一定数目页框,os保留若干空闲页框,进程发生缺页中断时,从系统空闲页框中选一个给进程,这样产生缺页中断进程的内存空间会逐渐增大,有助于减少系统的缺页中断次数
    • 系统拥有的空闲页框耗尽时 ,会从内存中选择一页淘汰,该页可以是内存中任一进程的页面,这样又会使那个进程的页框数减少,缺页中断率上升

    可变分配和局部替换配合使用:

    • 实现要点:
      • (1)新进程装入内存时,根据应用类型、程序要求,分配给一定数目页框,可用请页式或预调式完成这个分配。

        (2)产生缺页中断时,从该进程驻留集中选一个页面替换。

        (3)不时重新评价进程的分配,增加或减少分配给进程的页框以改善系统性能

    缺页中断率:

    • 影响缺页中断率的因素:
      • 内存页框数
      • 页面大小
      • 页面替换算法
      • 程序特性
    • 全局页面替换算法
      • 1) 最佳页面替换算法OPT

        • 调入一页而必须淘汰一个旧页时,所淘汰的页应该是以后不再访问的页或距现在最长时间后再访问的页
      • 2) 先进先出页面替换算法FIFO

        • 算法淘汰最先调入内存的页,或者说在内存中驻留时间最长的页
        • FIFO算法增加可用物理页框数量会导致更多的缺页异常
        • 页面缓冲算法:
          • •维护两个FIFO队列,修改页面队列和非修改(空闲)页面队列,前者是由修改页面的页框构成的链表;后者是由可直接用于装入页面的页框构成的链表,未修改的淘汰页暂时还留在其中,当进程再次访问这些页面时,可不经I/O而快速回。
          • 按FIFO选出淘汰页,并不立即抛弃它,根据它的内容是否被修改过进入两个队列之一的末尾,需要装入的页面被读进非修改队列的队首指向的页框中,不必等待淘汰页写回,使得进程能快速恢复运行
      • 3) 最近最少用页面替换算法LRU

        • 算法淘汰的页面是在最近一段时间里较久未被访问的那页
        • 根据程序局部性原理,那些刚被使用过的页面,可能马上还要被使用,而在较长时间里未被使用的页面,可能不会马上使用到
        • 算法实现:
          • 页面淘汰队列:
            •  队列中存放当前在内存中的页号,每当访问一页时就调整一次,使队列尾总指向最近访问的页,队列头就是最近最少用的页。
            • 发生缺页中断时总淘汰队列头所指示的页;执行一次页面访问后,需要从队列中把该页调整到队列尾
          • 引用位法最近未使用页面替换算法(Not Recently Used replacement,NRU) :
            • 每页设置一个引用位R,访问某页时,由硬件将页标志位R置1,隔一定时间t将所有页的标志R均清0。
            • 发生缺页中断时,从标志位R为0的页中挑选一页淘汰。挑选到要淘汰的页后,也将所有页的标志位R清0
          • 计数法:
            • 每个页面设置一个多位计数器,又叫最不常用页面替换算法LFU。每当访问一页时,就使它对应的计数器加1。
            • 当发生缺页中断时,可选择计数值最小的对应页面淘汰,并将所有计数器全部清0
          • 计时法:
            • 为每个页面设置一个多位计时器,每当页面被访问时,系统的绝对时间记入计时器。
            • 比较各页面的计时器的值,选最小值的未使用的页面淘汰,因为,它是最“老”的未使用的页面
          • 老化算法:
            • 为每个页设置一个多位寄存器r。当页面被访问时,对应寄存器的最左边位置1;每隔时间t,将r寄存器右移一位;在发生缺页中断时,找最小数值的r寄存器对应的页面淘汰
      • 4) 第二次机会页面替换算法SCR

        • 改进FIFO算法,把FIFO与页表中的”引用位”结合起来使用:

          • 检查FIFO中的队首页面(最早进入内存页面),如果它的”引用位”是0,这个页面既老又没有用,选择该页面淘汰;

          • 如果”引用位”是1,说明它进入内存较早,但最近仍在使用。把它的”引用位”清0,并把这个页面移到队尾,把它看作是一个新调入的页。

          • 算法含义:最先进入内存的页面,如果最近还在被使用的话,仍然有机会作为像一个新调入页面一样留在内存中

      • 5) 时钟页面替换算法Clock

        • 实现要点:
          • 一个页面首次装入内存,其“引用位”置1 。

          • 内存中的任何页面被访问时, ”引用位”置1。

          • 淘汰页面时,从指针当前指向的页面开始扫描循环队列,把迁到的”引用位”是1的页面的”引用位”清0,跳过这个页面; 把所迁到的”引用位”是0的页面淘汰掉,指针推进一步。

          • 扫描循环队列时,如果迁到的所有页面的”引用位”为1,指针就会绕整个循环队列一圈,把碰到的所有页面的”引用位”清0;指针停在起始位置,并淘汰掉这一页,然后,指针推进一步 

        •  改进算法:
          • 把”引用位”和”修改位”结合起来使用,共组合成四种情况: 
            • (1)最近没有被引用,没有被修改(r=0,m=0)

              (2)最近被引用,没有被修改(r=1,m=0)

              (3)最近没有被引用,但被修改(r=0,m=1)

              (4)最近被引用过,也被修改过(r=1,m=1)

          • 步1:选择最佳淘汰页面,从指针当前位置开始,扫描循环队列。扫描过程中不改变”引用位”,把迂到的第一个r=0,m=0的页面作为淘汰页面。
          • 步2:如果步1失败,再次从原位置开始,查找r=0且m=1的页面,把把迂到的第一个这样的页面作为淘汰页面,而在扫描过程中把指针所扫过的页面的”引用位”r置0
          • 步3:如果步2失败,指针再次回到了起始位置,由于此时所有页面的”引用位”r均己为0,再转向步1操作,必要时再做步2操作,这次一定可以挑出一个可淘汰的页面

    计算缺页中断次数和被淘汰页面:

    • 假设采用固定分配策略,进程分得三个页框,执行中按下列次序引用5个独立的页面:     2  3  2  1  5  2  4  5  3  2  5  2。
    •  

     局部页面替换算法

    • 1) 局部最佳页面替换算法

      • 实现思想:进程在时刻t访问某页面,如果该页面不在内存中,导致一次缺页,把该页面装入一个空闲页框。
      • 不论发生缺页与否,算法在每一步要考虑引用串,如果该页面在时间间隔(t,t+τ)内未被再次引用,那么就移出;否则,该页被保留在进程驻留集中。
      • τ为一个系统常量,间隔(t,t+τ)称作滑动窗口
      •  实现思想:进程在时刻t访问某页面,如果该页面不在内存中,导致一次缺页,把该页面装入一个空闲页框。
      • 不论发生缺页与否,算法在每一步要考虑引用串,如果该页面在时间间隔(t,t+τ)内未被再次引用,那么就移出;否则,该页被保留在进程驻留集中。 τ为一个系统常量,间隔(t,t+τ)称作滑动窗口  
    • 2) 工作集模型和工作集置换算法

      • 进程工作集指“在某一段时间间隔内进程运行所需访问的页面集合”
        • 指“在某一段时间间隔内进程运行所需访问的页面集合”,W(t,Δ)表示在时刻t-Δ到时刻t之间( (t-Δ,t))所访问的页面集合,进程在时刻t的工作集。
        • Δ是系统定义的一个常量。变量Δ称为“工作集窗口尺寸”,可通过窗口来观察进程行为,还把工作集中所包含的页面数目称为“工作集尺寸”
      • 实现思想:工作集模型用来对局部最佳页面替换算法进行模拟实现,不向前查看页面引用串,而是基于程序局部性原理向后看。
      • 任何给定时刻,进程不久的将来所需内存页框数,可通过考查其过去最近的时间内的内存需求做出估计
      • 通过工作集确定驻留集大小
        • (1)监视每个进程的工作集,只有属于工作集的页面才能留在内存;
        • (2)定期地从进程驻留集中删去那些不在工作集中的页面;
        • (3)仅当一个进程的工作集在内存时,进程才能执行。 
    • 3) 模拟工作集替换算法

      • 时间戳算法:
        • 为页面设置引用位及关联时间戳,通过超时中断,至少每隔若干条指令周期性地检查引用位及时间戳:

        • 当引用位为1时,就把它置0,并把这次改变的时间作为时间戳记录下来。
        • 当引用位为0时,系统当前时间减去时间戳时间,计算出从它上次使用以来未被再次访问的时间量,记入t_off
        • t_off值随着每次超时中断的处理而不断增加,除非页面在此期间被再次引用,导致其使用位为1;
        • 把t_off与系统时间参数t_max相比,若t_off>t_max,就把页面从工作集中移出,释放相应页框
    • 4) 缺页频率替换算法

      • 根据连续的缺页之间的时间间隔来对缺页频率进行测量,每次缺页时,利用测量时间调整进程工作集尺寸
      • 规则:如果本次缺页与前次缺页之间的时间超过临界值τ,那么,所有在这个时间间隔内没有引用的页面都被移出工作集

    请求分页虚存管理的几个设计问题:

    •  页面大小
      • 从页表大小考虑
      • 从内存利用率考虑
      • 从读写一个页面所需的时间考虑
      • 最佳页面尺寸
      • 页面长度是由CPU中的MMU规定的,操作系统通过特定寄存器的指示位来指定当前选用的页面长度
    •  

     页面交换区:

    • 替换算法要挑选页面淘汰出内存,但被淘汰出去的页面可能很快使用,又要被重新装入内存。操作系统必须保存被淘汰的页面,
    • 需要建立和维护交换区映射表,记录所有被换出的页面在交换区中的位置。如果页面要被换出内存,仅当其内容与保存在交换区的副本不同时才进行复制。交换区最常用的数据结构是进程页面号与盘块号的对照表,称磁盘外页表

    写时复制:

    • 是存储管理节省物理内存(页框)的一种页面级优化技术,已被Linux等采用,能减少内存页面内容的复制操作,减少相同内容页面在内存的副本数目

    请求段页式虚存管理

    • 段式存储是基于用户程序结构的存储管理技术,有利于模块化程序设计,便于段的扩充、动态链接、共享和保护,但会生成段内碎片浪费存储空间 
    • 页式存储是基于系统存储器结构的存储管理技术, 存储利用率高,便于系统管理,但不易实现存储共享、保护和动态扩充 
    • 基本原理:
      • 1、虚地址以程序的逻辑结构划分成段(段页式存储管理的段式特征)

        2、实地址划分成位置固定、大小相等的页框(段页式存储管理的页式特征)

        3、将每一段的线性地址空间划分成与页框大小相等的页面,于是形成了段页式存储管理特征。

        4、逻辑地址形式为:

    • 数据结构:
      • 作业表:登记进入系统中的所有作业及该作业段表的起始地址,
      • 段表:包含这个段是否在内存,以及该段页表的起始地址等,
      • 页表:包含该页是否在内存(中断位)、对应内存块号
    • 请求段页式虚存管理动态地址转换
      • 从逻辑地址出发,先以段号s和页号p作索引去查快表,如果找到,那么立即获得页p的页框号p’,并与位移d一起拼装得到访问内存的实地址,从而完成了地址转换
      • 若查快表失败,就要通过段表和页表作地址转换了,用段号s作索引,找到相应表目,由此得到s段的页表起址s’,再以p作索引得到s段p页对应的表目,得到页框号p’;这时一方面把s段p页和页框号p’置换进快表,另一方面用p’和d生成内存实地址,从而完成地址转换
      • 如查段表时,发现s段不在内存,产生“缺段中断”,引起系统查找s段在外存的位置,将该段页表调入内存;
      • 如查页表时,发现s段的p页不在内存,产生“缺页中断”,引起系统查找s段p页在外存的位置,并将该页调入内存,当内存已无空闲页框时,就会导致淘汰页面
      •  
    •  
    展开全文
  • radosgw-admin4j 是一 Ceph 对象存储管理客户端,允许配置和控制 Ceph 对象存储部署。 功能包括用户/子用户管理、配额管理、使用报告、存储桶/对象管理等。 强调 在最新 Ceph 版本中完全支持所有包括subuser 、 ...
  • Nging V3 注意:这是Nging V3源代码,旧版V2.x,V1.x已经...本软件项目不完全实现了一些网站服务工具,本身还是一具有很好扩展性通用网站后台管理系统,通过本项目,您可以很轻松构建一全新网站项目,省去
  • 存储管理 存储管理的主要模式 逻辑地址 逻辑地址:又称相对地址,即用户编程所使用的地址空间 逻辑地址从0开始编号,有两种...这一技术是程序设计技术,不是OS存储管理的功能 物理地址 物理地址:又称绝对地...

    存储管理的主要模式

    逻辑地址
    • 逻辑地址:又称相对地址,即用户编程所使用的地址空间
    • 逻辑地址从0开始编号,有两种形式:
      • 一维逻辑地址(地址)
      • 二维逻辑地址(段号:段内地址)
    段式程序设计
    • 把一个程序设计成多个段
      • 代码段、数据段、堆栈段等等
    • 用户可以自己应用段覆盖技术扩充内存空间使用量
      • 这一技术是程序设计技术,不是OS存储管理的功能
    物理地址
    • 物理地址:又称绝对地址,即程序执行所使用的地址空间
    • 处理器执行指令时按照物理地址进行
    主存储器的复用
    • 多道程序设计需要复用主存
    • 按照分区复用:
      • 主存划分为多个固定/可变尺寸的分区
      • 一个程序/程序段占用一个分区
    • 按照页架复用:
      • 主存划分为多个固定大小的页架
      • 一个程序/程序段占用多个页架
    存储管理的基本模式
    • 单连续存储管理:一维逻辑地址空间的程序占用一个主存固定分区或可变分区
    • 段式存储管理:段式二维逻辑地址空间的程序占用多个主存可变分区
    • 页式存储管理:一维逻辑地址空间的程序占用多个主存页架区
    • 段页式存储管理:段式二维逻辑地址空间的程序占用多个主存页架区

    存储管理的功能

    地址转换
    • 地址转换:又称重定位,即把逻辑地址转换成绝对地址
    • 静态重定位:在程序装入内存时进行地址转换
      • 由装入程序执行,早期小型OS使用
    • 动态重定位:在CPU执行程序时进行地址转换
      • 从效率出发,依赖硬件地址转换机构
    主存储器空间的分配与去配
    • 分配:进程装入主存时,存储管理软件进行具体的主存分配操作,并设置一个表格记录主存的分配情况
    • 去配:当某个进程撤离或主动归还主存资源时,存储管理软件要收回它所占用的全部或者部分存储空间,调整主存分配表的信息
    主存储器空间的共享
    • 多个进程共享主存储器资源:多道程序设计技术使若干个程序同时进入主存储器,各自占用一定数量的存储空间,共同使用一个主存储器
    • 多个进程共享主存储器的某些区域:若干个协作进程有共同的主存程序块或者主存数据块
    存储保护
    • 为避免主存中的多个进程相互干扰,必须对主存中的程序和数据进行保护
      • 私有主存区中的信息:可读可写
      • 公共区中的共享信息:根据授权
      • 非本进程信息:不可读写
    • 这一功能需要软硬件协同完成
      • CPU检查是否允许访问,不允许则产生地址保护异常,由OS进行相应处理
    主存储器空间的扩充
    • 存储扩充:把磁盘作为主存扩充,只把部分进程或进程的部分内容装入内存
      1. 对换技术:把部分不运行的进程调出
      2. 虚拟技术:只调入进程的部分内容
    • 这一工作需要软硬件协作完成
      1. 对换进程决定对换,硬件机构调入
      2. CPU处理到不存在的地址,发出虚拟地址异常,OS将其调入,重执指令

    虚拟存储器的概念

    • 主存容量限制带来诸多不便
      • 用户编写程序必须考虑主存容量限制
      • 多道程序设计的道数受到限制
    • 用户编程行为分析
      • 全面考虑各种情况,执行时有互斥性
      • 顺序性和循环性等空间局部性行为
      • 某一阶段执行的时间局部性行为
    • 因此可以考虑部分调入进程内容
    虚拟存储器的基本思想
    • 存储管理把进程全部信息放在辅存中,执行时先将其中一部分装入主存,以后根据执行行为随用随调入
    • 如主存中没有足够的空闲空间,存储管理需要根据执行行为把主存中暂时不用的信息调出到辅存上去
    虚拟存储器的实现思路
    • 需要建立与自动管理两个地址空间
      • (辅存)虚拟地址空间:容纳进程装入
      • (主存)实际地址空间:承载进程执行
    • 对于用户,计算机系统具有一个容量大得多的主存空间,即虚拟存储器
    • 虚拟存储器是一种地址空间扩展技术,通常意义上对用户编程是透明的,除非用户需要进行高性能的程序设计

    存储管理的硬件支撑

    存储管理涉及的存储对象
    • 存储管理是OS管理主存储器的软件部分
    • 为获得更好的处理性能,部分主存程序与数据(特别是关键性能数据)被调入Cache,存储管理需要对其进行管理,甚至包括对联想存储器的管理
    • 为获得更大的虚拟地址空间,存储管理需要对存放在硬盘、固态硬盘、甚至网络硬盘上的虚拟存储器文件进行管理
    高速缓存存储器(Cache)
    • Cache是介于CPU和主存储器间的高速小容量存储器,由静态存储芯片SRAM组成,容量较小但比主存DRAM技术更加昂贵而快速,接近于CPU的速度
    • CPU往往需要重复读取同样的数据块,Cache的引入与缓存容量的增大,可以大幅提升CPU内部读取数据的命中率,从而提高系统性能
    高速缓存存储器的构成
    • 高速缓冲存储器通常由高速存储器、联想存储器、地址转换部件、替换逻辑等组成
    • 联想存储器:根据内容进行寻址的存储器
    • 地址转换部件:通过联想存储器建立目录表以实现快速地址转换。命中时直接访问Cache;未命中时从内存读取放入Cache
    • 替换部件:在缓存已满时按一定策略进行数据块替换,并修改地址转换部件
    高速缓存存储器的分级
    • L1 Cache:分为数据缓存和指令缓存;内置;其成本最高,对CPU的性能影响最大;通常在32KB - 256KB之间
    • L2 Cache:分内置和外置两种,后者性能低一些;通常在512KB - 8MB之间
    • L3 Cache:多为外置,在游戏和服务器领域有效;但对很多应用来说,总线改善比设置L3更加有利于提升系统性能
    存储管理与硬件支撑
    • 鉴于程序执行与数据访问的局部性原理,存储管理软件使用Cache可以大幅度提升程序执行效率
    • 动态重定位、存储保护等,若无硬件支撑在效率上是无意义的,即无实现价值
    • 无虚拟地址中断,虚拟存储器无法实现
    • 无页面替换等硬件支撑机制,虚拟存储器在效率上是无意义的

    单连续分区存储管理

    单连续分区存储管理
    • 每个进程占用一个物理上完全连续的存储空间(区域)
    • 单用户连续分区存储管理
    • 固定分区存储管理
    • 可变分区存储管理
    单用户连续分区存储管理
    • 适用于单用户单任务操作系统,如DOS
    • 主存区域划分为系统区与用户区
    • 设置一个栅栏寄存器界分两个区域,硬件用它在执行时进行存储保护
    • 一般采用静态重定位进行地址转换
      • 静态重定位:在装入一个作业时,把该作业中程序的指令地址和数据地址全部转换成绝对地址
    • 硬件实现代价低
    固定分区存储管理的基本思想
    • 支持多个分区
    • 分区数量固定
    • 分区大小固定
    • 可用静态/动态重定位
    • 硬件实现代价低
    • 早期OS采用
    可变分区存储管理概述
    • 固定分区存储管理不够灵活,既不适应大尺寸程序,又存在内存内零头,有浪费
    • 能否按照进程实际内存需求动态划分分区,并允许分区个数可变
    • 这就是可变分区存储管理

    可变分区存储管理

    • 按进程的内存需求来动态划分分区
    • 创建一个进程时,根据进程所需主存量查看主存中是否有足够的连续空闲空间
      • 若有,则按需要量分割一个分区
      • 若无,则令该进程等待主存资源
    • 由于分区大小按照进程实际需要量来确定,因此分区个数是随机变化的
    可变分区方式的内存分配
    • 最先适应分配算法
    • 邻近适应分配算法
    • 最优适应分配算法
    • 最坏适应分配算法
    可变分区方式的内存零头
    • 固定分区方式会产生内存内零头
    • 可变分区方式也会随着进程的内存分配产生一些小的不可用的内存分区,称为内存外零头
    • 最优适配算法最容易产生外零头
    • 任何适配算法都不能避免产生外零头
    移动技术(程序浮动技术)
    • 移动分区以解决内存外零头
    • 需要动态重定位支撑

    在这里插入图片描述

    页式存储管理的基本原理

    • 分页存储器将主存划分成多个大小相等的页架
    • 受页架尺寸限制,程序的逻辑地址也自然分成页
    • 不同的页可以放在不同页架中,不需要连续
    • 页表用于维系进程的主存完整性
    页式存储管理的地址
    • 页式存储管理的逻辑地址由两部分组成,页号和单元号,逻辑地址形式:页号+单元号
    • 页式存储管理的物理地址也有两部分组成,页架号和单元号,物理地址形式:页架号+单元号
    页的共享
    • 页式存储管理能够实现多个进程共享程序和数据
    • 数据共享:不同进程可以使用不同页号共享数据页
    • 程序共享:不同进程必须使用相同页号共享代码页
      • 共享代码页中的(JMP<页内地址>)指令,使用不同页号是做不到

    页式存储管理的地址转换

    页式存储管理的地址转换代价
    • 页表放在主存:每次地址转换必须访问两次主存
      1. 按页号读出页表中的相应页架号
      2. 按计算出来的绝对地址进行读写
    • 存在问题:降低了存取速度
    • 解决办法:利用Cache存放部分页表
    页式存储管理的快表
    • 为提高地址转换速度,设置一个专用的高速存储器,用来存放页表的一部分
    • 快表:存放在高速存储器中的页表部分
    • 快表表项:页号,页架号
    • 这种高速存储器是联想存储器,即按照内容寻址,而非按照地址访问
    基于快表的地址转换流程
    • 按逻辑地址中的页号查快表
    • 若该页已在快表中,则由页架号和单元号形成绝对地址
    • 若该页不在快表中,则再查主存页表形成绝对地址,同时将该页登记到快表中
    • 当快表填满后,又要登记新页时,则需在快表中按一定策略淘汰一个旧登记项
    多道程序环境下的进程表
    • 进程表中登记了每个进程的页表
    • 进程占有处理器运行时,其页表起始地址和长度送入页表控制寄存器

    页式虚拟存储管理

    页式虚拟存储管理的基本思想
    • 把进程全部页面装入虚拟存储器,执行时先把部分页面装入实际内存,然后,根据执行行为,动态调入不在主存的页,同时进行必要的页面调出
    • 现代OS的主流存储管理技术
    • 首次只把进程第一页信息装入主存,称为请求页式存储管理
    页式虚拟存储管理的页表
    • 需要扩充页表项,指出:
      • 每页的虚拟地址、实际地址
      • 主存驻留标志、写回标志、保护标志、引用标志、可移动标志
    页式虚拟存储管理的实现
    • CPU处理地址
      • 若页驻留,则获得块号形成绝对地址
      • 若页不在内存,则CPU发出缺页中断
    • OS处理缺页中断
      • 若有空闲页架,则根据辅存地址调入页,更新页表与快表等
      • 若无空闲页架,则决定淘汰页,调出已修改页,调入页,更新页表与快表

    页面调度

    • 当主存空间已满而又需要装入新页时,页式虚拟存储管理必须按照一定的算法把已在主存的一些页调出去
    • 选择淘汰页的工作称为页面调度
    • 选择淘汰页的算法称为页面调度算法
    • 页面调度算法如果设计不当,会出现(刚被淘汰的页面立即又要调入,并如此反复)
    • 这种现象称为抖动颠簸

    反置页表

    反置页表的提出
    • 页表及相关硬件机制在地址转换、存储保护、虚拟地址访问中发挥了关键作用
    • 为页式存储管理设置专门硬件机构
    • 内存管理单元MMU:CPU管理虚拟/物理存储器的控制线路,把虚拟地址映射为物理地址,并提供存储保护,必要时确定淘汰页面
    • 反置页表IPT:MMU用的数据结构
    反置页表的基本设计思想
    • 针对内存中的每个页架建立一个页表,按照块号排序
    • 表项包含:正在访问该页架的进程标识、页号及特征位,和哈希链指针等
    • 用来完成内存页架到访问进程页号的对应,即物理地址到逻辑地址的转换
    反置页表的页表项
    • 页号:虚拟地址页号
    • 进程标志符:使用该页的进程号(页号和进程标志符结合起来标志一个特定进程的虚拟地址空间的一页)
    • 标志位:有效、引用、修改、保护和锁定等标志信息
    • 链指针:哈希链
    基于反置页表的地址转换过程
    • MMU通过哈希表把进程标识和虚页号转换成一个哈希值,指向IPT的一个表目
    • MMU遍历哈希链找到所需进程的虚页号,该项的索引就是页架号,通过拼接位移便可生成物理地址
    • 若遍历整个反置页表中未能找到匹配页表项,说明该页不在内存,产生缺页中断,请求操作系统调入

    段式存储管理

    • 每个程序可由若干段组成,每一段都可以从“0”开始编址,段内的地址是连续的
    • 分段存储器的逻辑地址由两部分组成 段号:单元号
    段式存储管理的基本思想
    • 段式存储管理基于可变分区存储管理实现,一个进程要占用多个分区
    • 硬件需要增加一组用户可见的段地址寄存器(代码段、数据段、堆栈段、附加段),供地址转换使用
    • 存储管理需要增加设置一个段表,每个段占用一个段表项,包括:段始址、段限长,以及存储保护、可移动、可扩充等标志位
    段的共享
    • 通过不同进程段表中的项指向同一个段基址来实现
    • 对共享段的信息必须进行保护,如规定只能读出不能写入,不满足保护条件则产生保护中断

    段式虚拟存储管理

    段式虚拟存储管理的基本思想
    • 把进程的所有分段都存放在辅存中,进程运行时先把当前需要的一段或几段装入主存,在执行过程中访问到不在主存的段时再把它们动态装入
    • 段式虚拟存储管理中段的调进调出是由OS自动实现的,对用户透明
    • 与段覆盖技术不同,它是用户控制的主存扩充技术,OS不感知

    段页式存储管理

    段页式存储管理的基本思想
    • 段式存储管理可以基于页式存储管理实现
    • 每一段不必占据连续的存储空间,可存放在不连续的主存页架中
    • 能够扩充为段页式虚拟存储管理
    • 装入部分段,或者装入段中部分页面

    2019 ZhiZDK 如转载请声明。

    展开全文
  • 2、内存管理的功能功能1:内存空间的分配与回收方法1:单一连续分配方法2:固定分区分配方法3:动态分区分配1、什么是动态分区分配?2、系统用什么样的数据结构记录内存使用情况?3、当很多空闲分区都能满足需求时...


    看几个问题

    在这里插入图片描述在这里插入图片描述

    功能1:内存空间的分配与回收

    在这里插入图片描述

    连续分配管理:

    方法1:单一连续分配

    在这里插入图片描述

    方法2:固定分区分配

    在这里插入图片描述
    问题:如何对每一块分区进行记录呢?
    在这里插入图片描述

    方法3:动态分区分配

    1、什么是动态分区分配?

    在这里插入图片描述
    一个接一个的放入。

    2、系统用什么样的数据结构记录内存使用情况?

    在这里插入图片描述

    3、当很多个空闲分区都能满足需求时,应该选择哪个分区进行分配?(首次适应、最佳适应、最坏适应、临近适应)

    在这里插入图片描述

    4、如何进行分区的分配与回收操作?

    能合并就合并

    5、如何解决动态分区分配碎片化问题?

    采用“拼凑”技术,就是将使用的存储空间拼接到一起,闲散的存储空间拼接到一起。例如现在内存中有互不相邻的三块空间:1K,3K,5K;现在有一个7K的程序要运行,但是由于内存空间不连续而无法运行,此时就需要将三块空间拼接。

    非连续分配管理方式

    见下篇:
    操作系统之内存管理:3、基本分页存储管理

    功能2:内存空间的扩充

    方法1、覆盖技术

    在这里插入图片描述

    在这里插入图片描述

    看上图:
    假设现在B、C不能同时放入内存,D、E、F不能同时放入内存;
    所以:
    可以将A放入固定区;(8K)
    将B、C设置一个覆盖区用于存放B、C(只需10K)
    将D、E、F设置一个覆盖区用于存放D、E、F(只需12K)
    从而从逻辑上达到内存扩充的目的,以淘汰

    方法2、交换技术

    在这里插入图片描述

    方法3、虚拟存储技术

    功能3:地址转化

    方法1、绝对装入

    在这里插入图片描述

    方法2、可重定位装入

    在这里插入图片描述

    装入后可执行文件中的地址都被修改为了物理地址,地址变换在装入时一次性完成

    方法3、动态重定位

    在这里插入图片描述

    在装入后通过重定位寄存器和逻辑地址计算数据存放地址,即使程序移动后,也可以通过再次计算得到新的物理地址

    功能4:存储保护

    方法1:上下限寄存器法

    在这里插入图片描述

    用物理地址设置俩个上下界寄存器,CPU访问存储单元时判断是否在上下界寄存器地址范围内

    方法2:重定位寄存器(基址寄存器)和界地址寄存器法(限长寄存器)

    在这里插入图片描述

    重定位寄存器:存放起始物理地址
    界地址寄存器:存放最大逻辑地址
    此时,CPU想要访问逻辑地址80,首先要与界地址寄存器比较判断是否越界,未越界则访问物理地址:80+100=180.

    展开全文
  • POI实现图书馆管理系统数据存储目的:通过这系统POI操作Excel表,实现了对其数据增、删、改、查功能系统功能描述:备注: ①各项功能的详细操作流程参见压缩文件中视频,项目效果演示。 1:增加图书 添加一...

    POI实现图书馆管理系统的数据存储

    目的:通过这个系统POI操作Excel表,实现了对其数据的增、删、改、查功能

    系统功能描述:

    备注:     ①各项功能的详细操作流程参见压缩文件中视频,项目效果演示。

             1:增加图书

                       添加一个图数信息(图书编号、名称、价格、类别、简介)

             2:删除图书

    允许管理员输入要删除的图书编号,然后完成图书的删除

             3:修改图书信息

                       允许管理员输入要修改的部门的编号,然后输入该图书修改后的新名称、新价格、新类别、新简介。最后完成修改

             4:查看所有图书信息

                       展示该系统中所有图书信息。

             5:根据价格区间查找图书

    管理员输入,最小价格,和最大价格,然后展示所有图书价格处于这个之间的所有图书信息。

             6:根据类别查找图书

    管理员输入类别名称,然后展示该类别的所有图书。

    1、主函数

    public class Library_main {
    	public static void main(String[] args) {
    		// 将数据存入excle表格中
    		Library a = new Library();
    		Scanner sc = new Scanner(System.in);
    		while (true) {
    			show();
    			System.out.println("输入您的选项:");
    			int i = sc.nextInt();
    			switch (i) {
    			case 1:
    				System.out.println("请输入书的编号:");
    				Integer id = sc.nextInt();
    				System.out.println("请输入书的名称:");
    				String name = sc.next();
    				System.out.println("请输入书的价格:");
    				Double price = sc.nextDouble();
    				System.out.println("请输入书的类别:");
    				String cla = sc.next();
    				System.out.println("请输入书的简介:");
    				String produce = sc.next();
    				Book book = new Book();
    				book.setBook_id(id);
    				book.setBook_title(name);
    				book.setBook_price(price);
    				book.setBook_produce(produce);
    				book.setBook_class(cla);
    				a.addBook(book);
    				break;
    			case 2:
    				System.out.println("请输入书的编号:");
    				Integer id1 = sc.nextInt();
    				a.removeBook(id1);
    				break;
    			case 3:
    				System.out.println("请输入要更新的书的编号:");
    				Integer id2 = sc.nextInt();
    				System.out.println("请输入编号为" + id2 + "的书的新的名字:");
    				String name2 = sc.next();
    				System.out.println("请输入编号为" + id2 + "的书的新的价格:");
    				Double price2 = sc.nextDouble();
    				System.out.println("请输入编号为" + id2 + "的书的新的类别:");
    				String class2 = sc.next();
    				System.out.println("请输入编号为" + id2 + "的书的新的简介:");
    				String product2 = sc.next();
    				a.updateBook(id2, name2, price2, class2, product2);
    				break;
    			case 4:
    				List<Book> li = a.getAllBooks();
    				for (Book book2 : li) {
    					System.out.println(book2);
    				}
    				break;
    			case 5:
    				System.out.println("输入最低价格:");
    				Double minPrice = sc.nextDouble();
    				System.out.println("输入最高价格:");
    				Double maxPrice = sc.nextDouble();
    				List<Book> li1 = a.getBooksByPriceRange(minPrice, maxPrice);
    				for (Book book2 : li1) {
    					System.out.println(book2);
    				}
    				break;
    			case 6:
    				System.out.println("请输入类别查找图书:");
    				String category = sc.next();
    				List<Book> li2 = a.getBooksByCategory(category);
    				for (Book book2 : li2) {
    					System.out.println(book2);
    				}
    				break;
    			case 7:
    				System.exit(0);
    			}
    		}
    	}
    
    	public static void show() {
    		System.out.println("1、添加一个图书信息(图书编号、名称、价格、类别、简介):");
    		System.out.println("2、根据编号删除图书:");
    		System.out.println("3、修改图书信息:");
    		System.out.println("4、查看所有图书信息:");
    		System.out.println("5、根据价格区间查找图书:");
    		System.out.println("6、根据类别查找图书:");
    		System.out.println("7、退出系统");
    	}
    }

    2、接口

    package com.baizhi.test.project;
    
    import java.util.List;
    
    /**
     * 图书管理系统功能标准(接口) 作者:sqc 时间:2018-4-3 下午21:43:41 描述:TODO
     */
    public interface LibrarySystem {
    	/**
    	 * 描述:TODO 将参数book对象添加到数据仓库类中
    	 */
    	public void addBook(Book book);
    	/**
    	 * 描述:TODO 根据参数bookId在数据仓库中找到对应的图书,然后删除。
    	 * 提示:1.遍历数据仓库中的books属性中所有的图书,找到图书编号和bookId相同的图书下标
    	 * 		2.在遍历的循环外面,通过list的remove(index)方法删除图书
    	 */
    	public void removeBook(int bookId);
    	/**
    	 * 描述:TODO 根据bookId找到对应的图书,将图书的其余属性分别修改为参数中传递过来的值
    	 */
    	public void updateBook(int bookId, String newName, double newPrice,
    			String newCategory, String newDesc);
    	/**
    	 * 描述:TODO 获得所有图书
    	 */
    	public List<Book> getAllBooks();
    	/**
    	 * 描述:TODO 根据价格区间找到   minPrice<=price<=maxPrice的所有图书
    	 */
    	public List<Book> getBooksByPriceRange(double minPrice, double maxPrice);
    	/** 
    	 * 描述:TODO 根据类名查找所有的图书
    	 */
    	public List<Book> getBooksByCategory(String category);
    }
    

    3、实现接口

    class Library implements LibrarySystem {
    
    	@Override
    	public void addBook(Book book) {
    		try{
    			File file = new File("0.xls");
    			if(!file.exists()){
    				file=Excel.createExcel(file);
    			}
    			FileInputStream fis = new FileInputStream(file);
    			HSSFWorkbook wb = new HSSFWorkbook(fis);
    			HSSFSheet sheet = wb.getSheetAt(0);
    			HSSFRow row = sheet.getRow(0);//获取第一行(excel中的行默认从0开始,所以这就是为什么,一个excel必须有字段列头),即,字段列头,便于赋值  
    			int lastRowNum = sheet.getLastRowNum();//得到最后一行的信息
    			System.out.println(lastRowNum);
    			
    			FileOutputStream fos = new FileOutputStream(file);
    			row = sheet.createRow((short)(lastRowNum+1));  //现有行之后追加数据
    			for(int i=0;i<5;i++){
    				switch(i){
    				case 0:row.createCell(0).setCellValue(book.getBook_id());break;
    				case 1:row.createCell(1).setCellValue(book.getBook_title());break;
    				case 2:row.createCell(2).setCellValue(book.getBook_price());break;
    				case 3:row.createCell(3).setCellValue(book.getBook_class());break;
    				case 4:row.createCell(4).setCellValue(book.getBook_produce());break;
    				}
    			}
    			wb.write(fos);
    			fos.close();
    		}catch(Exception e){
    			e.printStackTrace();
    		}	
    	}
    	@Override
    	public void removeBook(int bookId) {
    		try{
    			HSSFWorkbook wb = new HSSFWorkbook(new FileInputStream("0.xls"));
    			HSSFSheet sheet = wb.getSheetAt(0);
    			HSSFRow row ;
    			int lastRowNum = sheet.getLastRowNum();
    			//得到第二行的数据
    			int i = sheet.getFirstRowNum()+1;
    			//从第二行开始遍历,直至最后,因为第一行是表头
    			while(i<=lastRowNum){
    				//得到第i行
    				row = sheet.getRow(i);
    				//得到第i行的第一个单元格
    				int removeRow = (int) row.getCell(0).getNumericCellValue();
    				if(bookId == removeRow){
    					sheet.shiftRows(i, sheet.getLastRowNum(), -1);
    					sheet.removeRow(sheet.getRow(lastRowNum));//删除最后一个空行,避免下次存入数据有空行出现
    					FileOutputStream fos = new FileOutputStream("0.xls");
    					wb.write(fos);
    					fos.close();
    					System.out.println("数据删除完成!");
    					return ;
    				}
    				i++;
    			}
    			System.out.println("不存在这条数据!");
    			
    		}catch(Exception e){
    			e.printStackTrace();
    		}
    	}
    
    	public void updateBook(int bookId, String newName, double newPrice,
    			String newCategory, String newDesc) {
    		try{
    			File file  = new File("0.xls");
    			FileInputStream fis = new FileInputStream(file);
    			HSSFWorkbook wb = new HSSFWorkbook(fis);
    			HSSFSheet sheet = wb.getSheetAt(0);
    			HSSFRow row;
    			//得到第二行的行号
    			int firstRowNum = sheet.getFirstRowNum()+1;
    			//得到最后一行的行号
    			int lastRowNum = sheet.getLastRowNum();
    			while(firstRowNum<=lastRowNum){
    				//得到一行数据
    				row = sheet.getRow(firstRowNum);
    				//进行第一个单元格和bookId作比较
    				if((int)row.getCell(0).getNumericCellValue() == bookId){
    					row.getCell(1).setCellValue(newName);//设置firstRowNum的第二个单元格
    					row.getCell(2).setCellValue(newPrice);//设置firstRowNum的第三个单元格
    					row.getCell(3).setCellValue(newCategory);//设置firstRowNum的第四个单元格
    					row.getCell(4).setCellValue(newDesc);//设置firstRowNum的第五个单元格
    					FileOutputStream fos = new FileOutputStream(file);
    					wb.write(fos);
    					fos.close();
    					return;
    				}
    				firstRowNum++;
    			}
    			System.out.println("此条数据不存在!");
    		}catch(Exception e){
    			e.printStackTrace();
    		}
    		
    
    	}
    
    	@Override
    	public List<Book> getAllBooks() {
    		List<Book> list = new ArrayList<Book>();
    		try{
    			FileInputStream fis = new FileInputStream(new File("0.xls"));
    			HSSFWorkbook wb = new HSSFWorkbook(fis);
    			HSSFSheet sheet = wb.getSheetAt(0);
    			HSSFRow row;
    			int firstRowNum = sheet.getFirstRowNum()+1;
    			
    			int lastRowNum = sheet.getLastRowNum();
    			System.out.println(firstRowNum+"    "+lastRowNum);
    			while(firstRowNum<=lastRowNum){
    				System.out.println(firstRowNum+"------------->");
    				row = sheet.getRow(firstRowNum);
    				Book book = new Book();
    				int id= (int) row.getCell(0).getNumericCellValue();
    				String name= row.getCell(1).getStringCellValue();
    				double price = row.getCell(2).getNumericCellValue();
    				String newCategory = row.getCell(3).getStringCellValue();
    				String newDesc = row.getCell(4).getStringCellValue();
    				book.setBook_id(id);
    				book.setBook_title(name);
    				book.setBook_price(price);
    				book.setBook_class(newCategory);
    				book.setBook_produce(newDesc);
    				list.add(book);
    				firstRowNum++;
    			}
    		}catch(Exception e){
    			e.printStackTrace();
    		}
    		return list;
    	}
    
    	@Override
    	public List<Book> getBooksByPriceRange(double minPrice, double maxPrice) {
    		List<Book> list = new ArrayList<Book>();
    		try{
    			FileInputStream fis = new FileInputStream(new File("0.xls"));
    			HSSFWorkbook wb = new HSSFWorkbook(fis);
    			HSSFSheet sheet = wb.getSheetAt(0);
    			HSSFRow row;
    			int firstRowNum = sheet.getFirstRowNum()+1;
    			int lastRowNum = sheet.getLastRowNum();
    			while(firstRowNum<=lastRowNum){
    				double price = sheet.getRow(firstRowNum).getCell(2).getNumericCellValue();
    				if(price>minPrice && price<maxPrice){
    					row = sheet.getRow(firstRowNum);
    					Book book = new Book();
    					int id= (int) row.getCell(0).getNumericCellValue();
    					String name= row.getCell(1).getStringCellValue();
    					String newCategory = row.getCell(3).getStringCellValue();
    					String newDesc = row.getCell(4).getStringCellValue();
    					book.setBook_id(id);
    					book.setBook_title(name);
    					book.setBook_price(price);
    					book.setBook_class(newCategory);
    					book.setBook_produce(newDesc);
    					list.add(book);	
    				}
    				firstRowNum++;
    			}
    		}catch(Exception e){
    			e.printStackTrace();
    		}
    		return list;
    	}
    
    	@Override
    	public List<Book> getBooksByCategory(String category) {
    		List<Book> list = new ArrayList<Book>();
    		try{
    			FileInputStream fis = new FileInputStream(new File("0.xls"));
    			HSSFWorkbook wb = new HSSFWorkbook(fis);
    			HSSFSheet sheet = wb.getSheetAt(0);
    			HSSFRow row;
    			int firstRowNum = sheet.getFirstRowNum()+1;
    			int lastRowNum = sheet.getLastRowNum();
    			while(firstRowNum<=lastRowNum){
    				String cg = sheet.getRow(firstRowNum).getCell(3).getStringCellValue();
    				if(category.equals(cg)){
    					row = sheet.getRow(firstRowNum);
    					Book book = new Book();
    					int id= (int) row.getCell(0).getNumericCellValue();
    					String name= row.getCell(1).getStringCellValue();
    					Double price = row.getCell(2).getNumericCellValue();
    					String newCategory = row.getCell(3).getStringCellValue();
    					String newDesc = row.getCell(4).getStringCellValue();
    					book.setBook_id(id);
    					book.setBook_title(name);
    					book.setBook_price(price);
    					book.setBook_class(newCategory);
    					book.setBook_produce(newDesc);
    					list.add(book);	
    				}
    				firstRowNum++;
    			}
    		}catch(Exception e){
    			e.printStackTrace();
    		}
    		return list;
    	}
    }
    
    4、Book类
    package com.baizhi.test.project;
    
    public class Book {
    	private Integer book_id;
    	private String book_title;
    	private Double book_price;
    	private String book_class;
    	private String book_produce;
    	
    	public Book(){}
    	public Book(Integer book_id, String book_title, Double book_price,
    			String book_class, String book_produce) {
    		super();
    		this.book_id = book_id;
    		this.book_title = book_title;
    		this.book_price = book_price;
    		this.book_class = book_class;
    		this.book_produce = book_produce;
    	}
    
    
    	public Integer getBook_id() {
    		return book_id;
    	}
    	public void setBook_id(Integer book_id) {
    		this.book_id = book_id;
    	}
    	public String getBook_title() {
    		return book_title;
    	}
    	public void setBook_title(String book_title) {
    		this.book_title = book_title;
    	}
    	public Double getBook_price() {
    		return book_price;
    	}
    	public void setBook_price(Double book_price) {
    		this.book_price = book_price;
    	}
    	public String getBook_class() {
    		return book_class;
    	}
    	public void setBook_class(String book_class) {
    		this.book_class = book_class;
    	}
    	public String getBook_produce() {
    		return book_produce;
    	}
    	public void setBook_produce(String book_produce) {
    		this.book_produce = book_produce;
    	}
    	@Override
    	public String toString() {
    		return "Book [book_id=" + book_id + ", book_title=" + book_title
    				+ ", book_price=" + book_price + ", book_class=" + book_class
    				+ ", book_produce=" + book_produce + "]";
    	}
    	
    	
    }
    

    5、辅助操作Excel表的类,功能未写完
    class Excel {
    	//创建一个文件
    	public static File createExcel(File file) {
    		try {
    			FileOutputStream os = new FileOutputStream(file);
    			HSSFWorkbook workbook = new HSSFWorkbook();
    			HSSFSheet sheet = workbook.createSheet("信息");
    			HSSFRow row ;
    			HSSFCell cell ;
    			// 创建表头
    			row = sheet.createRow(0);
    			for (int i = 0; i < 5; i++) {
    				cell = row.createCell(i);
    				switch (i) {
    				case 0:cell.setCellValue("图书编号");break;
    				case 1:cell.setCellValue("名称");break;
    				case 2:cell.setCellValue("价格");break;
    				case 3:cell.setCellValue("类别");break;
    				case 4:cell.setCellValue("简介");break;
    				}
    			}
    			workbook.write(os);
    			os.close();
    			System.out.println("创建成功!");
    			} catch (Exception e) {
    		}
    		return file;
    	}
    }


    展开全文
  • 分段存储管理系统

    2011-12-26 17:07:22
    分段存储管理系统:建立一基本分段存储管理系统模型。 (1)首先分配一片较大内存空间,作为程序运行可用存储空间; (2)建立应用程序模型,应该包括相应分段描述与存储结构; (3)建立进程基本...
  • 操作系统--存储管理4

    2017-10-28 14:18:00
    概念:当出现缺页异常时候,并且内存中空闲页面也用完, 此时必须把进行外存与内存页面置换。 页面置换算法的功能:选择合适页面进行置换。 2.置换算法追求目标 * 尽可能减少页面置换次数 * 将未来...
  • 运行条件: 需要建立一名字为1文件在D盘中,fp=fopen(“D:\1.txt”,“w+”); 在控制台输入信息会自动记入到该文件中,缺点是无法对文件本身进行操作改变信息,优点...4)系统采用菜单方式工作 功能概述: 1)查
  • Linux 高级存储管理

    2021-05-09 12:33:00
    Linux 高级存储管理一.逻辑卷1.lvm设备建立2.lvm拉伸3.lvm缩减4.lvm删除:5.lvm快照二..vdo1.vdo建立:2.使用vdo设备3.测试vdo性能5.vdo设备删除 一.逻辑卷 1.物理卷(PV, Physical Volume) 物理卷就是指磁盘,...
  • 存储管理 实验指导书

    2013-12-30 11:21:05
    存储管理的主要功能之一是合理地分配空间 请求页式管理是一种常用的虚拟存储管理技术 本设计的目的是通过请求页式存储管理中页面置换算法模拟设计 了解虚拟存储技术的特点 掌握请求页式存储管理的页面置换算法 要求...
  • GitHubExplorer是一用Swift编写本地iOS应用程序。 它使您能够以所有编程语言查看GitHub当前趋势存储库,还使您能够根据不同条件(例如星数)或存储库存在对初学者友好问题来浏览存储库。 屏幕截图 产品...
  • Disk 是一个功能强大而简单文件管理库,它利用AppleData Storage Guidelines构建。 Disk 使用Swift 4中引入可编解码协议最大优势,使您能够持久保留JSON数据,而无需担心编码/解码。 Disk 还可以帮助您...
  • 在一请求页式存储管理中,一程序页面走向为 4, 3, 2, 1, 3, 5, 4, 3, 2, 1, 5,并采用 LRU 算法。假设分配给该程序存储块数 M 分别为 3 和 4,则该访问中发生缺页次数 F 分别是? 这里我们讲讲两概念: ...
  • 内部存储器:计算机主机组成部分,用来容纳当前正在使用或经常要使用程序和数据,对于内存,CPU可直接访问。包括ROM和RAM 外部存储器:存储各种信息,CPU要使用时,必须通过专门机制将其中信息先传到...
  •  存储器管理的功能  1.地址映射  2.主存分配与回收  3.存储保护  4.主存扩充(虚拟内存)  地址映射(地址重定位)  内存的每个存储单元都有一编号,这种编号称为内存地址(或物理地址,地址)。  实现...
  • 实验4 内存管理 一、实验目的 1、对内存管理的相关内容做进一步的...3、在设计好的数据结构上设计一主存分配算法,要求实现的基本功能操作有:寻找空闲分区,空闲分区表的修改,已分区表的修改。 4、在设计好的数据.
  • FanPress CM 4个模块 此回购包括版本4中FanPress CM新闻系统模块。安装系统后,可通过模块管理器使用这些模块。 随时报告任何错误,功能请求等。
  • 存储管理——笔记

    2013-10-10 17:44:10
    一、分区存储管理  固定分区:静态分区方式,系统生成时将主存划分大小不等区域,易形成碎片  可变分区:动态分区方式,作业装入时划分,数可变,大小等于作业大小,也容易形成碎片  可重定位分区:移动...
  • 存储空间管理 功能 记录磁盘使用情况,管理和分配,回收存储空间。 记录磁盘空闲块方法 空闲文件目录 空闲块链 位示图 文件目录管理 文件目录 目录文件 文件目录以文件形式存于外存,这文件叫目录文件。 ...
  • 另一部分是演示系统,调用请求分段存储管理系统相应函数,以让其运行,同时提供系统展示界面,可以是GUI或者字符界面,以展示系统运行状态,显示系统关键数据结构内容。 具体包括: 1.首先分配一片较大...
  • 通过编写固定分区存储管理的模拟程序,加深对操作系统存储管理功能中的固定分区管理方式、主存分配表等相应知识的理解。 二、实验内容 1、实现固定分区存储管理方式下存储空间的分配和去配。 2、已知当前内存分配表...
  •  6.1 存储管理概述 操作系统中用于管理内存空间模块称为内存管理模块,它负责内存全部管理工作,具体地说就是要完成4个功能,即存储空间分配、存储地址变换、存储空间保护以及存储空间扩充。...
  • 分页存储方式管理模拟 C++实现

    千次阅读 2019-12-25 16:25:26
    设计要求:设计一简单分页存储管理系统,要求实现以下功能。 (1) 定义分页地址结构和页表结构。 (2) 对进程逻辑地址空间、页表起址、给定逻辑地址进行初始化。 (3) 实现从逻辑地址到物理地址变换。 ...
  • 使用版本4、5或6存储管理嵌套集树库! 它支持多根树。 如果您有错误或想法,请随时提出问题或PR。 PS别忘了给这图书馆加注星标。 这激发了我对支持! :star: PPS如果您觉得可以在库方面为我提供帮助(编写...
  • General Bot是一基于强类型程序包聊天​​机器人服务器,专注于约定而非配置和无代码方法,它带来了软件包和应用程序服务器概念来帮助并行机器人开发。 什么是Bot服务器? Bot Server加快了开发机器人过程。...
  • 之前自己用DQ77KB搭建一个小存储系统(帖子链接:http://www.chiphell.com/thread-567753-1-1.html),一直使用intel主板带软RAID功能构建RAID5来用,使用一段时间后发现并不好管理,不能扩容(主板只有4个原生...
  • 4.文件存储oss

    2021-04-16 20:15:21
    在前端品牌管理模块需要文件上传存储功能,就来做一下吧 以前项目可能是通过一服务器上传到一处就可以了,但这项目是分布式,分了很多服务器 文件存储,就不能只存在一台服务器,要存在一地方(例如...
  • 存储管理的主要功能之一是合理地分配空间 请求页式管理是一种常用的虚拟存储管理技术 本实验的目的是通过请求页式存储管理中页面置换算法模拟设计 了解虚拟存储技术的特点 掌握请求页式管理的页面置换算法 2 ...
  • 3.虚拟存储管理:允许将一作业分多次调入内存。 若采用连续分配方式,需申请足够空间,再分多次装入,造成内存资源浪费,并不能从逻辑上扩大内存容量。 4.虚拟存储器特征:离散分配方式是基础 多次性 对换性 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,277
精华内容 1,710
关键字:

存储管理的4个功能