操作系统简记

1.操作系统四个特性:并发,共享,虚拟,异步

2.处理机包括中央处理器CPU,主存储器等

3.进程的定义:具有独立功能的程序在一个数据集合上运行的过程,他是系统进行资源分配盘和调度的一个独立单位。

  • 进程控制块PCB:作用:用来描述进程的基本情况和活动过程,进而控制和管理进程。
    • 组成:由程序段,数据段,pcb组成
    • 创建进程:创建进程中的PCB;撤销进程:撤销进程中的PCB
  • 进程和程序的不同
    • 并发性:进程拥有,程序没有。
    • 动态性:进程是动态的,程序是静态的。
    • 独立性和异步性。

4.进程基本状态和转换:

 

PS:创建和退出不是进程的状态。阻塞也叫等待,等待和就绪的区别:等待是等待除CPU以外的资源,而就绪等待的是CPU资源。

  就绪状态 -> 运行状态:处于就绪状态的进程被调度后,获得处理机资源(分派处理机时间片),于是进程由就绪状态转换为运行状态。

  运行状态 -> 就绪状态:处于运行状态的进程在时间片用完后,不得不让出处理机,从而进程由运行状态转换为就绪状态。此外,在可剥夺的操作系统中,当有更高优先级的进程就 、 绪时,调度程度将正执行的进程转换为就绪状态,让更高优先级的进程执行。

  运行状态 -> 阻塞状态:正在执行的进程因发生某等待事件而无法执行,进程就从运行状态转换为阻塞状态。如进程提出I/O请求而变成等待外部设备传输信息的状态,进程申请资源(如外部设备)得不到满足时变成等待资源状态,进程运行中出现了故障(程序出错或主存储器读写错等)变成等待干预状态等等;进程以系统调用的形式请求操作系统提供服务,这是一种特殊的、由运行用户态程序调用操作系统内核过程的形式。

  当进程等待的事件已经发生,如I/O操作完成,资源得到满足或错误处理完成时,中断处理程序必须把相应进程的状态由阻塞状态转换为就绪状态;再由系统进程调度程序在适当的时候将该进程转为执行状态。

  进程的创建和终止

  • 创建过程:申请空白的PCB,填写信息-->为进程分配运行时所需的资源-->进程变为就绪状态,插入就绪队列
  • 终止过程:等待操作系统善后处理-->将PCB清零,空间返还系统。

5.进程同步:

基本概念:

  • 临界资源:一次仅允许一个进程使用的资源,属于临界资源的硬件有打印机,磁带机等,软件有消息队列,变量,数组,缓冲区等,进程之间采取互斥方式实现对这种资源的共享。
  • 临界区:每个进程中访问临界资源的那段代码称为临界区。无论是硬件临界资源还是软件临界资源,进程都必须互斥的对它进行访问(所以每次想要访问临界区的资源的时候,必须确保它没有被人访问)
  • 同步机制遵循的规则:①:空闲让进②:忙则等待③:有限等待④:让权等待。
  • 线程同步的方式主要有以下四种:临界区(CriticalSection)、互斥量(Mutex)、信号量(Semaphore)、事件(Event)。
  • #
    1)临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。在任意时刻只允许一个线程对共享资源进行访问,如果有多个线程试图访问公共资源,那么在有一个线程进入后,其他试图访问公共资源的线程将被挂起,并一直等到进入临界区的线程离开,临界区在被释放后,其他线程才可以抢占。
    
    2)互斥量:采用互斥对象机制。只有拥有互斥对象的线程才有访问公共资源的权限,因为互斥对象只有一个,所以能保证公共资源不会同时被多个线程访问。互斥不仅能实现同一应用程序的公共资源安全共享,还能实现不同应用程序的公共资源安全共享。
    
    3)信号量:它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目。
    
    4)事件:通过通知操作的方式来保持线程的同步,还可以方便实现对多个线程的优先级比较的操作。
    四种进程同步方式简介

