记录型信号量进程同步机制拥有记录型的数据结构,其中包括某种临界资源的可供访问的数量和进程阻塞队列,进程在操作时只能采用wait()和signal(),两种原子操作。其算法模拟如下:
#include <stdio.h>
#include <string>
#include <stdlib.h>
#include <iostream>
using namespace std;
//信号量机制的同步和互斥//
//进程数据结构
//链式队列的数据结构
typedef struct process{
int num;//进程编号
struct process *next;//下指针
}*processptr;
typedef struct Link {
process *front, *rear;//队列的头尾指针
}*LinkQNode;
void InitQNode(LinkQNode q) {
//初始化队列
q->front = q->rear = (processptr)malloc(sizeof(process));
q->front->next = NULL;
}
void Insert(LinkQNode q,int num) {
processptr p1 = (process *)malloc(sizeof(process));
p1->num = num;
p1->next = NULL;
q->rear->next = p1;
q->rear = p1;
}
int Select(LinkQNode q) {
//出队操作
if (q->rear == q->front) {
//cout << "进程队列为空" << endl;
return 0;
}
processptr p = (process *)malloc(sizeof(processptr));
p = q->front->next;
q->front->next = q->front->next->next;
int num ;
num = p->num;
if (q->rear == p)
q->rear = q->front;//如果只有一个元素,那么队头指针等于队尾指针
free(p);
return num;
}
//进程记录的数据结构
typedef struct semaphore{
int value;//信号量的值,表征临界资源的请求和等待的进程数量
LinkQNode L;//等待进程队列
}*semaphoreptr;
//信号量机制的操作
class Singal_opt {
int num;//进程编号
public:
Singal_opt(int n):num(n) {};
~Singal_opt() {};
void setnumber(int n);//设置进程编号
void block(semaphoreptr s);//将等待进程插入到阻塞队列
void wakeup(semaphoreptr s);//唤醒进程
void wait(semaphoreptr s);//进程申请临界资源
void singal(semaphoreptr s);//进程使用完毕并释放临界资源
};
void Singal_opt::setnumber(int n) {
num = n;
}
void Singal_opt::block(semaphoreptr s) {
//将进程状态转变为阻塞,即将当前进程入队
Insert(s->L, num);
cout << num << "号进程申请临界资源并且进入阻塞队列" << endl;
}
void Singal_opt::wakeup(semaphoreptr s) {
//唤醒进程,即执行出队操作
s->value++;
int n;
n = Select(s->L);
if (n == 0) {
//表示队以空
cout << "阻塞队列已空" << endl;
}
else {
cout << n << "号进程被唤醒,开始使用临界资源" << endl;
}
}
void Singal_opt::wait(semaphoreptr s) {
s->value--;//表示有一个进程申请临界资源
if (s->value < 0) {
//表示临界资源被占用
//执行阻塞操作
block(s);
}
else if (s->value >= 0) {
cout << num << "号进程正在使用临界资源" << endl;
}
}
void Singal_opt::singal(semaphoreptr s) {
s->value++;//表示一个进程使用完毕并释放临界资源
cout << num << "号进程使用完毕临界资源" << endl;
while(s->value <= 0) {
//表示还有进程在使用临界资源
//从阻塞队列中唤醒一个临界资源
wakeup(s);
}
}
int main()
{
Singal_opt p1(1), p2(2),p3(3);
semaphoreptr s;
s = (semaphore *)malloc(sizeof(semaphore));
s->value = 1;
s->L = (LinkQNode)malloc(sizeof(Link));
InitQNode(s->L);
p1.wait(s);
p2.wait(s);
p3.wait(s);
processptr p = s->L->front->next;
p1.singal(s);
return 0;
}
PS:这段代码中我把signal写成singal了,-_-||
调试结果:
参考书籍:王道《2018年操作系统考研复习指导》