【多任务编程-基础知识】

进程的定义和性质 

1960年在MIT的MULTICS和IBM公司的TSS/360系统中提出
名称
    MIT称进程(Process)
    IBM公司称任务(Task)
    Univac公司称活动(Active)
定义 
    由数据结构以及在其上执行的程序(语句序列)组成
    是程序在这个数据集合上的运行过程
    是操作系统进行资源分配和保护的基本单位

  
进程的属性

结构性
        进程包含了数据集合和运行于其上的程序 
共享性 
        同一程序同时运行于不同数据集合上时,构成不同的进程 
动态性 
        进程是程序在数据集合上的一次执行过程,是动态概念 
        同时,它还有生命周期,由创建而产生,由撤销而消亡 
独立性 
        进程既是系统中资源分配和保护的基本单位,也是系统调度的独立单位(单线程进程) 
制约性 
        并发进程之间存在着制约关系需要相互等待或互通消息  
并发性
        进程可以并发地执行 

可再入程序 和 不可再入程序

具有多进程(线程)的操作系统必须考虑可再入问题
可再入程序
“可再入”程序是指能被多个程序同时调用的程序它是纯代码的,即它在执行中自身不改变(例如只是用了堆栈变量)
不可再入程序 
被调用过程中具有自身修改,在调用它的程序退出以前是不允许其它程序来调用它的         
比如操作共享变量/内存等 也称可在用程序
程序与计算(程序的执行)不再一一对应

进程的内存映像 

进程时机
        当一个程序进入计算机的主存储器进行计算就构成了进程
进程上下文(Context)
        操作系统中把进程物理实体和支持进程运行的环境合称为进程上下文(context) 
        系统调度新进程占有处理器时,新老进程随之发生上下文切换 
        进程的运行被认为是在上下文中执行 
进程上下文组成
        用户级上下文     由用户程序块、用户数据块(含共享数据块)和用户堆栈组成的进程地址空间  
        系统级上下文     包括进程的标识信息、现场信息和控制信息,进程环境块,以及系统堆栈等组成的进程地址空间 
        寄存器上下文     由程序状态字寄存器和各类控制寄存器、地址寄存器、通用寄存器组成 

进程内存映像(Process Image)

进程程序块 
        纯代码,作为一种系统资源可被多个进程共享 
进程数据块 
        全局变量、局部变量和常量等 
系统/用户堆栈 
        过程调用或系统调用时的地址存储和参数传递 
进程控制块 (PCB)
        用来存储进程的标志信息、现场信息和控制信息。进程创建时,建立一个PCB;进程撤销时,回收PCB,它与进程一一对应 

进程控制块 (PCB)

每一个进程都有一个也只有一个进程控制块
        PCB = (Process Control Block) 操作系统中最为重要的数据结构 
进程控制块 内容
        标识信息
                唯一地标识一个进程 ,包括进程标识符、父进程的标识符、用户进程名、用户组名等   
        现场信息 
                保留一个进程在运行时存放在处理器现场中的各种信息 
                通用寄存器的内容、控制寄存器(如PSW寄存器)的内容、用户堆栈指针、系统堆栈指针 
        控制信息 
                用于管理和调度一个进程,包括调度相关信息,进程组成信息,进程间通信信息,进程在二级存储器的地址,CPU资源的使用信息,资源清单等

windows进程以及它控制和使用的资源 

进程的状态和转换 -三态模型

 三态模型

  • 运行(running)态:占有处理器正在运行 
  • 就绪(ready)态:指具备运行条件,等待系统分配处理器以便运行 
  • 等待(wait)态:由称为阻塞(blocked)态或睡眠(sleep)态,指不具备运行条件,正在等待某个事件的完成 

运行态—→等待态:等待使用资源;如等待外设传输;等待人工干预
等待态—→就绪态:资源得到满足;如外设传输结束;人工干预完成
运行态—→就绪态:运行时间片到;出现有更高优先权进程。
就绪态—→运行态:CPU空闲时选择一个就绪进程。

进程的状态和转换 -五态模型

五态模型
        在一个实际的系统里进程的状态及其转换比三态会复杂一些,例如引入专门的新建态(new)和退出态(exit)
 
在复杂的操作系统中还会有其他更多的状态

五态模型状态转化

·NULL-→新建态
    执行一个程序,创建一个子进程。 
·新建态-→就绪态
    当操作系统完成了进程创建的必要操作,并且当前系统的性能和虚拟内存的容量均允许。
·运行态-→终止态
    当一个进程到达了自然结束点,或是出现了无法克服的错误,或是被操作  系统所终结,或是被其他有终止权的进程所终结。
