进程同步,信号量,互斥变量等说明

5 篇文章 0 订阅

0 前言

工作三年,敲了3年代码(PHP,C++,Java,C)等,开发过几种产品,非计算机科班出身,全部编程是自学最近闲来无事买了一本《计算机操作系统》第四版,学一下个人感觉对比较重要的章节,增加对编程的理解。

1 进程的描述

1.1 进程的定义和特征

1.进程控制块(PCB):为了使参与并发执行的每个程序(含数据)都能独立的运行,
            在操作系统中必须为之配置一个专门的数据结构。称之为进程控制块。
2.进程的定义:
    (1)进程是程序的一次执行。
    (2)进程是一个程序及其数据在处理机上顺序执行时所发生的活动。
  ★(3)进程是具有独立功能的程序在一个数据集合上的运行的过程,它是系统
        进行资源调度和分配的一个独立单位。
    (4)在引入进程实体之后,我们可以把传统OS中的进程定义为:
        ※进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位。
     进程 = PCB + 程序段 + 数据段
3.进程的特征:
    (1)动态性
    (2)并发性
    (3)独立性
    (4)异步性
4.进程与程序的区别和联系:
    进程:是程序的一次执行,是动态概念。一个进程可以同时包括多个程序;
          进程是暂时的,是动态的产生和消亡的。
    程序:是一组有序的静态指令,是静态概念。一个程序可以是多个进程的
          一部分;程序可以作为资料长期保存。


1.2 进程的基本状态及转换

        由于多个进程在并发执行时共享系统资源,致使他们在运行过程中呈现间断性的运行规律,所以进程在生命周期内可能具有不同状态。一般而言,每个进程至少应处于以下三种基本状态

  • 就绪(Ready)状态
    指进程已处于准备好运行的状态,即进程已分配到除CPU以外的所有必要资源后,只要再获得CPU就可以立即执行。如果有多个就绪状态的进程。
    通常按照一定的策略排成一个队列,称该队列为就绪队列
  • 执行(Running)状态
    指进程已经获得CPU,其程序正在执行的状态。在单处理机系统中,只有一个进程处于执行状态,而多处理机系统则有多个进程处于执行状态。
  • 阻塞(Block)状态
    指正在执行的进程由于发生某事件(如I/O请求、申请缓冲区失败等)暂时无法继续执行时的状态,即进程的执行受到了阻塞。此时引起进程调度,OS把处理机分配给另一个就绪的进程,而让受阻进程处于暂停状态,一般将这种暂停状态称为阻塞状态,有时也称为等待状态或封锁状态。
    通常系统将处于阻塞状态的进程也排成一个队列,称为阻塞队列。
  • 三种基本状态的转换
  1. 就绪--->执行 处于就绪状态的进程,在调度程序为之分配了处理机之后便可执行 。
  2. 执行--->就绪 正在执行的进程如果因为分配给他的时间片用完而被剥夺处理机暂停执行,其状态就会变成就绪。
  3. 执行--->阻塞 如果因发生某事件,致使当前进程行为受阻(例如进程访问临界资源,而该资源正被其他进程访问时),则变成了阻塞。

1.3 创建状态和终止状态

        为了满足进程控制块对数据及操作的完整性要求以及增强管理的灵活性,通常在系统中有引入的两种状态:创建状态和终止状态;进程的五种状态及转化如下如所示:

 

1.4 进程的挂起与激活

  • 进程的挂起

检查进程状态,如果活动就绪改为静止就绪;如果活动阻塞改为静止阻塞。为了方便用户或父进程考察该进程的运行情况,把进程PCB复制到制定内存区域;最后若被挂起的进程正在执行,则扎ungxiangdiaodu程序重新调度。

  • 进程的激活状态

利用激活原语Active,把进程从外存调入内存,检查其状态,若静止就绪改为活动就绪;若静止阻塞改为活动阻塞。

  • 三种基本状态下加入挂起和激活的进程状态图:

  •  五种状态下加入挂起和激活的进程状态图:

1.5 进程管理中的数据结构

PCB的作用

