操作系统——进程管理

前言

进程管理模块是操作系统中非常重要的部分。进程的调度算法,进程通信(PV操作,这好难!!),进程与线程的区别联系等等,需要仔细认真地学习,联系之前学的知识点,建立知识点的思维导图。

概要

多道程序设计、进程、线程、进程间的同步与互斥、进程调度、系统核心

1.多道程序设计

背景:一般程序是顺序执行的,这与人类的认知规律相符。试想,大多数人是不是偏好按顺序做事情,有条不紊。那程序的顺序执行有什么特点呢?

  1. 顺序性:处理机严格按照程序所规定的顺序执行,每个操作必须在下一个操作之前结束。
  2. 封闭性:程序一旦开始执行,那计算结果不受外界的影响,当程序的初始条件给定后,其后的状态只能由程序本身确定,只有本程序才能改变它。(就好比我按顺序做某件事情当然是不希望有其他的事情打捞到我啦)
  3. 程序执行结果的确定性:程序执行结果与时间无关性。(做的慢和做的快,只要我按程序的步骤一步一步执行,那么最后的结果是一样的,例如(2+3)*3+7,计算这个式子按顺序计算,慢点快点结果都是一样的)
  4. 程序执行结果的可再现性:如果程序在不同的时间执行,只要输入的初始条件相同,无论何时重复执行该程序都会得到相同的结果。

引入:顺序执行的资源利用率很低,早上起来刷牙和听早间新闻明明可以同时进行,但是非得按顺序先刷牙再听新闻,或是听完新闻再吃早饭。如果是我,我已经饿晕过去了。所以,为了提高计算机系统中各资源的利用效率,缩短作业的周转时间,在现代计算机中广泛采用多道程序技术,使多种硬件资源能并行工作。

多道程序设计特点:

  1. 独立性:每道程序在逻辑上是独立的,且执行速度与其他程序无关,执行的起止时间也是独立的
  2. 随机性:在多道程序环境下,程序和数据的输入和执行开始时间都是随机的。(因为你不知道之前做完哪个操作转换过来的,比如你是从刷完牙来的,也有可能是听完新闻来的)
  3. 资源共享性:输入输出设备、内存、信息等资源都会被各个程序共享。(你同时在听新闻和吃饭,不就是在共享你自己吗)

2.进程

2.1进程的概念

进程是具有独立功能的程序关于某个数据集合上的一次运行活动(妙哉,既表明了进程是程序+数据,有表明了进程是动态的,程序是静态的),是系统进行资源分配和调度的独立单位。

2.2程序和进程的区别
  • 进程能更真实地描述并发,而程序不能
  • 程序是静态的,进程是动态的
  • 进程有生命周期,有生有死,而程序是相对长久的
  • 一个程序可对应多个进程,反之亦然
2.4进程分类
  • 系统进程
  • 用户进程
  • 前台进程
  • 后台进程
  • CPU密集型进程
  • I/O密集型进程
2.5 进程的基本状态及其转换

七状态进程模型

  • 就绪模型(Ready):进程在内存且立即进入运行状态
  • 阻塞模型(Blocked):进程在内存等待某事件的出现
  • 阻塞挂起状态(Blocked,suspend):进程在外存并等待事件的出现
  • 就绪挂起状态(Ready,suspend):进程在外存,但只要进入外存,即可运行
  • 挂起(Suspend):把一个进程从内存转到外存
    • 阻塞->阻塞挂起:没有进程处于就绪状态或就绪进程要求更多的内存资源
    • 就绪->就绪挂起:有高优先级级阻塞进程(系统认为会很快就绪的)和低优先级就绪进程时,系统会选择挂起低优先级就绪进程
    • 运行->就绪挂起:对抢占式系统,当有高优先级阻塞挂起进程因事件出现而进入就绪挂起,系统可能会把运行进程转到就绪挂起状态。
  • 激活(Active):把一个进程从外存转到内存
    • 就绪挂起->就绪:没有就绪进程或就绪挂起进程优先级高于就绪进程
    • 阻塞挂起->阻塞:当一个进程终止结束后并释放足够多内存时,系统会把一个高优先级阻塞挂起(系统认为会很快出现所等待的事件)进程调入内存。

为什么会发生挂起?

内存不够了;用户希望挂起一个程序的执行,以便进行调试或关联资源使用;父进程请求

2.6进程控制块(PCB)

是什么(what):系统为了管理进程设置的一个专门的数据结构,用它来记录进程的各种属性,描述进程的动态变化过程。

