【第 7 周】深入理解计算机系统共读心得体会

所在小组

第六组

组内昵称

undefined

心得体会

信号

关于信号

信号是一个操作系统提供的基础异常机制。主要核心改了就是发生信号和接收信号

发生方可以是操作系统或其他进程,接收方则必须设置一个信号处理程序,或使用默认的信号。

信号是针对进程组而言,如果未设置信号组,则以pid为准。

信号的核心问题

信号的优先级问题,多个信号触发时,存在2类阻塞机制:隐式阻塞机制和显式阻塞机制。

针对信号处理方法,存着多个设计点:处理逻辑尽可能简单、只调用异步信号安全的函数、保存和恢复errno、阻塞所有信号并保护对共享局部数据结构的访问、volatilee声明全局变量、sig_atomic_t声明标记

不过这几个设计点暂时还是不能特别理解。

虚拟内存

虚拟内存的核心

DRAM缓存的组织结构,位于高速缓存下的主存缓存,同时为了支持缓存是否命中,以及当前缓存位于哪个物理页,则需要一个数据结构来表示,此乃页表

页命中,通过地址翻译将虚拟地址翻译成实际地址并进行读取。
缺页,则会出发一个缺页中断,将磁盘中的数据加载回内存。

虚拟内存的核心优化点:简化链接、简化加载、简化共享、简化内存分配。
这也是印证了所有计算机问题都可以通过一层代理来解决。

所在小组:第三组

组内昵称:晴天

心得体会:

  1. 异常控制流发生在计算机系统的各个层次,是计算机系统中提供并发的基本机制。
  2. 系统中有一张异常表,启动时会被初始化。通过间接过程调用异常,跳转到到一个专门设计用来处理异常事件的操作系统子程序。
  3. 异常可以分为4类:中断,陷阱和系统调用,故障,终止。
  4. 系统中的每个程序运行在某个进程的上下文中,而上下文是程序正确运行所需要的状态组成。
  5. 用户模式和内核模式和某个控制寄存器中的一个模式位来确认。
  6. 如何理解上下文以及上下文切换?
    1. 上下文切换是什么?较高层形式的异常控制流,用于实现多任务。由一血对象值组成,包括通用目的寄存器,浮点寄存器,程序计数器,用户栈,状态寄存器,内核栈和各种内核数据结构,
    2. 上下文切换是由调度器实现的。

所在小组:

     第二组

组内昵称:

心得体会

  1. 异常 是异常控制流的一种形式,它一部分由硬件实现,一部分由操作系统实现
    1.异常:控制流中的突变,用来响应处理器状态中的某些变化
    2.这种状态变化成为事件(event),事件可能和当前指令的执行直接相关
    • 虚拟内存缺页、算术溢出
    • 除以零
  2. 异常处理程序:任何情况下,当处理器检测到有事件(event)发生时,会通过一张叫做异常表的跳转表,进行一个间接调用,到一个专门处理这类事件的操作系统子程序
  3. 异常处理完成后,根据异常事件类型,分为以下三种情况
    • 返回当前指令
    • 返回没有异常,所执行的下一条指令
    • 中断cheng程序

所在小组

第一组

组内昵称

SADAME

心得体会

除了基本的改变控制流的方法

  • 跳转和分支
  • 调用和返回
    还有另一种更加复杂的机制,称之为异常控制流(exceptional control flow)。
    异常控制流存在于系统的每个层级,最底层的机制称为异常(Exception),用以改变控制流以响应系统事件,通常是由硬件的操作系统共同实现的。更高层次的异常控制流包括进程切换(Process Context Switch)信号(Signal)非本地跳转(Nonlocal Jumps),也可以看做是一个从硬件过渡到操作系统,再从操作系统过渡到语言库的过程。进程切换是由硬件计时器和操作系统共同实现的,而信号则只是操作系统层面的概念了,到了非本地跳转就已经是在 C 运行时库中实现的了。

异常 Exception

这里的异常指的是把控制交给系统内核来响应某些事件(例如处理器状态的变化),其中内核是操作系统常驻内存的一部分,而这类事件包括除以零、数学运算溢出、页错误、I/O 请求完成或用户按下了 ctrl+c 等等系统级别的事件。
系统会通过异常表(Exception Table)来确定跳转的位置,每种事件都有对应的唯一的异常编号,发生对应异常时就会调用对应的异常处理代码

异步异常(中断)

