内容要求:
(1)用C语言完成线程的创建和撤销,并按先来先服务方式对多个线程进行调度。
(2)将线程调度算法修改为时间轮转算法,实现时间片轮转调度。
(3)改变时间片的大小,观察结果的变化。
(4)假设两个线程共用一软件资源(如某一变量,或某一数据结构),请用记录型信号量来实现对它的互斥访问。
(5)假设有两个线程共享一个可存放5个整数的缓冲,其中一个线程不停地计算1至50的平方,并将结果放入缓冲,另一个线程不断地从缓冲中取出结果,并将它们打印出来,请用记录型信号量来实现这一生产者和消费者的同步问题。
(6)实现消息缓冲通信。
代码运行环境:Turbo C
#include <alloc.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dos.h>
/* 状态码常量定义 */
#define FINISHED 0 /* 表示线程处于终止态或者TCB是空白状态 */
#define RUNNING 1 /* 表示线程处于运行态 */
#define READY 2 /* 表示线程处于就绪态 */
#define BLOCKED 3 /* 表示线程处于阻塞态 */
#define NTCB 10 /* NTCB是系统允许的最多任务数 */
#define NTEXT 20 /* 文本大小 */
#define NBUF 5 /* 缓冲区大小 */
#define NSTACK 1024 /* 私有栈大小 */
#define GET_INDOS 0x34
#define GET_CRIT_ERR 0x5d06
char far *indos_ptr = 0; /* 该指针变量存放INDOS标志的地址 */
char far *crit_err_ptr = 0; /* 该指针变量存放严重错误标志的地址 */
int timecount = 0;
int TL; /* time slice时间片 */
int current = -1; /* 当前进程的tcb下标 */
int n = 0;
typedef int (far *codeptr)(void); /* 定义一个函数指针类型 */
void interrupt(*old_int8)(void);
/* 记录型信号量 */
typedef struct{
int value;
struct TCB *wq;
}semaphore;
semaphore mutex = {1, NULL};
semaphore mutexfb = {1, NULL}; /* 缓冲区互斥信号量 */
semaphore sfb = {NBUF, NULL}; /* 计算信号量 */
semaphore empty = {NBUF, NULL};
semaphore full = {0, NULL};
/* 消息缓冲区 */
struct buffer{
int id;
int size;
char text[NTEXT];
struct buffer *next;
}buf[NBUF], *freebuf;
struct TCB{
unsigned char *stack; /* 线程堆栈的起始位置 */
unsigned ss; /* 堆栈段址 */
unsigned sp; /* 堆栈指针 */
char state; /* 线程状态,取值可以是FINISHED, RUNNING, READY, BLOCKED */
char name[NTEXT]; /* 线程的外部标识符 */
struct buffer *mq; /* 接收线程的消息队列首指针 */
semaphore mutex; /* 接收线程的消息队列的互斥信号量 */
semaphore sm; /* 接收线程的消息队列的计数信号量,用于实现同步 */
struct TCB *next;
} tcb[NTCB];
struct int_regs{
unsigned bp, di, si, ds, es, dx, cx, bx, ax, ip, cs, flags, off, seg;
};
int intbuf[NBUF], buftemp;
int in = 0, out = 0;
void over();
void destroy(int id);
void wait(semaphore *sem);
void signal(semaphore *sem);
void block(struct TCB **qp);
void wakeupFirst(struct TCB **qp);
void send(char *receiver, char *a, int size);
int receive(char *sender, char *b);
/* InitDos()函数:功能是获得INDOS标志地址和严重错误标志的地址 */
void InitDos(void)
{
union REGS regs;
struct SREGS segregs;
/* 获得INDOS标志的地址 */
regs.h.ah = GET_INDOS;
/* intdosx(): Turbo C的库函数,其功能是调用DOS的INT21H中断 */
intdosx(®s, ®s, &segregs);
/* MK_FP(): 不是一个函数,只是一个宏 */
/* 其功能是做段基址加上偏移地址的运算,也就是取实际地址。 */
indos_ptr = MK_FP(segregs.e