·就绪态-→终止态
    未在状态转换图中显示,但某些操作系统允许父进程终结子进程。
·终止态-→NULL
    完成善后操作。
·等待态-→终止态
    未在状态转换图中显示,但某些操作系统允许父进程终结子进程。

windows线程状态

引入多线程技术的动机 

进程切换的开销大,频繁的进程调度将耗费大量处理器时间。
进程之间通信的代价大,每次通信均要涉及通信进程之间以及通信进程与操作系统之间的切换。
进程之间的并发性粒度较粗,并发度不高 过多的进程切换和通信使得细粒度的并发得不偿失。
不适合并行计算和分布并行计算的要求。
        对于多处理器和分布式的计算环境来说,进程之间大量频繁的通信和切换,会大大降低并行度。
不适合客户/服务器计算的要求。
        对于C/S结构来说,那些需要频繁输入输出并同时大量计算的服务器进程(如数据库服务器、事务监督程序)很难体现效率。
轻量级进程(Light Weight Process) 
线程(Thread)

线程特点

  • 线程被进程拥有,是系统进行处理器调度的基本单位 
  • 同一个进程中的所有线程共享进程获得的主存空间和资源,但不拥有资源 
  • 当线程不运行时,有一个受保护的线程上下文,用于存储现场信息 
  • 拥有自己的执行堆栈
  • 同一进程的多个线程可在单/多处理器上并发或并行地运行 
  • 线程也是程序在相应数据集上的一次执行,由创建而产生,至撤销而消亡,有其生命周期 
  • 线程拥有完整的执行状态(运行、就绪、…) 
  • 系统创建线程的代价比进程小的多 

线程内存映象和内容

线程存在于进程之中,除了堆栈和CPU状态外,全部数据是共享的
线程内存映象

线程的实现方法

从实现的角度看,线程可以分成用户级线程ULT(如,Java和Informix)和内核级线程KLT(如OS/2)。也有一些系统(如,Solaris)提供了混合式线程,同时支持两种线程实现 

windows进程设计的目标是提供对不同操作系统环境的支持,具有:多任务(多进程)、多线程、支持SMP、能在任何可用CPU上运行的特点。由内核提供的进程结构和服务相对来说简单、适用,其重要的特性如下:
1)进程和线程是用对象来实现的(内核对象)
2)一个可执行的进程可以包含一个或多个线程
3)进程或线程两者均有内在的同步设施
4)线程是基本的调度单位,能够被系统中断,系统得以调度其他线程
5)进程是不活泼的,只是线程的容器
6)一个进程内的线程共享同一块内存地址,文件句柄等资源

中断 -进程切换调度的根源

中断是指程序执行过程中,当发生某个事件时,中止CPU上现行程序的运行,引出处理该事件的程序执行的过程 
中断源
I/O 操作、 硬件故障、电源掉电、数组越界、被零除、电压偏低、定时器、请求操作系统服务、实时设备 等
中断分类
硬中断 - 设备中断
软中断 - 系统调用(Trap)
中断是现代操作系统实现并发性的基础之一 
中断是激活操作系统,进行系统调度的唯一方法 

进程的控制 -- 进程切换与模式切换 

中断是激活操作系统的唯一方法 
它暂时中止当前运行进程的执行,把处理器切换到操作系统的控制之下,而当操作系统获得了处理器的控制权之后,它就可以实现进程切换 .
进程切换定义
进程切换就是让处于运行态的进程中断运行,让出处理器,这时要做一次进程上下文切换、即保存老进程的状态而装入被保护了的新进程的状态,以便新进程运行 

 * 一次进程切换就包含发生一次进程调度

模式切换 - 内核态和用户态

特权指令(Privileged Instructions)和非特权指令

  • 特权指令是指那些只能提供给操作系统的核心程序使用的指令 

            如启动输入输出设备、设置时钟、控制中断屏蔽位、清内存等。

  • 操作系统能执行全部指令(特权指令和非特权指令)
  • 一般用户只能执行非特权指令

            防止用户程序使用特权指令对系统造成破坏
            防止用户程序竞争使用外围设备而导致I/O混乱
处理器状态
大多数系统把处理器状态简单的划分为
内核状态(又称特权状态)
    当处理器处于内核状态时,可以执行全部指令
    使用所有资源,并具有改变处理器状态的能力
用户状态(又称目标状态)    
    当处理器处于用户状态时,只能执行非特权指令

Pentium的处理器状态有四种 Ring0-Ring3

Windows操作系统只使用了Ring0和Ring3
中断会导致从用户状态向内核状态转换 
 

