实验分两部分,第一部分,实现互斥
思路很简单,利用信号量,将其值初始化为1,semaphore resource = {1,NULL};
获取资源时做P()操作,释放资源使用权时做V()操作。
所以
void p1( )
{
long i, j, k;
p(&semlock); //获取资源使用权,如果不能获取,会被放到信号量队列中等待资源可用被唤醒
//中间过程相当于是在使用这个资源(模拟)
for(i=0; i<40; i++)
{
putchar('a');
for(j=0; j<1000; j++)
for(k=0; k<20000; k++);
}
v(&semlock); //释放资源,信号量值加1,队列中第一个线程会被唤醒(如果队列不为空)
}
void p2( )
{
long i, j, k;
p(&semlock); //同p1()
for(i=0; i<20; i++)
{
putchar('b');
for(j=0; j<1000; j++)
for(k=0; k<20000; k++);
}
v(&semlock);
}
另外,我们要更改Find()调度程序,找到没有被阻塞的线程来调度
int Find()
{
int i,j;
for(i = 1; i < NTCB; i++)
{
if(tcb[i].state != FINISHED && tcb[i].state != BLOCKED) return i;
}
return 0;
}
到这里,互斥锁就完成了。上最终代码:
#include <stdlib.h>
#include <dos.h>
#include <stdio.h>
#define GET_INDOS 0x34 /* 34H 系统功能调用 */
#define GET_CRIT_ERR 0x5d06 /* 5D06H号系统功能调用 */
#define BLANK -1
#define FINISHED 0 /* 终止 */
#define RUNNING 1 /* 执行 */
#define READY 2 /* 就绪 */
#define BLOCKED 3 /* 阻塞 */
#define NTCB 3 /* 系统线程的最大数 */
#define TL 10 /* 时间片大小 */
#define NBUF 10 /* 消息缓冲区数目 */
#define NTEXT 50 /* 文本输出大小 */
char far* intdos_ptr=0;
char far* crit_err_ptr=0;
int timecount=0;
int current=-1;
typedef unsigned int UINT16;
typedef struct/* 信号量 */
{
int value;
struct TCB* wq;
} semaphore;
int critical = 0; //
semaphore semlock = {1,NULL};
struct TCB /* 线程控制块 */
{
unsigned char* stack; /* 堆栈的起始地址 */
unsigned ss;
unsigned sp; /* 堆栈段址和堆栈指针 */
char state; /* 进程状态 */
char name[10]; /* 线程的外部标识符 */
int value; /*优先级*/
struct TCB* next; /* 指向控制快指针 */
semaphore mutex; /* 互斥信号量 */
} tcb[NTCB];
struct int_regs /* 堆栈现场保护和恢复结构体 */
{
unsigned BP,DI,SI,DS,ES,DX,CX,BX,AX,IP,CS,Flags,off,seg;
};
typedef int(far* codeptr)(void);
void interrupt(*old_int8)(void);
int DosBusy(void);
void InitIndos(void);
void InitTcb();
void interrupt new_int8(void);
void interrupt swtch();
void p(semaphore *sem);
void v(semaphore *sem);
int Create(char* name,codeptr code,int stacklen,int prio); /* 创建线程 */
void Destroy(int i);
void p1( )
{
long i, j, k;
p(&semlock);
for(i=0; i<40; i++)
{
putchar('a');
for(j=0; j<1000; j++)
for(k=0; k<20000; k++);
}
v(&semlock);
}
void p2( )
{
long i, j, k;
p(&semlock);
for(i=0; i<20; i++)
{
putchar('b');
for(j=0; j<1000; j++)
for(k=0; k<20000; k++);
}
v(&semlock);
}
void InitInDos() /* 取得INDOS标志和严重错误标志地址 */
{
union REGS regs;
struct SREGS segregs;
regs.h.ah=GET_INDOS; /* 使用34H号系统功能调用 */
intdosx(®s,®s,&segregs);
intdos_ptr=MK_FP(segregs.es,regs.x.bx);
if(_osmajor<3)
crit_err_ptr=intdos_ptr+1; /* 严重错误在INDOS后一字节处 */
else if(_osmajor==3&&_osminor==0)
crit_err_ptr=intdos_ptr-1; /* 严重错误在INDOS前一字节处 */
else
{
regs.x.ax=GET_CRIT_ERR;