20145339《信息安全系统设计基础》第14周学习总结

20145339《信息安全系统设计基础》第14周学习总结

教材学习

  • 虚拟存储器 对主存的抽象机制,是硬件异常、硬件地址翻译、主存、磁盘文件和内核软件的完美交互。
    • 将主存看成是一个存储在磁盘上的地址空间的高速缓存,在内存中只保存活动区域,并根据需要在磁盘和内存之间来回传送数据。
    • 为进程提供了一致的地址空间,从而简化了存储器管理。
    • 保护了每个进程的地址空间不被其他进程所破坏。
  • 物理和虚拟地址
    • CPU通过生成一个虚拟地址(Virtual address,VA)来访问主存。将虚拟地址转换为物理地址叫做地址翻译(address translation)。地址翻译也需要CPU硬件和操作系统之间的紧密结合。
    • CPU芯片上有叫做存储器管理单元(Memory Management Unit,MMU)的专用硬件。利用存储在主存中的查询表来动态翻译虚拟地址。 查询表由操作系统管理。
  • 虚拟存储器作为缓存的工具虚拟存储器(VM)被组织为一个存放在磁盘上的N个连续字节大小的单元组成的数组。每个字节都有一个唯一的虚拟地址,这个唯一的虚拟地址作为到数组的索引。磁盘上数组的内容被缓存到主存中。VM系统通过将虚拟存储器分割为称为虚拟页的大小固定的块来处理磁盘和主存信息交互问题。任何时候,虚拟页的集合都被分为3个不相交的子集。
    • VM系统还未分配(或者创建)的页。未分配的块没有任何数据与之相关联。不占用磁盘空间。
    • 当前缓存在物理存储器的已分配页。
    • 没有缓存在物理页面存储器中的已分配页。
  • 虚拟存储器作为存储器管理的工具 操作系统为每个进程提供一个独立的页表,VM简化了链接和加载,代码和数据共享,以及应用程序的存储器分配。

  • Linux虚拟存储器系统 Linux为每个进程维持一个单独的虚拟地址空间:内核虚拟存储器和进程虚拟存储器。内核虚拟存储器包含内核中的代码和数据。
    • 内核虚拟存储器的某些区域被映射到所有进程共享的物理页面.如:内核代码,全局数据结构。
    • Linux将一组连续的虚拟页面(大小等同于系统DRAM总量)映射到相应的一组物理页面。
    • 内核虚拟存储器包含每个进程不相同的数据。页表,内核在进程上下文中时使用的栈等。
  • 并发Linux 虚拟存储器区域 Linux将虚拟存储器组织成一些区域(也叫做段)的集合。就是已经存在着的(已分配的) 虚拟存储器的连续片,这些片/页已某种形式相关联。所有存在的虚拟页都保存在某个区域,允许虚拟地址空间有间隙。

  • Linux缺页异常处理 MMU在试图翻译虚拟地址A时,触发缺页。这个异常导致控制转移到缺页处理程序,执行如下步骤:
    • 缺页处理程序搜索区域结构链表。把A和每个区域的vm_start和vm_end做比较。如果不合法,触发段错误。
    • 试图访问的存储器是否合法,如果不合法,触发保护异常,终止进程。
    • 若不存在以上情况,则选择牺牲页,替换,重新执行指令。
  • 存储器映射 Linux 通过将一个虚拟存储器区域与一个磁盘上的对象关联,以初始化这个虚拟存储器区域的内容。虚拟存储器区域可以映射到Unix文件系统中的普通文件、匿名文件这两种类型文件。

  • fork函数 当fork函数被当前进程调用时:
    • 内核为新进程创建内核数据结构,并分配给它唯一一个PID。
    • 为新进程创建虚拟存储器。
    • 创建了当前进程的mm_struct,区域结构和页表的原样拷贝。
    • 将两个进程的每个页面都标记为“只读”。并给两个区域进程的每个区域结构都标记为“私有的写时拷贝”。
  • execve函数 execve函数加载并运行需要以下几个步骤:
    • 删除已存在的用户区域:删除当前进程虚拟地址的用户部分中已存在的区域结构。
    • 映射私有区域:为新程序的文本,数据,bss和栈区域创建新的区域结构。所有新的区域结构都是私有的,写时拷贝的。文本和数据区域被映射到执行文件中的文件和数据区。bss区域是请求二进制零,映射到匿名文件。
    • 映射共享区域。
    • 设置程序计数器。
    • execve最后一件事设置PC指向文本区域的入口点。
  • mmap函数 可以使用mmap函数来创建新的虚拟存储器区域,并将对象映射到这些区域中 mmap();munmap函数删除虚拟存储器的区域 munmap()。

  • 储存器映射

    • 共享对象和私有对象

      • 共享对象

      • 私有对象

        execve函数:

        enter description here

    • 使用mmap函数的用户级存储器映射

      • 创建新的虚拟存储器区域

             #include <unistd.h>
             #include <sys/mman.h>
        
             void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
    • 参数含义:

      • start:这个区域从start开始

      • fd:文件描述符

      • length:连续的对象片大小

      • offset:距文件开始处的偏移量

      • prot:访问权限位,具体如下:

        PROT_EXEC:由可以被CPU执行的指令组成

        PROT_READ:可读

        PROT_WRITE:可写

        PROT_NONE:不能被访问

      • flag:由描述被映射对象类型的位组成,具体如下:

        MAP_ANON:匿名对象,虚拟页面是二进制0

        MAP_PRIVATE:私有的、写时拷贝的对象

        MAP_SHARED:共享对象

    • 删除虚拟存储器:

              include <unistd.h>
              include <sys/mman.h>
              int munmap(void *start, size_t length);

      成功返回0,失败返回-1

      start开始删除,由接下来length字节组成的区域。

    动态存储器分配

    • mallocfree函数:

      malloc函数:从堆中分配块:

              #include <stdlib.h>
      
              void *malloc(size_t size);

      free函数:释放已分配的堆块:

              #include <stdlib.h>
      
              void free(void *ptr);
    • 碎片:分为内部碎片和外部碎片

    • 放置策略:首次适配、下一次适配、最佳适配

    • 申请额外的堆存储器:

      sbrk函数:

          #include <unistd.h>
      
          vid *sbrk(intptr_t incr);

      成功则返回旧的brk指针,出错为-1

      通过将内核的brk指针增加incr来扩展和收缩堆。

    • 实现简单的分配器:序言块和结尾块

    • 显式空闲链表的区别

      • 分配时间

        隐式:分配时间是块总数的线性时间

        显式:分配时间是空闲块数量的线性时间。

      • 链表形式

        隐式:隐式空闲链表

        显式:双向链表,有前驱和后继,比头部脚部好使。

    垃圾收集

    • 基本知识:垃圾收集器

    • Mark&Sweep垃圾收集器

      两个阶段:标记、清除

      相关函数:

           ptr定义为typedef void *ptr
           ptr isPtr(ptr p):如果p指向一个已分配块中的某个字,那么就返回一个指向这个块的起始位置的指针b,否则返回NULL
           int blockMarked(ptr b):如果已经标记了块b,那么就返回true
           int blockAllocated(ptr b):如果块b是已分配的,那么久返回ture
           void markBlock(ptr b):标记块b
           int length(ptr b):返回块b的以字为单位的长度,不包括头部
           void unmarkBlock(ptr b):将块b的状态由已标记的改为未标记的
           ptr nextBlock(ptr b):返回堆中块b的后继
    • C保守的Mark&Sweep——平衡二叉树:根本原因是C语言不会用类型标记来标记存储器位置。

    C程序中常见的与存储器有关的错误

    • 间接引用坏指针:scanf错误

    • 读未初始化的存储器:假设堆存储器被初始化为0

    • 允许栈缓冲区溢出:缓冲区溢出错误

    • 假设指针和它们指向的对象是相同大小的

    • 造成错位错误

    • 引用指针,而不是它所指向的对象

    • 误解指针运算

    • 引用不存在的变量

    • 引用空堆块中的数据

    • 引起存储器泄露

原文地址:https://www.cnblogs.com/dj20145339/p/6221146.html