1.作为独立运行的基本单位的标志;
系统创建一个新进程时,就为它建立一个PCB,进程结束时回收PCB,进程也随之消亡,系统通过感应PCB来感知进程的存在。事实上,PCB已成为进程存在于系统的唯一标志。
2.能实现间断性运行方式;
有了PCB后,当进程阻塞暂停运行时,系统可以将CPU现场信息保存在PCB中,当进程再次执行时使用PCB中的CPU现场信息,恢复CPU现场。
3.提供进程管理所需要的信息;
4.提供进程调度所需要的信息;
5.实现与其他进程的同步与通信;

PCB中的信息

1. 进程标识符
        用于唯一地标识一个进程,一个进程通常有两种标识符。
        内部标识符:操作系统为每一个进程设置的唯一的标识符;
        外部标识符:为了方便用户(进程)对进程的访问,由创建者提供的标识符。
2. 处理机状态;
        处理机上下文信息;
3. 进程调度信息
4. 进程控制信息
5. PCB的组织方式

1.线性方式
        把所有的PCB组织在一张线性表中,将该表的首地址放在内存的专用区域。访问时在指定区域找表的首地址,再通过访问表的首地址找到表的信息,最后查找到需要的PCB。

2.链接方式
        把具有相同状态进程的PCB分别通过PCB的链接字链接成为一个队列。

3.索引方式
        根据进程状态的不同,各自建立索引表,把索引表在内存的首地址存放在指定的区域。通过这些首地址查找需要的PCB;

2 进程的控制

2.1 OS内核

大多数操作系统内核包括两大方面的内容:

  • 支撑功能
  • 资源管理功能

通常将处理机的执行状态分为系统状态和用户状态两种。
    ①系统态:又称为管态,也称为内核态。
    ②用户态:又称为目态。
1.支撑功能:
    (1)中断处理
    (2)时钟管理
    (3)原语操作
2.资源管理功能:
    (1)进程管理
    (2)存储器管理
    (3)设备管理


2.2 进程的创建

进程的层次结构:
    通常,把创建进程的进程成为--父进程;把被创建进程的进程成为子进程。
    在UNIX中,进程与其子孙进程共同组成一个进程家族(组)。
    但在Windows中不存在任何进程层次结构的概念。
引起进程创建的事件:
    (1)用户登录
    (2)作业调度
    (3)提供服务
    (4)应用请求
进程的创建:
    (1)申请空白PCB为新进程申请获得唯一的数字表示符,并从PCB集合中索取一个空白PCB。
    (2)为新进程分配其运行所需的资源。
    (3)初始化进程控制块
    (4)如果程序就绪队列能够接纳新进程,便将新进程插入就绪队列。


2.3 进程的终止

引起进程终止的事件:

1、正常结束。
2、异常结束:
        ①越界错,这是指程序所访问的存储区,已越出该程序的区域。
        ②保护错,指进程试图去访问一个不允许访问的资源或文件。或者以不适当的方式进行访问。
        ③非法指令,指程序试图去执行一个不存在的指令。
        ④特权指令错,指用户进程试图去执行一条只允许OS执行的指令。
        ⑤运行超时,指进程的执行时间超过了指定的最大值。
        ⑥等待超时,指进程等待某事件的时间超过了规定的最大值。
        ⑦算术运算错,指进程试图去执行一个被禁止的运算。
3、外界干预:① ②③

进程终止的过程:

1、根据被终止进程的标识符,从PCB集合中j检索出该进程的PCB,从中读出该进程的状态。
2、若被终止的进程的处于执行状态,应立即终止该进程的执行,并置调度标志为真,用于指示该进程被终止后应重新进行调度。
3、若该进程还有子孙进程,还应将其所有子孙进程也都予以终止,以方他们成为不可控的进程。
4、将被终止的进程所拥有的全部资源或者归还其父进程,或者归还给系统。
5、将被终止的进程(PCB)从所在的队列(或链表)中移除,等待其它程序来搜集信息。

2.4 进程的阻塞与唤醒

  • 引起进程阻塞和唤醒的事件
  • 进程阻塞过程
  • 进程唤醒过程