为什么要有(why):系统利用PCB来控制和管理进程,所以PCB是系统感知进程存在的唯一标志。

so:进程与PCB是一一对应的

2.6.1PCB表的组织方式
  • 线性方式
  • 链接结构
  • 索引结构
  • 进程队列
2.7进程控制

其实是进程的状态间的转换,由原语完成

原语:完成某种特定功能的一段程序具有不可分割性或不可中断性

  • 创建原语:出生,填PCB表
  • 撤销原语:死亡,撤销PCB表
  • 阻塞原语:运行->阻塞
  • 唤醒原语:阻塞->就绪

3.线程模型

3.1引入

为什么会提出线程这个概念呢,进程不是资源调度和分配的基本单位吗,还需要线程啥事。不急,我们一步一步来分析:

首先,先复习一下进程的的两个基本属性:可拥有资源的独立单位;可独立调度和分派的的基本单位。正是它有了这两个属性,所以能够并发执行。但是,程序能够并发执行系统要做下面这些事:

  1. 创建进程:必须为其分配所需的所有资源(除了CPU,包括内存空间、I/O设备)还要建立相应的数据结构PCB
  2. 撤消进程:回收资源,撤销PCB
  3. 进程切换:在对进程进行切换的时候,要保留当前的CPU环境和设置新选中进程的CPU环境,这可要花不少CPU时间。想想,CPU的使用时间计费,看着都心疼。

要是把两个属性分开来,作为调度和分派的基本单位,轻装运行;作为拥有资源的基本单位,不频繁地进行切换。

3.2线程

what:线程是进程中的一个实体,是CPU调度和分派的基本单位。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源。

3.2.1 线程的属性(简要)
  • 状态转换:执行、就绪、阻塞
  • 共享所在进程的地址空间和其他资源
3.2.2 引入线程的好处
  • 新建和撤销一个进程所花费的时间少
  • 两个线程切换花费的时间少
  • 同一进程内的线程共享内存和文件,因此他们之间相互通信不需要调用内核
3.2.3 线程和进程的比较

不详细说了

调度;并发性;拥有资源;系统开销

3.2.4 线程的实现机制

有两类线程:核心级线程KLT用户级线程ULT

主要区别是是否内核参与了

4.系统内核

what:为了有效地控制和管理进程的运行,操作系统中必须设置一个统一的机构,提供支持进程运行的各种基本操作,这叫做系统内核。简称内核。

向上提供多个无中断的虚拟机器,在核心中不允许中断。

how:进入核心的唯一入口:中断

内核执行的特点:

  • 内核执行是连续的
  • 内核执行过程中在中断屏蔽状态下
  • 内核使用特权指令

5.进程调度

5.1批处理系统的进程调度算法

  • 先进先出(FIFO):非抢占
  • 最短作业优先(SJF):非抢占
  • 最短剩余时间优先(SRTN):抢占
  • 最高响应比优先(HRRN):非抢占

5.2 交互式系统的调度算法

  • 时间片轮转算法(RR):抢占
  • 最高优先级算法(HPF):抢占
  • 多级反馈队列:时间片和优先级互补,抢占
  • 最短进程优先(SPN):非抢占

6.同步与互斥

概要

  • 进程互斥
  • 进程同步
  • 信号量与PV操作
  • 经典IPC问题

6.1进程间的相互作用

有关系的进程称为相关进程,没有关系的称为无关进程

多道程序系统中并发运行的进程之间存在着相互制约关系,这种相互制约的关系称为进程间的相互作用。细分为:直接相互作用和间接相互作用

相关进程无关进程
直接相互作用发生不发生
间接相互作用发生发生

进程之间会竞争使用共享资源,它们之间必须相互协调,彼此之间交换信息,这叫做进程之间的简单通信。

6.1.1 进程的同步

进程同步是指进程之间一种直接的协同关系,是一些进程相互合作,共同完成一项任务。进程间的直接相互作用构成进程的同步。

6.1.2 进程的互斥

(1)进程互斥:顾名思义,对于一些共享资源,一次只能为一个进程服务,自然就产生了互斥关系

(2)临接区:系统中一些资源一次只允许一个进程使用,这类资源称为临界资源共享变量。

在进程中访问临界资源的那一段程序称为临界区。对于想进入临界区的进程构成了互斥关系。

6.1.3 同步机制

系统中设置解决进程同步的专门同步机制。已有的:硬件同步机制、信号量及PV操作、管程等。

进程同步机制——信号量和P、V操作

信号量semaphore:是一个特殊的变量,它的表面形式是一个整数变量附加一个队列。

