第三章 第一节 操作系统(一)

18 December 2021  |  home page


进程与线程

  进程 线程
内存分配 进程在执行过程中拥有独立的内存单元 多个线程共享进程的内存,(资源分配给进程,同一进程的所有线程共享该进程的所有资源。同一进程中的多个线程共享代码段(代码和常量),数据段(全局变量和静态变量),扩展段(堆存储)。但是每个线程拥有自己的栈段,栈段又叫运行时段,用来存放所有局部变量和临时变量)
调度单位 进程是资源分配的最小单位 线程时CPU调度的最小单位
系统开销 由于在创建或撤消进程时,系统都要为之分配或回收资源,如内存空间、I/o设备等。因此,操作系统所付出的开销将显著地大于在创建或撤消线程时的开销 而线程切换只须保存和设置少量寄存器的内容,并不涉及存储器管理方面的操作。可见,进程切换的开销也远大于线程切换的开销
稳定性 进程间不会相互影响 线程一个线程挂掉将导致整个进程挂掉

进程通信方式

  1. 管道
    • 普通管道 1) 半双开,有固定的读端和写段 2) 只能用于具有亲缘关系的进程之间的通信 3) 它可以看成是一种特殊文件,对于它的读写也可以使用普通的read,write等函数。但它不是普通的文件,并不属于其它任何的文件系统,只存在于内存中

    • 命名管道FIFO 1) FIFO可以在无关进程之间交换数据 2) FIFO有路径名与之关联,它以一种特殊设备文件形式存在于文件系统中

  2. 系统IPC 2.1 消息队列 是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标记。 (消息队列克服了信号传递信息少,管道只能承载无格式字节流以及缓冲区大小受限等特点)具有写权限得进程可以按照一定得规则向消息队列中添加新信息;对消息队列有读权限得进程则可以从消息队列中读取信息

    • 消息队列面向记录,其中的消息具有特定的格式以及特定的优先级
    • 消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除
    • 消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取

    2.2 信号量 semaphore 是一个计数器,可以用来控制多个进程对共享资源的访问。信号量用于实现进程的互斥与同步,而不是用于存储进程间通信数据

    • 信号量用于进程间同步,若要在进程间传递数据需要结合共享内存
    • 信号量基于操作系统的 PV 操作,程序对信号量的操作都是原子操作
    • 每次对信号量的 PV 操作不仅限于对信号量值加 1 或减 1,而且可以加减任意正整数
    • 支持信号量组

    2.3 信号 signal 信号是一种比较复杂的通信方式,用于通知接受进程某个时间已经发生

    2.4 共享内存 shared memory 它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据得更新。这种方式需要依靠某种同步操作,如互斥锁和信号量等

    • 共享内存是最快的一种IPC,因为进程是直接对内存进行存取
    • 因为多个进程可以同时操作,所以需要进行同步
    • 信号量+共享内存通常结合在一起使用,信号量用来同步对共享内存的访问
  3. 套接字 socket socket也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同主机之间的进程通信

线程通信方式

linux 虚拟地址空间

为了防止不同进程同一时刻在物理内存中运行而对物理内存的争夺和践踏,采用了虚拟内存。 虚拟内存技术使得不同进程在运行过程中,它所看到的是自己独自占有了当前系统的4G内存。所有进程共享同一物理内存,每个进程只把自己目前需要的虚拟内存空间映射并存储到物理内存上。 事实上,在每个进程创建加载时,内核只是为进程“创建”了虚拟内存的布局,具体就是初始化进程控制表中内存相关的链表,实际上并不立即就把虚拟内存对应位置的程序数据和代码(比如.text .data段)拷贝到物理内存中,只是建立好虚拟内存和磁盘文件之间的映射就好(叫做存储器映射),等到运行到对应的程序时,才会通过缺页异常,来拷贝数据。还有进程运行过程中,要动态分配内存,比如malloc时,也只是分配了虚拟内存,即为这块虚拟内存对应的页表项做相应设置,当进程真正访问到此数据时,才引发缺页异常。

请求分页系统、请求分段系统和请求段页式系统都是针对虚拟内存的,通过请求实现内存与外存的信息置换。

缺页中断

malloc()和mmap()等内存分配函数,在分配时只是建立了进程虚拟地址空间,并没有分配虚拟内存对应的物理内存。当进程访问这些没有建立映射关系的虚拟内存时,处理器自动触发一个缺页异常。

缺页本身是一种中断,与一般的中断一样,需要经过4个处理步骤:

  1. 保护CPU现场
  2. 分析中断原因
  3. 转入缺页中断处理程序进行处理
  4. 恢复CPU现场,继续执行

但是缺页中断是由于所要访问的页面不存在于内存时,由硬件所产生的一种特殊的中断,因此,与一般的中断存在区别:

  1. 在指令执行期间产生和处理缺页中断信号
  2. 一条指令在执行期间,可能产生多次缺页中断
  3. 缺页中断返回是,执行产生中断的一条指令,而一般的中断返回是,执行下一条指令

fork vs vfork

操作系统的页表寻址

页式内存管理,内存分成固定长度的一个个页片。操作系统为每一个进程维护了一个从虚拟地址到物理地址的映射关系的数据结构,叫页表,页表的内容就是该进程的虚拟地址到物理地址的一个映射。页表中的每一项都记录了这个页的基地址。通过页表,由逻辑地址的高位部分先找到逻辑地址对应的页基地址,再由页基地址偏移一定长度就得到最后的物理地址,偏移的长度由逻辑地址的低位部分决定。一般情况下,这个过程都可以由硬件完成,所以效率还是比较高的。页式内存管理的优点就是比较灵活,内存管理以较小的页为单位,方便内存换入换出和扩充地址空间。

Linux最初的两级页表机制:

Linux的三级页表机制:

Linux的四级页表机制:

多层分页会带来内存节约,若一个上级的页目录为空,则会剩下剩余的页目录

线程有哪些上下文

进程切换

  1. 切换页目录(每个进程都有一个页目录,页目录里存放页表,页表里存放物理页的映射)、刷新TLB(translation lookaside buffer)以使用新的地址空间
  2. 切换内核栈(每个进程都有内核栈和用户栈)和硬件上下文(寄存器)

死锁

死锁出现的条件

死锁解决方法

虚拟地址和物理地址

逻辑地址(相对地址,分段) -> 线性地址(分页) -> 物理地址

关于分段

逻辑地址 = [段标识符 : 段内偏移量]

虚拟内存置换方法




Hosted on GitHub Pages — Theme by orderedlist