有下述几类事件会引起进程阻塞或被唤醒:
    (1)向系统请求共享资源失败。
    (2)等待某种操作的完成
    (3)新数据尚未到达
    (4)等待新任务的到达

2.5 进程的挂起与激活

  • 进程的挂起
  • 进程的激活过程

3 进程同步

进程同步是重点知识,需要深入理解,也是我在开发过程中经常会遇到的场景,进程同步机制的主要任务,是对多个相关进程在执行次序上进行协调,使并发执行的进程之间能够按照一定的规则共享系统资源,并且很好地相互合作,从而使程序的执行具有可再现性。

3.1 进程同步的基本概念

  • 两种形式的制约

        由于共享资源或者为完成某一任务相互合作,而产生制约关系;

        间接相互制约关系 :多个程序在并发执行时,由于共享系统资源导致这些并发执行程序之间形成的相互制约关系。例如打印机这些临界资源;

        直接相互制约关系 :通过合作而产生的制约关系。例如只有a执行过后,b才能执行。而两者都是为了完成某一个功能。

  • 临界资源

        只能一个进程访问的资源。进程之间采取互斥方式,实现对这种资源的共享。通过生产者---消费者问题(进程同步问题)可说明这一过程.(具体不再说明该问题) 。

  • 临界区

        每个进程中访问临界资源的那段代码称为临界区。可把一个访问临界资源的循环进程描述如下(剩余区是取出进入,临界,退出区的剩下的代码):

while(TRUE)
{
	进入区
	临界区
	退出区
	剩余区
}
  • 同步机制应遵循寻的规则        

        1.空闲让进
        2.忙则等待
        3.有限等待
        4.让权等待

3.2 硬件同步机制

1、关中断

        关中断就是一种中断信号,在单片机中的中断描述一种,这种统计机制就是针对多线程,多进程程序效率太低,频繁使用中断可能造成严重异常,不适用多CPU系统;

2、使用TEST-and-Set指令实现互斥

        简称TS指令,在许多计算机中都提供了这种指令,代码逻辑如下:

// lock=false时表示资源空闲
bool TS(bool *lock)
{
    bool old;
    old = *lock;
    *lock = true;
    return old
}
  
//用法示例如下
int main(void)
{
    do{
        //代码块
        while(TS(&lock)); //为true时进入循环,不出来
        //临界区处理代码
        *lock = false;    //处理完成后将锁置空闲
    }
    while(true);
}
  

3、利用Swap指令实现进程互斥

        该指令实现两个变量互换,在Intel 80x86中称为XCHAR指令,代码如下

void swap(bool *a, bool *b)
{
	bool temp;
	temp = *a;
	*a = *b;
	*b = temp;
}
/*
使用说明:为每个临界资源设置一个全局的布尔变量lock,初始值为false
在每个进程中再利用一个局部变量key,利用swap进程临界资源操作,实现互斥
*/
int main()
{
	bool key,lock;
	while (1)
	{
		key = true;
		do{
			swap(&lock, &key);
		} while (key != false);
		//临界区操作
		lock = false;
		//剩余区操作
	}
}

3.2 信号量机制

1、整形信号量(P、V操作)

通过两个标准的原子操作wait(S)和signal(S)来访问;这两个操作有叫P,V操作;

int S = 1;			 //用整形变量表示信号量
void wait(int s)	 //进入区
{
	while(s <= 0);	 //资源不够一致循环,缺点一致不让权等待,就是瞎忙
	s--;			 //占用资源
}

void signal(int s)	 //退出区
{
	s++;			 //释放资源
}

//进程P0
int main()
{
	wait(S);				//进入区,申请资源
	//使用打印机资源			//临界区。。。
	signal(S);				//退出区,释放资源
	//剩余区
}

//进程P1
int main()
{
	wait(S);				//进入区,申请资源
	//使用打印机资源			//临界区。。。
	signal(S);				//退出区,释放资源
	//剩余区
}

//进程PN
int main()
{
	wait(S);				//进入区,申请资源
	//使用打印机资源			//临界区。。。
	signal(S);				//退出区,释放资源
	//剩余区
}

 2、记录型信号量