6.进程通信(IPC):

  1.Linux进程通信的3种高级方式

  • 共享存储器系统:共享某些数据结构或者共享某个存储区。这里面分为:共享数据结构(生产者消费者问题),共享存储区(划分一块内存,用于共享,由进程直接管理)
  • 管道通信系统:由一个读进程和一个写进程实现共享。发送进程以字符流的形式将数据送入管道,接收进程从管道接收数据,利用管道进行通信。
  • 消息传递系统:①直接通信方式:利用os直接将消息发送出去。②间接通信方式:发送和接收进程通过中间实体(邮箱)的方式进行发送和接收。这个方法不借用任何共享存储或数据结构。
  • 补充:
  • # 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
    
    # 有名管道 (named pipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
    
    # 信号量( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
    
    # 消息队列( message queue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
    
    # 信号 ( sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
    
    #共享内存( shared memory):共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的IPC方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。# 套接字( socket ) : 套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。
    
    管道的主要局限性正体现在它的特点上:
    只支持单向数据流;
    只能用于具有亲缘关系的进程之间;
    没有名字;
    管道的缓冲区是有限的(管道制存在于内存中,在管道创建时,为缓冲区分配一个页面大小);
    管道所传送的是无格式字节流,这就要求管道的读出方和写入方必须事先约定好数据的格式,比如多少字节算作一个消息(或命令、或记录)等等;
    通信方式补充

     

7.线程:作为调度和分派的基本单位。

  进程和线程的比较:

  • 调度的基本单位:进程是独立调度和分配的基本单位,能独立运行,切换代价大;线程作为调度和分配的基本单位,能独立运行,切换代价小;进程的切换回导致线程的切换,而同一个进程中线程的切换对进程没有影响,但是不同进程中的线程相互切换会导致进程切换。
  • 并发性:进程间可以并发执行,多个线程也能并发执行,一个进程的所有线程也能并发执行。
  • 拥有资源:进程可以拥有资源,作为系统中拥有资源的一个基本单位(PCB);线程不拥有系统资源,只有本有够自己运行的资源。线程允许多个线程共享该进程的所有的资源。
  • 进程的系统开销大,独立性高,线程开销小,独立性比较差。

  线程的实现方式:

  • 内核支持线程:无论系统进程还是用户进程都是在操作系统内核下运行的。
  • 用户级线程:在用户空间中实现的,用户级线程和内核无关。
  • #
    1)内核支持线程是OS内核可感知的,而用户级线程是OS内核不可感知的。
    
    2)用户级线程的创建、撤消和调度不需要OS内核的支持,是在语言(如Java)这一级处理的;而内核支持线程的创建、撤消和调度都需OS内核提供支持,而且与进程的创建、撤消和调度大体是相同的。
    
    3)用户级线程执行系统调用指令时将导致其所属进程被中断,而内核支持线程执行系统调用指令时,只导致该线程被中断。
    
    4)在只有用户级线程的系统内,CPU调度还是以进程为单位,处于运行状态的进程中的多个线程,由用户程序控制线程的轮换运行;在有内核支持线程的系统内,CPU调度则以线程为单位,由OS的线程调度程序负责线程的调度。
    
    5)用户级线程的程序实体是运行在用户态下的程序,而内核支持线程的程序实体则是可以运行在任何状态下的程序。
    用户级线程和内核级线程的区别

     