系统调用的实施

系统调用使操作系统转入内核态
系统调用等于软中断(引起Trap)
系统调用引起进程调度

Win32系统调用包括

Win32文件操作 

Win32内核对象操作

Win32GDI操作

等等

 系统调用 例-WIN32 WriteFile & GDI

任务的优先级

优先级:根据任务的重要性不同,可以设定优先级
任务的优先级影响到调度程序将哪一个任务取出来作为要运行的任务
任务的优先级决定其重要程度,所以,高优先级的任务应该优先得到系统的资源(得到CPU,设备等)
Windows内核支持从0-31种的优先级(系统引导的时候创建唯一的0优先级任务用来将所有空闲RAM页面置0)
WindowsCE.Net内核支持256个优先级

Windows线程的优先级

每个线程都会被赋予一个从0-31的优先级号码
只要是高优先级的线程是可以调度的,系统绝对不会调度低优先级的(渴求调度Starvation)
系统引导的时候创建特殊的线程——0页线程,其优先级为0,当系统中没有任何其他线程运行时,0页线程负责将系统中所有的空闲RAM页面置0
进程内使用线程相对的优先级:空闲、低于正常、高于正常、最高、关键时间。
进程也根据具体情况被分为7个进程优先级类:空闲、低于正常、高于正常、最高、关键时间
线程的实际优先级是进程优先级类和进程内线程相对优先级的组合
正常优先级类的进程的基本优先级是5, 进程内正常优先级线程的优先级是8, 所以一个正常进程中的正常优先级线程的真正优先级是13

任务调度

按照某种原则把处理器分配给就绪进程或内核级线程
调度策略的优劣直接影响到整个系统的性能 
调度程序所使用的算法称为调度算法(scheduling algorithm)
调度主要功能

  • 记住进程(内核级线程)的状态 
  • 决定某个进程(内核级线程)什么时候获得处理器,以及占用多长时间 
  • 把处理器分配给进程(内核级线程)即进行进程(内核级线程)上下文切换 
  • 收回处理器 

调度算法要考虑因素

资源利用率
        使得CPU或其他资源的使用率尽可能高且能够并行工作 
响应时间
        使交互式用户的响应时间尽可能短,或尽快处理实时任务 
周转时间
        应使作业周转时间或平均作业周转时间尽可能短 
吞吐量
        吞吐量——使得单位时间处理的作业数尽可能多 
公平性
        确保每个用户每个进程获得合理的CPU份额或其他资源份额 

合作型多任务调度算法(Non-preemptive Multitasking )

各个任务共享CPU,由任务控制CPU的使用权。
中断服务可以中断一个任务,但是中断以后仍然回到原来的任务继续进行,直到任务自己放弃CPU。
不需要使用信号量同步保护,可使用不可重入函数,共享数据方便。
高优先级响应慢,依赖于其他任务何时放弃CPU 。
典型操作系统Windows 3.1 。

基于优先级抢占式调度算法(Preemptive Multitasking) 

由操作系统控制CPU的使用权。
最高优先级的任务一旦就绪,总能得到CPU。
不能直接使用不可重入函数,需要同步机制(信号量等的保护)
中断服务结束后,操作系统优先调度高优先级的任务。
任务级响应时间得到最优化,中断响应较快。
绝大部分的实时操作系统都使用这种调度算法。 

同一优先级时间片轮转 & 单调速率 

同一优先级时间片轮转
1)允许多个任务共享一个优先级
2)具有同等优先级的任务公平的享有CPU
3)在相同优先级的任务中使用时间片进行轮转
4)如果具有高优先级的任务,仍然遵循抢占式调度。
单调速率( RMS Rate Monotonic Scheduling )
1)根据任务的执行频率确定优先级。
2)任务执行频率高,则优先级越高
3)任务执行频率低,则优先级越低
4) CPU饥渴,执行频率低的任务可能得不到CPU

先来先服务 & 彩票调度

先来先服务
1)按照任务进入就绪队列的先后次序来分配处理器。
2)先进入就绪队列的进程优先被挑选。
3)运行进程一旦占有处理器将一直运行直到运行结束或阻塞。
4)效率不高,显然不利于I/O频繁的进程
彩票调度
1)为进程发放针对系统各种资源(如CPU时间)的彩票
2)当调度程序随机选择一张彩票,持有彩票的进程将获得系统资源
3)如果某些进程需要更多的机会,就可以被给予更多的额外彩票

常用操作系统调度