为了解决数字型信号量,瞎等问题;

/*
----解决瞎忙问题,添加到进程等待链表里面
*/
//记录型信号量的定义
typedef struct
{
	int value; //
	struct process *L;
}semaphore;

//申请资源
void wait(semaphore S)
{
	S.value--;
	if (S.value < 0)
	{
		/*若资源不够,
		*使用block原语使进程从运行态进入阻塞态
		*并把挂到信号量S的等待队列中
		* 该进程从阻塞态变为就绪状态*/
		block(S.L);
	}
}

//释放资源
void sigle(semaphore S)
{
	S.value++;
	if (S.value <= 0)
	{
		/*释放资源后,若有其他进程等到资源,
		 *使用wakeup唤醒等待队列中的进程
		 * 该进程从阻塞态变为就绪状态*/
		wakeup(S.L);  
	}
}

3、And型信号量

为了解决一个进程中多个临界资源的访问,解决死锁问题;
S1到Sn都表示所需资源,资源数都大于1,对每个资源进行--表示资源被占用,分配好资源之后跳出循环,wait操作结束。如果其中某个资源Si得不到满足,会执行else中的内容:把进程放进Si关联的阻塞队列中,然后程序计数器把指针移向wait操作开始。(wait操作是原语,遵循要执行都执行,执行不了就从头重新执行)

signal操作表示的是释放资源,把S1到Sn全部资源释放,并且把S1到Sn关联的阻塞队列全部置空,阻塞队列中的进程直接调度到就绪队列中。

缺点:AND型信号量满足了 “多种资源,数量为1”的使用情景,但是实际上还会有多种资源数量不固定的情景,AND型信号量显然处理不了这种情况的进程调度。为了解决多资源多数量的情况,出现了信号量集。

//出现的死锁情况如下,假设有两个进程A,B,分别访问共享数据D,E,
//分别设置互斥量Dmutex,Emutex
process A:            process B:  
wait(Dmutex);          wait(Emutex);
wait(Emutex);          wait(Dmutex);

//若下面执行则死锁:
process A:wait(Dmutex);
process B:wait(Emutex);
process A:wait(Emutex);   //死锁
process B:wait(Dmutex);   //死锁

//And型实现的代码如下;
//核心思想:每个进程都是一次性申请全部共享资源,

Swait(S1, S2, …, Sn)
{
	while(true)
	{
		if (S1 >= 1 and … and Sn >= 1){
			for (i = 1; i <= n; i++) Si--;
			break;
		}
		else{
			//将进程放入与Si<1的第一个Si相关联的等待队列中,
		}
	}
}


Ssignal(S1, S2, …, Sn){
	while (true){
		for (i = 1; i <= n; i++) {
			Si++;
			//将与Si关联的队列中等待的所有进程移除到就绪队列中
		}
	}
}

3、信号量集

     PV操作只能对互斥变量做加1减1访问,表明一个进程只能对共享资源中某个资源做一次操作,当需要操作多次时,会多次PV操作,会大大增加死锁概率,在有些情况下,必须对系统资源做强制分配,申请临界资源的数量大于下限值时,必须管制不予分配,所以在每次分配之前需要测试资源的数量,所以多And信号量机制做升级,提出了信号集的概念;

其实就是对每个进程申请每个资源的下限值放入到PV函数中,扩展PV函数,

Swait(S1,T1,D1,.....)
Ssignal(S1,T1,D1,.....)
进程对S的测试值不是1,而是T,当资源大于T时,才能分配资源;一旦分配资源进程对改资源的需求就是D,释放资源是是进行S=S-D操作;

//一般的信号量集有一下几种情况
1、Swait(S,d,d)   一个信号,每次申请d个资源,现有资源少于d个,不予分配
2、Swait(S,1,1)   退化成记录型信号量
3、Swait(S,1,0)   可控的开关,当S≥1时,允许多个进程进入特定区,S变为0时将阻止任何进程进入特定区

后续将学习计算机中进程调度问题,是以什么算法进行调度的?

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值