管程是什么_管程由几部分组成

管程是什么_管程由几部分组成1.管程(Monitor)是什么?由Hansen和Hoare提出,管程是变量、数据结构和操作函数等组成的一个集合,通过ADT封装。管程是一种高级的进程同步工具,它是编程语言的概念。管程的局部变量只能由局部函数所访问。管程结构确保每次只能有一个进程在管程内处于活动状态,各个进程只能串行执行管程

大家好,欢迎来到IT知识分享网。

1.管程(Monitor)是什么?

由Hansen和Hoare提出,管程是变量、数据结构和操作函数等组成的一个集合,通过ADT封装。
管程是一种高级的进程同步工具,它是编程语言的概念。

管程的局部变量只能由局部函数所访问。
管程结构确保每次只能有一个进程在管程内处于活动状态,各个进程只能串行执行管程内的函数。

进入管程的互斥由编译器负责实现,但是一种通用做法是使用互斥量(mutex)和二进制信号量(binary semaphores)。
写管程的人不用关心编译器如何实现互斥,只需要将临界区转换成管程过程就行。

补充:互斥量(mutex)可以看作是信号量的一个简单版本,它是一个处于两种状态:unlocked和locked的共享变量。
互斥量实现非常简单,使用TSL指令等就可以。
通常用一个整数(integer)来表示,0表示解锁,其他所有值表示加锁。
对于一个加了互斥量的临界区,如果一个进程想进入且mutex locked,那么它将阻塞直到mutex unlocked。

2.管程如何实现互斥与同步?

互斥量(mutex)用于各进程对管程的互斥访问,条件变量(condition variables)用于各进程的同步。
对于条件变量 x,由x.wait()和x.signal()两种操作可以调用,实现进程的阻塞与唤醒。
x.wait():当 x 对应的条件不满足(资源不够)时,调用x.wait()的进程将自己插入条件 x 的等待队列中,释放管程;
x.signal():当条件 x 的等待队列非空时,唤醒一个挂起进程。
注意:关于条件变量的PV操作与信号量的PV操作略有不同!

以生产者–消费者问题为例,当管程发现进程无法继续运行时(如生产者发现缓冲区满),就会在某个条件变量(如empty)上执行empty.wait()操作。
当一个消费者发现有消费者在等待条件变量 full 时,会调用full.signal()唤醒一个等待的消费者。

拓展:此时管程中就会有两个活跃的进程,为了实现管程的互斥,有三种解决办法。
1.唤醒并等待:当前进程等待直到被唤醒进程离开管程或等待另一个条件。
2.唤醒并继续:被唤醒进程等待直到当前进程离开管程或等待另一个条件。
3.折中方案:当前进程执行signal操作时,立即离开管程,让被唤醒进程执行。

通常采用方案1,容易实现。
假定使用方案1,调用signal的进程会阻塞进入紧急队列,与等待mutex解锁的入口队列一样都在等待访问管程。
当需要唤醒一个阻塞进程时,紧急队列中进程的优先级高于入口队列。
管程是什么_管程由几部分组成

3.采用信号量的管程示例

monitor的参考伪代码如下:

int mutex = 1; // 互斥信号量 mutex,用于组织入口队列

monitor Demo{
    share_data_struct S; // 共享数据结构,资源
    condition x; // 条件变量 x
    int next = 0; // 信号量 next,用于组织紧急队列
    int next_count = 0; // 记录紧急队列中的进程数量
    int x_sem = 0; // 条件变量 x 对应的信号量 x_sem
    int x_count = 0; // 记录与条件 x 关联的队列中的进程数量
    
    init_code(){
        S = 5;
    }
    
    // x 条件不满足时,将自己阻塞进入 x 关联的队列
    x.wait(){
        x_count ++;
        if (next_count > 0) signal(next); // 优先唤醒紧急队列中进程
        else signal(mutex); // 然后唤醒入口队列中进程
        wait(x_sem); // 进入与条件 x 关联的队列(阻塞)
        x_count --;
    }
    
    // 当 x 的挂起队列非空时,唤醒一个进程
    x.signal(){
        next_count ++;
        signal(x_sem); // 唤醒一个等待条件 x 的挂起进程
        wait(next); // 阻塞自己
        next_count --;
    }
    
    // 申请一个资源
    take_away(){
        if (S <= 0) x.wait();
        S --; // 资源 --
        // 分配资源,做一系列处理
    }
    
    // 释放一个资源
    give_back(){
        // 归还资源,做一系列处理
        S ++; // 资源 ++
        x.signal();
    }
}

// 访问管程的示例代码
void demo(){
    wait(mutex);
    
    xxx; // 访问管程代码
    
    if (next_count > 0) signal(next);
    else signal(mutex);
}

4.管程与PV信号量

PV信号量的使用错误可能导致难以检测的时序错误。
以进程共享信号量 mutex 为例,若交换 signal(mutex) 和 wait(mutex) 的顺序可能导致违反临界区的互斥要求;若省略 signal 或 wait 操作可能会导致死锁等情况。

为了避免PV信号量使用不当导致的可能的错误,以及大量分散的PV同步操作给操作系统带来的管理麻烦,出现了进程同步工具–管程。
管程的特性保证了进程互斥,程序员可以通过条件变量来灵活地实现进程的同步,而无需担心进程互斥问题。

参考资料:
1.《2023王道操作系统考研复习指南》
2.《操作系统概念》第9版
3.《现代操作系统》第4版

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/30042.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信