Linux提供符合了POSIX标准的调度策略,包括FIFO调度策略、时间片轮转调度策略和静态优先级抢占式调度策略。
Linux在用户态支持可抢占调度策略,而在核心态却不支持抢占式调度策略 (非内核级线程)
Windows9x/NT以线程为单位进行调度,支持抢占式优先级调度,同等优先级时间片轮转和FIFO调度策略。
传统Unix系统的主要设计目标是提供交互式的分时操作环境,因此调度算法在保证低优先级的后台作业不饿死的前提下,尽可能向交互式用户提供快速的响应 
传统Unix的低级调度采用多级反馈队列,对于每一个优先级队列采用时间片调度策略。系统遵从1秒抢占的原则,即一个进程运行了1秒还没有阻塞或完成的话,它将被抢占

使用多进程/多线程

多进程和多线程统称为多任务
多任务系统的益处:几乎同一时间内完成多项工作
多任务系统的缺点:从总时间上讲,使用多任务会使程序变慢
以下情况应该使用多任务

  •   具有大量的异步后台任务而不希望阻塞其他功能(比如用户界面)
  •   需要花大量的时间来测试I/O是否完成
  •   具有多个工作,但是各个工作之间无需作太多的同步,即可独立执行
  •   具有多个CPU的系统(SMP系统)
  •   实时的操作系统

应该用增加线程来解决编程问题,避免创建新的进程

并发任务的同步 - 问题

并发的几个任务同时访问了一个不可重入代码段,结果不可预期
并发程序在时间上错误的两种表现形式:结果不唯一或者永远等待 
哲学家就餐问题(永远等待)
描述:
有五个哲学家,他们的生活是交替地进行思考和就餐。哲学家们共一张圆桌,周围放有五张椅子,每人坐一张。在圆桌上有五个碗和五只筷子,当一个哲学家思考时,他不与同事交谈,饥饿时便试图取左、右最靠近他的筷子,但他可能一支都拿不到。只有在他拿到两支筷子时方能就餐。餐毕,放下筷子继续思考
问题:可能每个哲学家都拿起了一个筷子,而等拿那另外一只筷子就餐,造成了谁也不能就餐的死锁状态

机票问题  (结果不唯一)

假设一个飞机订票系统有两个终端,分别运行进程Tl和T2。该系统的公共数据区中的一些单元Aj(j=l,2,…)分别存放某月某日某次航班的余票数,而xl和x2表示进程T1和T2执行时所用的工作单元,程序如下:
售票进程 Ti ( i = 1, 2 ) 
        int Xi;
         {按旅客定票要求找到票源票数为Aj; Xi=Aj;};
        if (Xi >=1) {Xi = Xi - 1; Aj = Xi; 输出一张票;} else {输出票已售完};
由于T1和T2是两个可同时运行的并发进程,它们在同一个计算机系统中运行,共享同一批票源数据,因此可能出现如下所示的运行情况:
T1:    X1 = Aj;            X1 = nn ( nn > 0 )
T2:    X2 = Aj;            X2 = nn
T2:    X2=X2-1; Aj=X2;输出一张票;    Aj = nn-1
T1:    X1=X1-1; Aj=X1;输出一张票;    Aj = nn-1
显然此时出现了把同一张票卖给了两个旅客的情况,两个旅客可能各自都买到一张同天同次航班的机票,可是,Aj的值实际上只减去了1,造成余票数的不正确。特别是,当某次航班只有一张余票时,就可能把这一张票同时售给了两位旅客,显然这是不能允许的。 

任务的交互(Interaction Among Processes)——协作和竞争 

竞争关系:多个任务共用了一套计算机系统资源,因而,必然要出现多个任务竞争资源的问题。当多个任务竞争共享硬设备、变量、表格、链表、文件等资源时,可能导致处理出错 
任务的互斥(Mutual Exclusion)是解决进程间竞争关系的手段 
协作关系:某些任务为完成同一任务需要分工协作 
任务的同步(Synchronization)是解决任务间协作关系的手段。指一个任务的执行依赖于另一个进程的消息,当一个任务没有得到来自于另一个任务的消息时则等待,直到消息到达才被唤醒 
任务互斥关系是一种特殊的任务同步关系,即逐次使用互斥共享资源 

互斥和临界区 

售票管理系统之所以会产生错误,原因在于两个进程交叉访问了共享变量Aj. 我们把并发进程中与共享变量有关的程序段称为“临界区”(Critical Section) , 共享变量代表的资源叫“临界资源”(Critical Resource) ,由Dijkstra在1965年首先提出
如果能保证一个进程在临界区执行时,不让另一个进程进入相关的临界区,即各进程对共享变量的访问是互斥的,那么就不会造成与时间有关的错误 
对若干个进程共享一个变量的相关的临界区,调度和设计的原则

  •    一次至多一个进程能够在它的临界区内
  •    不能让一个进程无限地留在它的临界区内
  •    不能强迫一个进程无限地等待进入它的临界区
  •    进入临界区的任一进程不能妨碍正等待进入的其它进程的进展