异步异常(Asynchronous Exception)称之为中断(Interrupt),是由处理器外面发生的事情引起的。对于执行程序来说,这种“中断”的发生完全是异步的,因为不知道什么时候会发生。CPU对其的响应也完全是被动的,但是可以屏蔽掉[1]。这种情况下:

  • 需要设置处理器的中断指针(interrupt pin)
  • 处理完成后会返回之前控制流中的『下一条』指令

比较常见的中断有两种:计时器中断和 I/O 中断。计时器中断是由计时器芯片每隔几毫秒触发的,内核用计时器终端来从用户程序手上拿回控制权。I/O 中断类型比较多样,比方说键盘输入了 ctrl-c,网络中一个包接收完毕,都会触发这样的中断。

同步异常

同步异常(Synchronous Exception)是因为执行某条指令所导致的事件,分为陷阱(Trap)、故障(Fault)和终止(Abort)三种情况。

类型 原因 行为 示例
陷阱 有意的异常 返回到下一条指令 系统调用,断点
故障 潜在可恢复的错误 返回到当前指令 页故障(page faults)
终止 不可恢复的错误 终止当前程序 非法指令

这里需要注意三种不同类型的处理方式,比方说陷阱和中断一样,会返回执行『下一条』指令;而故障会重新执行之前触发事件的指令;终止则是直接退出当前的程序。

系统调用虽然看起来像是函数调用,但实际上走的是异常控制流

非本地跳转 Non local Jump

所谓的本地跳转,指的是在一个程序中通过 goto 语句进行流程跳转,尽管不推荐使用goto语句,但在嵌入式系统中为了提高程序的效率,goto语句还是可以使用的。本地跳转的限制在于,我们不能从一个函数跳转到另一个函数中。如果想突破函数的限制,就要使用 setjmplongjmp 来进行非本地跳转了。

setjmp 保存当前程序的堆栈上下文环境(stack context),注意,这个保存的堆栈上下文环境仅在调用 setjmp 的函数内有效,如果调用 setjmp 的函数返回了,这个保存的堆栈上下文环境就失效了。调用 setjmp 的直接返回值为 0。

longjmp 将会恢复由 setjmp 保存的程序堆栈上下文,即程序从调用 setjmp 处重新开始执行,不过此时的 setjmp 的返回值将是由 longjmp 指定的值。注意longjmp 不能指定0为返回值,即使指定了 0,longjmp 也会使 setjmp 返回 1。

我们可以利用这种方式,来跳转到其他的栈帧中,比方说在嵌套函数中,我们可以利用这个快速返回栈底的函数

所在小组: 第七组

组内昵称:hayden

心得体会:

  • 进程处于三种状态之间的切换:运行、停止、终止

  • 控制寄存器分为用户模式和内核模式

  • 进程从用户模式到内核模式唯一的方法是通过异常:中断、进入系统调用、故障、终止

  • 信号产生有三种操作:

  • 执行默认信号
  • 捕捉信号
  • 忽略信号

信号处理有一下类别:

  • SA_ONESHOT:捕捉到信号之后只执行一次
  • SA_NOMASK:当处理这个信号的时候来了其他信号,去处理其他信号
  • SA_INTERRUPT,清除了SA_RESTART:在进行系统调用的时候,来了信号处理完了, 返回给应用一个错误码
  • A_INTERRUPT,没有清除SA_RESTART:自动重启
  • 信号分为可靠信号与不可靠信号

  • 虚拟内存,通过对物理内存的抽象给了程序员一块连续的内存空间,同时也使得多个进程互不干扰,主要两个部分,一个是pagetable,一个是mmu,当你代码中读取一个地址时,由mmu进行翻译,但是翻译参照的是pagetable中的内容,也就是操作系统负责处理虚拟内存与物理内存的映射,具体使用虚拟内存时,由mmu负责。

  • 虚拟内存的好处首先时提供了内存的保护,一个用户级进程无法访问内核的地址,其次,使用虚拟内存便于我们管理物理内存,使得内存碎片减少。

所在小组

第六组

组内昵称

蒋权

你的心得体会

