zoukankan      html  css  js  c++  java
  • 操作系统概念Operating System concepts

    附:操作系统概念各章习题整理

    OS大题预测

    进程同步与信号量,对semaphore的定义,wait()和singal()操作

    进程调度策略,画Gantt图,求各个进程的轮转时间,等待时间,以及平均轮转时间,平均等待时间

    给出页面的引用串,根据不同的调度策略(LRU,Opt,FIFO,Clock)进行计算,得出缺页次数与缺页率

    死锁避免,银行家算法,系统安全状态(能否找到一个安全序列),对于进程的资源请求判断是否会造成死锁(避免算法)

    给定文件的索引结构,计算查找特定记录所需要的磁盘I/O次数,以及文件可存储的最大大小

    操作系统类型

    简单批处理系统

    多道程序批处理系统:无论何时都有程序在运行,从而使CPU的利用率达到最大。

    分时系统(time-sharing):在进程之间频繁切换CPU,以便用户在程序运行时能与其进行交互,特点是立即响应。

    并行/多处理器系统:增加吞吐量(多个处理器加速比小于N),规模经济(资源共享减少开销),增加可靠性(一个处理器故障不会导致系统罢工)

    实时系统

    分布式系统:资源共享,计算加速,可靠性,通信

    系统调用System Call

    System call - the method used by a process to request action by the operating system.

    Usually takes the form of a trap (software interrupt).

    Control passes through an interrupt vector to a service routine in the OS, and the mode bit is automatically set to supervisor mode.

    The OS verifies that the parameters are correct and legal, executes the request, and returns control to the instruction following the system call.

    参数传递机制

    Passing parameters to the kernel for a system call must be performed differently than when using an ordinary functional call. This is because a system call is performed by the kernel itself, which typically runs in a completely different address space than the process which made the call. Thus it is not possible to simply place system call parameters onto the process’ stack as this will not be readily available to the kernel. There are three main methods to pass the parameters required for a system call:

    (1) Pass the parameters in registers (this may prove insufficient when there are more parameters than registers).

    (2) Store the parameters in a block, or table, in memory, and pass the address of block as a parameter in a register. This approach is used by Linux and Solaris.

    (3) Push the parameters onto a stack(内核栈); to be popped off by the OS. Block and stack methods do not limitt the number or length of parameters passed.

    中断Interrupt

    The occurrence of an event is usually signaled by a (an) interrupt from either the hardware or the software.

    Hardware may trigger it at any time by sending a signal to the CPU, usually by way of the system bus.

    硬件中断,又称外部中断,由CPU的外部硬件信号引发。例如磁盘,鼠标,键盘的通知。

    Software may trigger it by executing a special operation called a system call.

    软件中断,由执行指令引发。例如指令执行异常的时候(访问非法地址,除数为0),或者是执行int n等指令。

    保护上下文环境包括:

    中断隐指令的保护断点(程序计数器PC),中断服务程序的保护现场(通用寄存器和状态寄存器)

    前者是CPU自动实现,后者是OS负责保存。

    进程Process

    程序执行的本质是CPU取指执行内存中取指令,并将指令存入指令寄存器IR中。

    多道程序设计(Multiprogramming)的目的是无论何时都有进程在运行,从而使CPU的利用率达到最大。

    当多个程序放入内存中进行切换的时候,需要保存上下文信息,这引出进程的概念。而之后,为了使得切换的开销更小,又引出了线程的概念。

    当一个可执行文件被装入内存时,程序才能成为进程。

    进程是执行中的程序。随着进程的执行,它改变状态。进程状态由进程当前活动所定 义。每个进程可处于:新建、就绪、运行、等待和终止。每个进程在操作系统内通过自己的进程控制块 (PCB) 来表示。

    image

    任何一个处理器同一时刻只能运行一个进程,但是可能有许多进程处于就绪或等待状态。

    当前不在执行的进程会放在某个等待队列中。操作系统有两种主要队列::I/O 请求队列和就绪队列 。就绪队列包括所有准备执行井等待 CPU 的进程。每个进程都有 PCB,PCB 链接起来就形成了就绪队列。长期(作业)调度从进程缓冲池(硬盘中)选择进程调入内存去争用 CPU 。通常,长期调度会受资源限制(多道程序设计的程度,即内存中的进程数量),尤其是内存管理的影响。短期调度从就绪队列中选择进程来分配CPU。

    操作系统必须为父进程创建子进程提供一种机制。父进程在创建完子进程之后可以进入阻塞状态并等待它的子进程终止,也可以并发执行父进程和子进程。并发执行有许多优点,例如信息共享、计算加速、模块化和便利性等。

    操作系统的执行进程可以是独立进程或协作进程。协作进程需要进程间有互相通信的机制。主要有两种形式的通信:共享内存和消息传递。共享内存方法要求通信进程共享一 些变量。进程通过使用这些共享变量来交换信息。对于共享内存系统,主要由应用程序员提供通信,操作系统只需要提供共享的内存(硬件资源)。消息传递方法允许进程交换信息。提供通信的主要责任在于操作系统本身。这两种方法并不互相排斥,能在同一操作系统内同时实现。

    image image

    image

    线程Thread

    进程是系统资源分配的基本单位,线程是CPU调度的基本单位。

    线程是进程内的控制流。

    具有多线程的进程在同一地址空间内包括多个不同的控制流

    多线程的优点包括对用户响应的改进(例如多线程Web浏览器在用一个线程装入图像时,还能通过另一个线程与用户交互)、进程内的资源共享(共享代码,数据和文件)、经济(创建线程比创建进程效率更高)和利用多处理器体系结构的能力

    用户线程对程序员可见,但对内核来说是不可见的——内核不知道用户线程的存在

    用户级线程概念

    进程切换只切换指令序列但仍共享资源 —> 线程切换

    线程切换只是指令序列的切换,PC值发生改变

    用栈保存切换前将要执行的指令地址

    为了使得函数调用的return指令正常运行,每一个线程对应一个栈,栈和TCB相关联

    用户级线程的并发性没有内核级线程好,因为一旦某个用户级线程阻塞了,同属一个进程的其它线程也被阻塞,因为CPU被分配给其它进程了。OS不知道用户级线程的工作状况,也许一个线程阻塞了其他线程仍然可以工作。借此引出内核级线程的概念,也就是把TCB放入内核中,让OS对线程进行调度,并发性更好。

    操作系统支持和管理内核线程。通常,用户线程跟内核线程相比,创建和管理要更快,因为它不需要内核干预(再次说明内核不知道用户线程的存在)。

    内核级线程概念

    从用户级线程出发,将一个栈变成一套栈:用户栈和内核栈。TCB在内核中,同时内核栈与用户栈相关联。进入内核态的唯一方式就是中断。同理,从内核态回到用户态的方式是中断返回iret。从用户栈到内核栈通过硬件实现(推测),而内核栈中保存了用户栈的位置。对于内核级线程的切换,每个线程对应了一套栈,通过TCB进行切换。内核级线程的切换与进程的切换大体上类似,只是不涉及到资源的切换。内核级线程能够更好地利用多核的特性,但是相应的由于要进入内核中,开销也会变大。所以一般采用用户级线程+内核级线程的方式,既保证了灵活性,也保证了并发能力。

    如何创建内核级线程?

    创建TCB

    为内核栈和用户栈申请空间

    初始化内核栈:用户栈的位置,状态寄存器组,IP,CS,二级中断返回指令

    将TCB与内核栈关联起来

    线程状态就绪

    开始调度

    有三种不同模型将用户级线程和内核级线程关联起来:

    多对一模型将许多用户线程映射到一个内核线程,但不兼容多处理器

    当多个用户线程映射到一个内核线程,当任意用户线程阻塞都会导致内核线程阻塞,这样即使从属于该内核线程的其它用户线程仍可以运行,但是因为CPU已被剥夺(内核线程是系统资源的持有者),使得能够执行的线程也执行不了

    一对一模型将每个用户线程映射到一个相应的内核线程;

    限制了用户线程数量,因为内核线程的数量是有限的,有些Unix系统的进程上限是1024

    多对多模型将多个用户线程在同样(或更少)数量的内核线程之间切换(二级模型:多对多+一对一)。

    绝大多数现代操作系统提供对内核线程的支持,其中有Windows 98/ NT /2000 /XP ,还包括 Solaris 和Linux。

    线程库为应用程序员提供了创建和管理线程的 API ,通常有三种主要的线程库: POSIX Pthread API ,Windows 系统的 Win32 线程以及 Java 线程。

    多线程程序为程序员带来了许多挑战,包括系统调用fork()和exec()的语义。

    其他事项包括线程取消、信号处理和线程特定数据。Java 丰富的API解决了大部分线程问题。

    线程取消:异步取消(线程立刻被取消)和延迟取消(告知线程你要被取消了,线程自己找个安全时间点取消)

    信号处理:同步接受信号(信号是由进程自身产生的,例如进程自己访问了一个非法地址)和异步接受信号(信号是从外部来的,例如命令行正在跑一个程序,程序员利用ctrl+c强行中断了这个程序,这个程序异步接收了中断信号)

    进程与线程的比较

    • A process cannot share the same memory space whereas; threads can share memory and files. 资源共享
    • It takes more time to create a process whereas; it takes less time to create a thread. 创建开销
    • The process takes more time to complete the execution and termination whereas; thread takes less time to terminate. 启动开销
    • Process execution is slow, but threads execute very fast. 执行速度
    • Context switching time between two processes is much whereas; context switching time between two threads is less as compared to the process. 上下文切换开销
    • Implementing the communication between two processes is more difficult, but communication between the two threads is easy to implement because threads share the memory. 通信难度
    • The process requires more resources to execute whereas; the thread requires fewer resources to execute. Therefore, the thread is called a lightweight process. 执行开销 LWP轻量级进程
    • System calls are required to communicate with each process, but in the case of a thread, system calls not necessary. 用户级线程对内核不可见
    • The loosely coupled process, but tightly coupled threads.
    • A process is not suitable for parallel activity-based whereas threads are suitable for the parallel activity.

    CPU调度

    CPU 调度(短期调度)的任务是从就绪队列中选择一个进程,并为其分配 CPU。

    总的来说,时间是进程最看重的指标。进程想要最短的周转时间,最短的等待时间,最短的响应时间,并且系统想要尽量减少内耗,增大吞吐量。当然,不同种类的进程要求不一样,这就催生出不同侧重点的调度算法。但有一些期望客观上存在矛盾。例如响应时间越短,切换的次数就要越多,切换所造成的开销就越大,系统内耗就越大,吞吐量就会降低,最终导致进程的平均周转时间增加。如何综合上述因素去调度进程是一个很复杂的问题。

    先来先服务 (FCFS) 调度是最简单的调度算法,但是它会使得短进程等待长进程。

    短作业优先 (SJF)调度(实际上是下一个最短CPU区间调度算法)可证明是最佳的,它提供了最短平均等待时间。但实现 SJF 调度很困难,因为无法确定下一个 CPU 区间的长度。于是可以用近似SJF调度算法,用历史数据去估计下一个CPU区间长度,该方法被称为指数平均。SJF 算法是通用优先级调度算法(将 CPU 简单地分配给具有最高优先级的进程)的特例。

    优先级调度和 SJF 调度会产生饥饿,而老化技术(逐渐增加在系统中等待很长时间的进程的优先级)可阻止饥饿。

    轮转法 (RR) 调度对于分时(交互)系统更为合适。 RR 调度让就绪队列的第一个进程使用 CPU 的q个时间单元,这里q是时间片。在q时间单元之后,如果该进程还没有释放CPU ,那么它被抢占并放到就绪队列的尾部。该算法的主要问题是选择时间片。如果时间片太大,那么 RR 调度就成了 FCFS 调度;如果时间片太小,那么因上下文切换而引起的调度开销就过大。

    FCFS 算法是非抢占的,而 RR 算法是抢占的。 SJF 和优先级算法可以是抢占的,也可 以是非抢占的。

    多级队列算法允许针对各种类型的进程使用不同的调度算法。最为常用的模型包括使用RR调度的前台交互队列,以及使用 FCFS 调度的后台批处理队列。

    多级反馈队列允许进程在队列之间迁移。

    许多当前的计算机系统支持多处理器,并允许每个处理器独立地进行调度(对称多多处理器SMP)。通常, 每个处理器维护自己的私有进程(或线程)队列,它们都可以运行。

    与多处理器调度相关问题包括:

    处理器亲和性:SMP系统试图避免将进程从一个处理器移至另一个处理器,而是努力使一个进程在同一个处理器上运行(处理器缓存命中);

    负载平衡

    如果操作系统在内核级支持线程,那么调度的是内核线程而不是进程。 Solaris和Windows XP 就是这样的系统,它们采用抢占的、基于优先级的调度算法,并支持实时线程。 Linux 进程调度也使用基于优先级算法,井提供实时支持。这三种操作系统通常偏爱交互进程而不是批处理进程或 CPU 约束进程。Java规范中没有严格定义线程的调度。

    因为有多种不同的调度算法可用,所以需要某种方法来选择它们。分析方法使用数学分析以确定算法性能。模拟方法通过对代表性的进程采用调度算法模拟并计算其性能来确定优劣。不过,模拟最多也只是提供对真实系统性能的近似,评估调度算法唯一可靠的技术是在真实系统上的实现算法并在真实环境中进行性能跟踪。

    死锁

    死锁条件(与如何打破)

    • 资源互斥使用(让资源变成可共享式…不太可能,因为这是资源的某种特性)
    • 保持和请求(预先分配资源,但利用率较低)
    • 非抢占(变得可抢占,当进程申请一个暂时不可获得的资源,那么它已分配的资源就可以被抢占,对于CPU寄存器可以这么处理)
    • 循环等待(对所有资源类型进行完全排序,且要求每个进程按递增顺序来申请资源)

    死锁的解决措施

    死锁预防:确保至少一个必要条件不成立,限制如何申请资源的方法,但是资源利用率普遍不高

    死锁避免:OS事先得到有关进程申请资源和使用资源的额外信息,来判断申请的可行性

    ​ 安全状态:系统存在一个安全序列,按照这个序列分配资源,系统就能避免死锁

    银行家算法:让系统一直保持安全状态的前提下处理进程的资源请求

    死锁检测:得到有关进程申请资源和使用资源的额外信息来检查系统状态以确定死锁是否发生和死锁恢复

    死锁检测算法:己知 P 现在不参与死锁(因为Request<=Work) ,因此可以乐观地认为 P不再需要更多资源以完成其任务,它会返回其现已分配的所有资源。如果假定的不正确,那么稍后会发生死锁。下次调用死锁算法时,就会检测到死锁状态。

    死锁忽略:OS不作任何保证,人工重启

    友情,恋爱,推理,因为有当初的约定才努力不懈。
  • 相关阅读:
    如何进入闷声发大财的传统企业做数据分析工作,帮助企业做数字转型?
    做一个最好的自己,不盲目学数据分析
    sql server如何判断数据库是否存在
    c++引用深入探讨
    VirtualBox 安装ghost版windows XP
    QT透明显示文字
    CSAPP
    随机颜色的生成
    远程桌面如何传递声音的原理
    递归求解全排列
  • 原文地址:https://www.cnblogs.com/ziyanblog/p/15382942.html
Copyright © 2011-2022 走看看