概括:无空等待、有空让进、择一而入、算法可行。

使用互斥保证临界区安全

使用临界区有专门用于解决进程互斥问题系统不同
临界区只能允许一个任务进入,标记为“进入”
试图进入标记为“进入”状态的临界区的进程只能等待
对需要保护的临界区操作完成之后,进程离开临界区,

 对需要保护的票源进行互斥访问,则结果能够保证唯一了。

信号量与PV操作

1965年Dijkstra提出了新的同步工具 --- 信号量和P、V操作
原子操作是指操作系统中执行时不可中断的过程(Atomic Action)
PV操作 : 测试(Proberen)” 和“增量(Verhogen)”
PV操作只能是原子操作
二元信号量:仅允许取值为0和1,主要用于解决进程互斥问题原子操作解决了互斥的具体实现问题
一般信号量:允许取值为非负整数,用于解决进程间的同步问题

任务间通信 

并发进程之间的交往本质上是互相交换信息 
通信方式包括 

  •  信号通信机制(软中断 )(Event)
  •   共享文件通信机制  
  •   共享存储区通信机制 (Window内存映射文件等)
  •   消息传递通信机制(Message) 

 任务通信-信号(Signal )

信号机制又称软中断,是一种简单的通信机制。通过发送一个指定信号来通知进程某个异常事件发生 
可以分成OS标准信号和用户进程自定义信号,进程收到该信号后便可执行规定的操作 
OS标准信号是操作系统定义并处理的,如Unxi 的SIGCLD、SIGHUP、SIGKILL、SIGCHLD等
用户进程自定义信号是用户自行定义并处理的信号,如Windows中定义的各种EventHandle等
类似硬件中断但不分优先级,简单有效,但不能传送数据 
信号不但能从内核发给一个进程,也能由一个进程发给另一个进程 

任务通信-消息(Message)


死锁的发生

 如果在一个进程集合中的每个进程都在等待只能由该集合中的其他一个进程才能引发的事件,则称一组进程或系统此时发生了死锁 

死锁的解决方案

导致死锁的四个条件

  • 互斥条件(Mutual Exclusion) 进程应互斥使用资源,任一时刻一个资源仅为一个进程独占,若另一个进程请求一个已被占用的资源时,它被置成等待状态,直到占用者释放资源。
  • 占有和等待条件(Hold and Wait) 一个进程请求资源得不到满足而等待时,不释放已占有的资源。
  • 循环等待条件(Circular Wait) 存在一个循环等待链,其中,每一个进程分别等待它前一个进程所持有的资源,造成永远等待。
  • 不剥夺条件(No Preemption) 任一进程不能从另一进程那里抢夺资源,即已被占用的资源,只能由占用进程自己来释放。

解决死锁 ---- 打破四个条件

  • 通过强行规定任务获得资源的方式防止死锁:几个任务要访问资源A,B和C,任务以同样的次序获得和释放资源
  • 任务一次性请求所需要的资源,或要求被拒绝使用某一资源的任务,立即释放它所持有的所有其它资源,然后重新获得。

什么是优先级倒置 

优先级倒置是指在具有较低优先级的线程使用了互斥、关键部分或者旗语资源的情况下,造成具有较高优先级的进程被延迟执行(因为它们都争用同一个资源)

如何解决优先级倒置

优先级继承 (Priority Inheritance)

  • 设C为正占用某项共享资源的进程P和所有等待这个资源的进程的集合。
  • 找出这个集合中的最高优先级Pn
  • 把进程的优先级设成 Pn

优先级封顶 (Priority Ceiling)

  • 设C为正占用某项共享资源的进程P和所有等待这个资源的进程的集合。
  • 事先规定这个集合的优先级的上限Pn(Pn不一定是系统的最高优先级)
  • 在创建保护共享资源的信号量或者互斥量是,将Pn作为参数
  • 任何访问这个信号量或者互斥量的进程优先级提高为Pn

Windows CE.NET允许较低优先级的线程继承更关键线程的优先级,然后以较高优先级运行,直接它释放了所使用的资源 

 几种常见操作系统介绍

 几种常见嵌入式操作系统介绍

参考书籍
Windows核心编程
Win32多线程编程
 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值