信号

  • 在任何情况下,当处理器检测到有事件发生时,他就会通过异常表进行跳转,执行异常处理程序。
  • 异常可以分为四类:中断、陷阱、故障、终止。
  • 中断是异步发生的,是来自处理器外部的I/O设备的信号的结果。硬件中断不是由任何一条专门的指令造成的,从这个意义上来说,它是异步的,而其他异常时同步发生的,是执行当前指令的结果。
  • 程序代码和数据,它的栈、通用目的寄存器的内容、程序计数器、环境变量以及打开文件描述符的集合。
  • 一个进程为每个程序提供它自己的私有地址空间,一般来说,和这个空间中的某个地址相关联的那个存储器字节是不能被其他进程读或者写的,从这个意义上说,这个地址空间是私有的。
  • 在Linux中,可以通过fork函数新建一个子进程,子进程得到与父进程用户级虚拟地址空间相同的但是相互独立的一份拷贝,包括文本、数据、bss段、堆以及用户栈。子进程还获得与父进程任何打开文件描述符相同的拷贝,这意味着当父进程调用fork时,子进程可以读写父进程打开的任何文件。在父进程中fork函数返回子进程的pid值,而在子进程中fork函数返回0,因此fork函数调用一次却返回两次(一次在父进程,一次在子进程)。
  • 当一个进程由于某种原因终止时,内核并不是立即把它从系统中清除掉,相反,进程被保持在僵死状态,必须由父进程回收。如果父进程还没有回收僵死子进程就终止了,内核会安排init进程来回收它们。即使僵死进程没有运行,他们仍然消耗系统的存储器资源。
  • 在某些系统中,当处理程序捕获到一个信号时,被中断的慢速系统调用将会不再继续,而是立刻返回给用户一个错误条件。

虚拟内存

  • 虚拟内存是对于物理内存的抽象。支持虚拟内存的处理器,通过使用虚拟寻址 这种间接方法来引用物理内存。

所在小组

第四组

组内昵称

张旭辉

心得体会

虚拟内存

  • 虚拟内存被组织为一个由存放在磁盘上的N个连续的字节大小的单元组成的数组。
    每字节都有一个唯一的虚拟地址。

  • 虚拟内存用于管理内存,协调程序之间的内存占用和释放,但对程序来说是感知不到的。

  • 物理/虚拟 寻址流程:

所在小组: 第四组

组内昵称:LuGH

心得体会:
异常可以分为四类:中断(interrupt)、陷阱(trap)、故障(fault)和终止(abort)。

中断是异步产生的,是来自处理器外部的I/O设备的信号的结果。硬件中断不是由任何一条专门的指令造成的,从这个意义上来说它是异步的。硬件中断的异常处理程序通常称为中断处理程序(interrupt handler)。I/O设备,例如网络适配器、磁盘控制器和定时器芯片,通过向处理器芯片上的一个引脚发信号,并将异常号放到系统总线上,以触发中断,这个异常号标识了引起中断的设备。

陷阱是有意的异常,实质性一条指令的结果。就像中断处理程序一样,陷阱处理程序将控制返回到下一条指令。陷阱最重要的用途就是在用户程序和内核之间提供一个像过程一样的接口,叫做系统调用。

故障是由错误引起的,它可能被故障处理程序修正。当故障发生时,处理器将控制转移到故障处理程序。如果处理程序能够修正这个错误情况,它就会将控制返回到引起故障的指令,从而重新执行它。否则,处理程序返回到内核的abort例程,abort例程会终止引起故障的应用程序。

终止是不可恢复的致命错误造成的结果,通常是一些硬件错误,例如DRAM或者SRAM位被损坏时发生的奇偶错误。终止处理程序从不将控制返回给应用程序。

所在小组

第六组

组内昵称

利健锋

你的心得体会

  • 异常分为四类
    • 中断 interrupt
    • 陷阱 trap
    • 故障 fault
    • 终止 abort

地址翻译需要硬件操作系统紧密合作

  • 拿到就是命中,未拿到就是未命中,如果没有命中会发生缺页异常
  • 虚拟内存能简化内存管理 ,也能提供内存保护
  • 虚拟页集合
    • 未分配的
    • 缓存的
    • 未缓存的
  • 页面调度和虚拟地址空间的结合
    • 简化程序链接
    • 简化加载
    • 简化共享
    • 简化内存分配

CPU 有一个一般保护故障,Linux shell 报告为 Segmentation fault

所在小组

第四组

组内昵称

张旭辉

心得体会

虚拟内存

  • 同一个数据可以有一个或多个地址,其中每个地址都选自不同的线性地址空间

  • 虚拟内存被组织为一个由存放在磁盘上的N个连续的字节大小的单元组成的数组。
    每字节都有一个唯一的虚拟地址。

  • 虚拟内存用于管理内存,协调程序之间的内存占用和释放,但对程序来说是感知不到的。

  • 虚拟寻址流程:CPU加载指令是将其生成一个虚拟地址 ,递给主存,主存将其转换成物理地址 。主存取出物理地址对应的内存,并返回给 CPU,CPU 将其存放在寄存器中。转换过程叫做地址翻译 address translation。

  • 虚拟页存在三种状态:未分配,缓存(到物理页),未缓存(到物理页)。

  • 页表存放在内存(DRAM)中,记录虚拟页到物理页的映射关系