8.用户态和核心态的区别:

  1.内核态与用户态是操作系统的两种运行级别,,当程序运行在3级特权级上时,就可以称之为运行在用户态,因为这是最低特权级,是普通的用户进程运行的特权级,大部分用户直接面对的程序都是运行在用户态;反之,当程序运行在0级特权级上时,就可以称之为运行在内核态。运行在用户态下的程序不能直接访问操作系统内核数据结构和程序。当我们在系统中执行一个程序时,大部分时间是运行在用户态下的,在其需要操作系统帮助完成某些它没有权力和能力完成的工作时就会切换到内核态。

  补充了解“特权级”概念:

  • #
         熟悉Unix/Linux系统的人都知道,我们创建一个子进程时,是通过调用fork函数来实现的。事实上,fork的工作实际上是以系统调用的方式完成进程创建功能的,具体的工作是由sys_fork负责实施。对于任何操作系统来说,创建一个新的进程都是属于核心功能,因为它要做很多底层细致地工作,消耗系统的物理资源,比如分配物理内存,从父进程拷贝相关信息,拷贝设置页目录页表等等,这些显然不能随便让哪个程序就能去做,于是就自然引出特权级别的概念,显然,最关键性的权力必须由高特权级的程序来执行,这样才可以做到集中管理,减少有限资源的访问和使用冲突。
    
      特权级显然是非常有效的管理和控制程序执行的手段,因此在硬件上对特权级做了很多支持,就Intelx86架构的CPU来说一共有0~3四个特权级,0级最高,3级最低,硬件上在执行每条指令时都会对指令所具有的特权级做相应的检查,相关的概念有CPL、DPL和RPL,这里不再过多阐述。硬件已经提供了一套特权级使用的相关机制,软件自然就是好好利用的问题,这属于操作系统要做的事情,对于Unix/Linux来说,只使用了0级特权级和3级特权级。也就是说在Unix/Linux系统中,一条工作在0级特权级的指令具有了CPU能提供的最高权力,而一条工作在3级特权级的指令具有CPU提供的最低或者说最基本权力。
    特权级概念

     

  2.通常三种情况会导致用户态到内核态的切换:

  1)系统调用

  这是用户态进程主动要求切换到内核态的一种方式,用户态进程通过系统调用申请使用操作系统提供的服务程序完成工作,比如前例中fork()实际上就是执行了一个创建新进程的系统调用。而系统调用的机制其核心还是使用了操作系统为用户特别开放的一个中断来实现,例如Linux的int80h中断。

  2)异常

  当CPU在执行运行在用户态下的程序时,发生了某些事先不可知的异常,这时会触发由当前运行进程切换到处理此异常的内核相关程序中,也就转到了内核态,比如缺页异常。

  3)外围设备的中断

  当外围设备完成用户请求的操作后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条即将要执行的指令转而去执行与中断信号对应的处理程序,如果先前执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到内核态的切换。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。

  这3种方式是系统在运行时由用户态转到内核态的最主要方式,其中系统调用可以认为是用户进程主动发起的,异常和外围设备中断则是被动的。

9.用户栈和内核栈的区别:

  操作系统中,每个进程会有两个栈,一个用户栈,存在于用户空间,一个内核栈,存在于内核空间。当进程在用户空间运行时,cpu堆栈指针寄存器里面的内容是用户堆栈地址,使用用户栈;当进程在内核空间时,cpu堆栈指针寄存器里面的内容是内核栈空间地址,使用内核栈。

  内核栈是内存中属于操作系统空间的一块区域,其主要用途为:

  1)保存中断现场,对于嵌套中断,被中断程序的现场信息依次压入系统栈,中断返回时逆序弹出;

  2)保存操作系统子程序间相互调用的参数、返回值、返回点以及子程序(函数)的局部变量。

  用户栈是用户进程空间中的一块区域,用于保存用户进程的子程序间相互调用的参数、返回值、返回点以及子程序(函数)的局部变量。

  PS:那么为什么不直接用一个栈,何必浪费那么多的空间呢?

  1)如果只用系统栈。系统栈一般大小有限,如果中断有16个优先级,那么系统栈一般大小为15(只需保存15个低优先级的中断,另一个高优先级中断处理程序处于运行),但用户程序子程序调用次数可能很多,那样15次子程序调用以后的子程序调用的参数、返回值、返回点以及子程序(函数)的局部变量就不能被保存,用户程序也就无法正常运行了。

  2)如果只用用户栈。我们知道系统程序需要在某种保护下运行,而用户栈在用户空间(即cpu处于用户态,而cpu处于核心态时是受保护的),不能提供相应的保护措施(或相当困难)。