struct semaphore

{

        int count;

        queueType queue;

}

二元信号量(解决互斥问题)

多元信号量(解决同步问题)

1)信号量的物理意义:

  • S>0表示有S个资源可用
  • S=0表示资源可用
  • S<0则|S|表示的等待队列中的进程的个数

P(S):申请一个资源

V(S):释放一个资源

2)注意事项:

  • 信号量的初值应该大于等于0
  • pv操作必须成对出现
  • 互斥操作时,同处一个进程;同步操作,不在同一进程出现
  • 同步P操作在互斥P操作之前,两个V操作无关紧要

P、V操作:原语操作

P(s)
{
    s.count--;
    if(s.count<0)
    {
        进程状态设为阻塞状态;
        并插入相应的等待队列s.queue末尾,
        直到有其他进程在S上执行V操作
    }

}
V(s)
{
    s.xount++;
    if(s.count<=0)
        {
            唤醒相应等待队列s.queue中等待的一个进程;
            令其状态为就绪状态,并将其插入到就绪队列。
        }
}

6.2 经典IPC问题

有了前面的理论基础,下面上几道经典题型,走过路过不要错过。

6.2.1读者写者问题

int rc=0;//读者数量

semaphore mutex=1;//控制对rc的访问(因为会有多个读者,读者数量的增减操作是要互斥的)

semaphore db=1;//控制对数据库的访问(读者在读数据库,写着就不能写数据库,反之亦然)

void reader(void)
{
    while(true)
    {
        P(mutex);
        rc=rc+1;
        if(rc==1) P(db);//第一个读者,对数据库的操作关门
        V(mutex);

        read_data_base();//读数据库
        
        P(mutex);
        rc=rc-1;
        if(rc==0)V(db);//最后一个读者,开门,释放对数据库的保护
        V(mutex);
    }
}


void writer(void)
{
    while(true)
    {
    P(db);//测试一下,看看能不能对数据库操作
    write_data_base();
    V(db);
    }
}

int rc=0;//读者的数量
semaphore mutex=1;//对rc互斥
semaphore db=1;//读者、写者对数据库的互斥
semaphore w=1;//标记谁先来

int main()
{
	cobegin
	reader();
	weiter();
	coend
 } 
 
 void reader()
 {
 	P(w);
 		P(mutex);
 			rc++;
 			if(rc==1) P(db);//关门 
 		V(mutex);
 	V(w);
 	read_data_base();
	P(mutex);
		rc--;
		if(rc==0)V(db);
	V(mutex);
	use_data_read();
 }
 
void writer(void)
{	think_up_data();
	P(w);
	P(db);
		write_data_base();
	V(db);
	V(w);
}
6.2.2哲学家就餐问题

#define N 5
#define LEFT (i+N-1)%N
#define RIGHT (i+1)%N
#define THINKING 0
#define EATING 1
#define HUNGRY 2
#typedef  int semaphore;
int state[N]=THINKING;//状态 
semaphore mutex=1;//临界区互斥 
semaphore S[N]=0;//每个哲学家一个信号量

void test(int i)
{
	if(state[i]==HUNGRY && state[LEFT] == THINKING && state[RIGHT] == THINKING) 
	{
		state[i]=EATING;
		V(S[i]);
	}
 } 
 
void philosopher(int i)
{
	思考;
	P(mutex);
		state[i]=HUNGRY;
		test(i);
	V(mutex);
	
	P(S[i]);
	拿起左筷子;
	拿起右筷子;
	用餐;
	放下左筷子;
	放下右筷子;
	
	P(mutex);
		state[i]=THINKING;
		test(LEFT);
		test(RIGHT);
	V(mutex); 
}
6.2.3爱睡觉的理发师问题

【问题解决】

int waiting=0;
semaphore mutex=1;//用于waiting 增减的互斥
semaphore chair=1;//每次理发椅只有一把,顾客互斥使用
semaphore ready=0;//同步,顾客通知理发师准备好了
semaphore finish=0;//同步,理发师通知顾客,可以来理发了

main()
{
    cobegin
        barber();
        customer();
    coend
}

barber()
{
    while(true)
    {
        P(ready);
        cut_hair();
        V(finish);
    }
}

customer()
{
    P(mutex);
        if(waiting<=N)
            {waiting=waiting+1;
    V(mutex);
        P(chair);
            V(ready);
            P(finish);
        V(chair);
    P(mutex);
        waiting=waiting-1;
    V(mutex);
    }
    else{
    V(mutex);exit;
    }
}

 