所在小组

第七组

组内昵称

吴奇驴

你的心得体会

1.信号:更高层次的软件形式的异常,允许进程和内核中断其他进程;
2.任何时刻,一种类型至多只会有一个待处理信号;
3. Ctrl+C 是触发 SIGINT 信号给前台的进程组里的每一个进程;
4.未处理的信号是不排队的,如果存在一个未处理的信号就表明至少有一个信号到达了,不可以用信号来对其他进程中发生的事件计数;
5. strace\ps\top\pmap. /proc;
6. DRAM 总是写回而不是直写;
7. 工作集大小超出了物理内存大小,程序会发生“抖动”,页面会不停的换进换出,性能下降。

所在小组

第七组

组内昵称

jinmiaoluo

心得体会

见: https://github.com/jinmiaoluo/blog/tree/main/example-8-reading-notes/csapp/chapter-7-and-chapter-8
Diff: https://github.com/jinmiaoluo/blog/pull/10

所在小组:静默组
组内昵称:黄小黄
心得体会:

  • SRAM 缓存指的是 CPU 和 L1,L2,L3 和主存之间的缓存,DRAM 缓存指的是虚拟内存系统的缓存,他在主存中缓存虚拟页。
  • 虚拟内存优点:
  1. 简化链接:每个进程都可以使用相同的基本格式(包括 segment 组成,内存地址);
  2. 简化加载:向内存中加载可执行文件和共享对象文件变得简单。加载磁盘文件时是通过虚拟内存地址加载的;
  3. 简化共享:每个进程资源是隔离的,但只要将虚拟页面映射到同一个物理页面,就可以了安排多个进程共享这部分代码的一个副本,而不是每个进程都包含单独一个副本;
  4. 简化内存分配:进程申请额外的堆空间时(如 malloc),操作系统分配连续数字的虚拟内存页,并映射到不一定连续的物理页面中。
  • 虚拟内存的特性可以作为内存保护的工具。进程之间无法随意的访问对方的内存空间。虚拟内存还可以通过设置 flag 来控制内存的读写权限
  • 地址翻译过程:(命中)
  1. 处理器生成虚拟地址 VA,传给 MMU;
  2. MMU 生成 PTE 地址,通过高速缓存或主存请求得到它;
  3. 高速缓存或主存返回PTE;
  4. MMU 构造物理地址,并传送给高速缓存或主存;
  5. 高速缓存或主存返回请求的数据字给处理器。
  • 地址翻译过程:(不命中)
  1. 处理器生成虚拟地址 VA,传给 MMU;
  2. MMU 生成 PTE 地址,通过高速缓存或主存请求得到它;
  3. 高速缓存或主存返回PTE;
  4. PTE 有效位为 0,传递 CPU 的控制,让操作系统内核执行缺页异常处理程序
  5. 确定物理内存的牺牲页,如果该牺牲页已被修改则换出磁盘;
  6. 缺页处理程序页面调入新的页面,并更新内存中的 PTE。
  7. 返回到原来的进程,再次执行缺页指令,此时会命中,MMU 将返回请求的数据字给处理器。
  • 在 SRAM 缓存和虚拟内存共存的系统中,大部分系统使用的是物理寻址来访问 SRAM。这样设计可以让 SRAM 缓存保持简单。
  • PTE 也可以有缓存,来避免每次使用虚拟地址 MMU 都要查阅一个 PTE。PTE 缓存就在 MMU 中,叫 TLB
  • 内存映射是 Linux 把磁盘上的一个对象,关联起来并初始化一个虚拟内存区域的内容。
  • fork 原理是虚拟内存全部页面改为只读,新页面私有写时复制。
  • 内存分配实现:1. 隐式空闲链表。把大小和是否使用写在区块头,通过遍历链表(一般用数组实现),找出空闲区块。匹配策略有三种:首次适配,从头找到第一个适合的空闲块;下次适配,从上一次位置开始找;最佳适配,找到符合要求的最小空闲块。匹配后分割也有策略。合并(碎片整理)也有策略,可以是立即合并(释放时合并)和推迟合并(无空间时合并,通常会使用这个)。
    1. 显式空闲链表。把空闲块信息写在空闲块主体内(因为它是空闲的,所以可以用来存数据),信息数据结构是一个双向链表,记录上一个和下一个空闲块。管理方法可以是 LIFO,刚释放的块放入链表头部,这样释放块时间复杂度是 O(1),如果用了边界标记(末尾标记),合并的时间复杂度也是 O(1);也可以是地址顺序,这样首次匹配复杂度是 O(n),但内存利用率接近最佳匹配。显示链表有最小区块限制,一定程度上提高了内部碎片的程度。
    1. 分离空闲列链表。维护多个空闲链表,同一个链表的空闲块大小大致相等。
    1. 垃圾收集器根据内存的可达图,来判断孤立的内存块,进而回收