10.内存池,进程池,线程池:

  首先介绍一个概念“池化技术”:提前保存大量的资源,以备不时之需以及重复使用。池化技术应用广泛,如内存池,线程池等。

  由于在实际应用当做,分配内存、创建进程、线程都会设计到一些系统调用,系统调用需要导致程序从用户态切换到内核态,是非常耗时的操作。因此,当程序中需要频繁的进行内存申请释放,进程、线程创建销毁等操作时,通常会使用内存池、进程池、线程池技术来提升程序的性能。

  进程池与线程池同理。

  线程池:线程池的原理很简单,类似于操作系统中的缓冲区的概念,它的流程如下:先启动若干数量的线程,并让这些线程都处于睡眠状态,当需要一个开辟一个线程去做具体的工作时,就会唤醒线程池中的某一个睡眠线程,让它去做具体工作,当工作完成后,线程又处于睡眠状态,而不是将线程销毁。

  内存池:内存池是指程序预先从操作系统申请一块足够大内存,此后,当程序中需要申请内存的时候,不是直接向操作系统申请,而是直接从内存池中获取;同理,当程序释放内存的时候,并不真正将内存返回给操作系统,而是返回内存池。当程序退出(或者特定时间)时,内存池才将之前申请的真正内存释放。

11.死锁

  概念:计算机系统系统的资源分配策略不当,更常见的可能是程序员写的程序有错误等,则会导致进程因竞争资源不当而产生死锁

  死锁产生主要原因:

    1)因为系统资源不足。

    2)进程运行推进的顺序不合适。

    3)资源分配不当等。

  产生死锁的四个必要条件:

    1)互斥条件:一个资源每次只能被一个进程使用。

    2)请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。

    3)不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。

    4)循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

    PS:只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁

  死锁的解除和预防:

    处理死锁的策略

      1.忽略该问题。例如鸵鸟算法

      2.检测死锁并且恢复

      3.仔细对资源进行分配可以避免死锁

      4.通过破除死锁四个必要条件之一,来防止死锁产生

                     对待死锁的四个策略详细:

(1) 死锁预防:破坏导致死锁必要条件中的任意一个就可以预防死锁。例如,要求用户申请资源时一次性申请所需要的全部资源,这就破坏了保持和等待条件;将资源分层,得到上一层资源后,才能够申请下一层资源,它破坏了环路等待条件。预防通常会降低系统的效率。

(2) 死锁避免:避免是指进程在每次申请资源时判断这些操作是否安全,例如,使用银行家算法。死锁避免算法的执行会增加系统的开销。

(3) 死锁检测:死锁预防和避免都是事前措施,而死锁的检测则是判断系统是否处于死锁状态,如果是,则执行死锁解除策略。

(4) 死锁解除:这是与死锁检测结合使用的,它使用的方式就是剥夺。即将某进程所拥有的资源强行收回,分配给其他的进程。

死锁的避免:

死锁的预防是通过破坏产生条件来阻止死锁的产生,但这种方法破坏了系统的并行性和并发性。
死锁产生的前三个条件是死锁产生的必要条件,也就是说要产生死锁必须具备的条件,而不是存在这3个条件就一定产生死锁,那么只要在逻辑上回避了第四个条件就可以避免死锁。

避免死锁采用的是允许前三个条件存在,但通过合理的资源分配算法来确保永远不会形成环形等待的封闭进程链,从而避免死锁。该方法支持多个进程的并行执行,为了避免死锁,系统动态的确定是否分配一个资源给请求的进程。方法如下:

1.如果一个进程的当前请求的资源会导致死锁,系统拒绝启动该进程;

2.如果一个资源的分配会导致下一步的死锁,系统就拒绝本次的分配;

12.进程调度算法

13.内存管理

14.页面置换算法

未完待续

参考博客:http://www.cnblogs.com/Kobe10/p/5666439.html

     http://www.cnblogs.com/qiaozhoulin/p/4788316.html

    

 

posted @ 2018-03-10 12:46  木心熊  阅读(241)  评论(0编辑  收藏  举报