6.2.4酒吧设备租赁问题

【问题描述】

在一间酒吧里有三个音乐爱好者,第一位音乐爱好者只有随身听,第二位只有音乐CD,第三位只有电池。而要听音乐就必须随身听、音乐CD和电池这三种物品俱全。酒吧老板一次出借这三种物品中的任意两种。当一名音乐爱好者得到这三种物品并听完一首乐曲后,酒吧老板才能再一次出借这三种物品中的任意两种。于是第二名音乐爱好者得到这三种物品,并开始听乐曲。整个过程就这样进行下去。
试用P、V操作正确完成这一过程。

【问题解决】

borrow1: CD+电池
borrow2:随身听+电池
borrow3:随身听+CD
semaphore over=0;
semaphore borrow1=0;
semaphore borrow2=0;
semaphore borrow3=0;
main()
{
	cobegin
		boss();
		fans_i();(i=1,2,3)
	coend
 } 

boss()
{
	int s=guessservice();
	if(s==1)V(borrow1);
	elseif(s==2)V(borrow2);
		else(s==3)V(borrow3);
	P(over);
}

fans_i()
{
	P(borrowi);
	听音乐
	V(over); 
}
6.2.5巴拿马运河问题

【问题描述】

巴拿马运河建在太平洋和大西洋之间。由于太平洋和大西洋水面高度不同,有巨大落差,所以运河中修建有T(T>=2)级船闸,并且只能允许单向通行。船闸依次编号为1、2、…、T。由大西洋来的船需经由船闸 T、T-1、…、2,1通过运河到太平洋;由太平洋来的船需经由船闸1、2、…、T一1,T通过运河到大西洋。
试用P、V操作正确解决大西洋和太平洋的船只通航问题。

【问题解决】

int countPA[k]=0;//太平洋到大西洋 每个船闸的初船只数量 
int countAP[k]=0;//大西洋到太平洋 每个船闸的初船只数量 
semaphore mutex1=1; 
semaphore mutex2=1;
semaphore s[k]=1;//每个船闸的互斥操作 
main()
{
	cobegin
		P2A();
		A2P();
	coend
}

void P2A()
{
	int i;
	for(i=1;i<=T;i++)
	{
		P(mutex1);
			countPA[i]++;
			if(countPA[i]==1)//该船闸来的第一只船 
				P(S[i]);//关门 
		V(mutex1);
		过第i个船闸;
		
		P(mutex1);
			countPA[i]--;
			if(countPA[i]==0)V(S[i]);//最后一只船,开门 
		V(mutex1);
	}
}

void A2P()
{
	int i;
	for(i=T;i>=1;i--)
	{
		P(mutex2);
			countAP[i]++;
			if(countAP[i]==1)//该船闸来的第一只船 
				P(S[i]);//关门 
		V(mutex2);
		过第i个船闸;
		
		P(mutex2);
			countAP[i]--;
			if(countAP[i]==0)V(S[i]);//最后一只船,开门 
		V(mutex2);
	}
}
6.2.6银行叫号问题

【问题描述】

某银行有人民币储蓄业务,由n个柜员负责。每个顾客进入银行后先取一个号,并且等着叫号。当一个柜台人员空闲下来,就叫下一个号。试用P、V操作正确编写柜台人员和顾客进程的程序。

【问题解决】

semaphore mutex=1;//互斥 
semaphore client=0;//客户数量 
semaphore call=0;//同步 
semaphore finish=0//同步 

void main()
{
	cobegin
		client();
		server_i();i=1,2,3...,n
	coend
}

void client()
{
	P(mutex);
	取号; 
	V(mutex);
	V(client);
	P(call);//被叫号 
	被服务 ; 
	P(finish);//是否结束服务是由柜员传达 
}
void server_i()
{
	while(true)
	{
		P(client);
		P(mutex);
		取出队首号码; 
		V(mutex);
		V(call);//叫号 
		服务;
		V(finish); //服务结束 ,把信息传递给顾客 
	}
}

7.管程

7.1引入

PV操作比较复杂

7.2管程的定义和基本特征

管程是一种特殊的软件模块,由一下部分组成:

  1. 局部于管程的共享数据结构说明
  2. 对该数据结构进行操作的一组过程,即函数
  3. 对局部于管程的共享数据设置初始值的语句
  4. 管程有一个名字

基本特征:

  1. 局部于管程的数据只能被局部于管程的过程所访问
  2. 一个进程只有通过调用管程内的过程才能进入管程访问共享数据
  3. 每次仅允许一个进程在管程内执行某个内部过程

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值