所在小组

第四组

组内昵称

zhilin

心得体会

虚拟内存

虚拟存储器又叫做虚拟内存,我们现在的操作系统普遍都支持了虚拟内存,这样做是因为我们同时运行着太多的程序了,如果不使用虚拟内存4G的内存空间很快就会被耗尽,而一旦没有了内存空间,其他程序就无法加载了。虚拟内存的出现就是为了解决这个问题,当一个程序开始运行的时候,其实是为每个程序单独创建了一个页表(这个以后讲),只将一部分放入内存中,以后根据实际的需要随时从硬盘中调入内容。当然虚拟内存不仅仅只有这个功能,我们的操作系统也是在内存中运行着的,虚拟内存同时还提供了一种保护,这样做其他进程就不会损坏掉系统的内存空间。

虚拟存储器的主要思想就是:在主存中缓存硬盘上的虚拟页(pagefile.sys),虚拟页有三个状态:未分配、缓存的、未缓存的。

① 页表

页表1

页表是一个存放在内存中的数据结构,MMU就是通过页表来完成虚拟地址到物理地址的转换。这个数据结构每一个条目称为PTE(Page Table Entry),由两部分组成:有效位和n位地址段。有效位如果是1,那么n位地址就指向已经在内存中缓存好了的地址;如果为0,地址为null的话表示为分配,地址指向磁盘上的虚拟内存(pagefile.sys)的话就是未缓存。我们来看一个典型的页表图:

虚拟页vp1,2,7,4当前被缓存在内存中,页表上有效位设置成1,分别用PTE1,2,4,7表示。VP0和VP5(PTE0、5)未被分配,VP3和VP6被分配并指向虚拟内存,但未被缓存。

② 页命中

页命中

当我们使用2100虚拟地址来访问虚拟页2的内容的时候,就是一个页命中。地址翻译将指向PTE2上,由于有效位1,地址翻译器MMU就知道VP2已经缓存在内存中了。就使用页表中保存的物理地址进行访问。

③ 缺页

缺页

我们再来看看不命中,也就是缺页的情况,当CPU需要VP3的一个字时,初始化是这样的:

PTE3有效位是0,同时地址位指向了虚拟内存(pagefile.sys),就会触发缺页异常。异常处理程序会选择牺牲一个内存(DRAM)中的页,本例中选择的是内存中的PP3页的VP4,接下来内核就从虚拟内存中拷贝VP3到内存中的PP3,并使得PTE3指向内存中的PP3,形成如下:

(注:虚拟存储器出现早于高速缓存,按照习惯的说法块被叫做页。从虚拟内存到物理内存传送页的活动就叫做页面交换。)

[quote=“tarzan, post:7, topic:1255”]

所在小组

第七组

所在小组

第五组

组内昵称

王传义

你的心得体

  • cori7 结构没看懂,只理解地址转换在cpu完成,非内存完成。这说明物理内存只是物理内存。

  • 虚拟内存不同段存储第地址上不是连续的。因此在访问时候出现,小缺页,大缺页,只读三个异常。

  • 进程的虚拟内存区域通过映射方式直接把文件加载到内存。虚拟内存存储磁盘可能swap mmap

  • 虚拟内存出现,让动态库共享成为可能(file),虽然此时程序任务各自独占。只读 ,不然cow

  • 因为不确定内存需求情况,需要使用动态内存 new delete

  • 内存碎片造成heap 利用了低。

  • free 一个地址后,如果上下没有释放,这个地址标记为free,但是无法合并成更大的区块的。

    这也引证了free释放2个方式,小于128k 128k内存区别。

  • 忘记free为什么造成内存泄漏,因为这个区域依然标记被占用,系统并不知道

  • gc问题,不同语言不通处理,不是c++不提供,相关知识就学习了。1960就提出相关理论、

    过去优点,可能变成今天确定 ,gc通过图来维护,c无法来维护。

所在小组:第一组

组内昵称:nigel

心得体会:

  • 对于memory,我们通过一块称为MMU的内存管理单元的硬件来实现虚拟内存地址到物理地址到地址转换
  • 为什么要实现虚拟内存。
    • 第一,虚拟内存使用DRAM作为存储在磁盘上的实际数据的缓存。仅仅将虚拟地址空间的一部分实际存储在物理存储器中。
    • 第二,虚拟内存大大简化了内存管理。
    • 第三,它允许我们对访问内存进行保护。
  • Tool for Caching
    • 虚拟内存是存储在磁盘上的一个字节序列,物理内存可以看作是这个序列的一个缓存。
    • 从概念上讲,虚拟内存可以看作存储在磁盘上的一系列页面,这就叫做虚拟页面。一些页面缓存在物理内存中,一些页面没有缓存,它们仍然在磁盘上。大多数页都是未分配的。
    • 记录虚拟页面位置的数据结构称为页表,页表存在内存中,由内核维护,是每个进程上下文的一部分,所以每个进程都有自己的页表。 页表将虚拟页映射到物理页。
    • 在任意时刻,虚拟页面的分为三种:
      • 未分配的:VM系统还未分配(或者创建)的页。未分配的块没有任何数据和它们相关联,所以也就不占任何磁盘空间。
      • 缓存的:当前已缓存在物理内存中的已分配页。
      • 未缓存的:未缓存在物理内存中的已分配页。地址翻译硬件(MMU)在将虚拟地址转换为物理地址时,都会读取页表。页表每一行表示一个虚拟页面的信息,包括有效位和物理页号(磁盘地址),有效位表示此物理页是否被缓存,物理页号表示具体位置(没有分配的此栏值为null)。
    • 当访问一个虚拟页面时,操作系统通过地址翻译硬件读取页表,找到对应行后,就能知道对应空间的位置和是否缓存在物理内存中。如果有效位为0,表示缓存没有命中,我们称之为缺页。
    • 缺页会触发一个缺页异常,缺页异常调用内核中的缺页异常处理程序,该程序会选择一个牺牲页,如果牺牲页被修改过,则牺牲页会被拷贝回磁盘,接着内核会将磁盘上需要访问的页面复制到内存牺牲页的位置上,并更新页表,这时异常处理程序执行完毕返回,返回后会重新启动导致缺页的指令,该指令会重续将虚拟地址发送给地址翻译硬件,之后由于已经缓存了目的页面,也就可以由地址翻译硬件正常处理了。
    • 当我们调用malloc分配空间时,操作系统会分配在磁盘上分配对应页面,之后会将地址更新到页表中,使页表中对应项指向磁盘上新创建的页面。所以我们在调用malloc分配空间后,这个空间实际是在磁盘上,当我们访问这个空间时,会触发一个缺页异常之后,这个空间才会被缓存到物理内存中。
  • 虚拟内存作为内存管理的工具。
    • 简化链接。操作系统为每个进程提供了一个独立的页表,因而也就是一个独立的虚拟地址空间。独立的地址空间允许每个进程的内存映像使用相同的基本格式,而不用管代码和数据实际存放在物理内存何处。
    • 简化加载。虚拟内存使得容易向内存中加载可执行文件和共享对象文件。要把目标文件中.text和.data节加载到一个新创建的进程中,Linux加载器位代码和数据段分配虚拟页,把它们标记成未缓存的,将页表条目指向目标文件中适当位置。
    • 简化共享。独立地址空间为操作系统提供了一个管理用户进程和操作系统自身之间共享的一个机制。
    • 简化内存分配。虚拟内存为向用户进程提供一个简单的分配额外内存的机制。一个用户进程中的程序要求额外的内存空间时,操作系统分配一个适当数字的连续虚拟内存页面,并将它们映射到物理内存中随机位置的任意个物理页面而不需要连续的。

信号处理还有有下面三种类别(sa_flags):

  • SA_ONESHOT:捕捉到信号之后只执行一次
  • SA_NOMASK:当处理这个信号的时候来了其他信号,去处理其他信号
  • SA_INTERRUPT,清除了SA_RESTART:在进行系统调用的时候,来了信号处理完了, 返回给应用一个错误码,让人家自己去搞
  • SA_INTERRUPT,没有清除SA_RESTART:自动重启,但是有的时候比较尴尬,当用户输入的时候,系统调用处理字符的时候来了信号,再重启,还得让用户重新输入一遍