1. 程式人生 > >實驗一: 程序狀態轉換及PCB的模擬

實驗一: 程序狀態轉換及PCB的模擬

實驗目的

1)加深對程序概念的理解。
2)深入瞭解程序控制塊和程序狀態之間的轉換。
3)掌握程序排程演算法。

實驗預備知識

1)程序的狀態


2)程序的結構——PCB

程序都是由一系列操作(動作)所組成,通過這些操作來完成其任務。因此,不同的程序,其內部操作也不相同。在作業系統中,描述一個程序除了需要程式和私有資料之外,最主要的是需要一個與動態過程相聯絡的資料結構,該資料結構用來描述程序的外部特性(名字、狀態等)以及與其它程序的聯絡(通訊關係)等資訊,該資料結構稱為程序控制塊(PCB,Process Control Block)。

程序控制塊PCB與程序一一對應,PCB中記錄了系統所需的全部資訊、用於描述程序情況所需的全部資訊和控制程序執行所需的全部資訊。因此,系統可以通過程序的PCB來對程序進行管理。

實驗步驟

1)設計一個有 N個程序共行的程序排程程式。

2)程序排程演算法:採用最高優先數優先的排程演算法(即把處理機分配給優先數最高的程序)。每個程序有一個程序控制塊( PCB)表示。程序控制塊可以包含如下資訊:程序名、優先數、到達時間、需要執行時間、已用CPU時間、程序狀態等等。程序的優先數及需要的執行時間可以事先人為地指定(也可以由隨機數產生)。程序的到達時間為程序輸入的時間。程序的執行時間以時間片為單位進行計算。每個程序的狀態可以是就緒 W(Wait)、執行R(Run)、或阻塞F(Finish)三種狀態之一。就緒程序獲得 CPU後都只能執行一個時間片。用已佔用CPU時間加1來表示。如果執行一個時間片後,程序的已佔用 CPU時間已達到所需要的執行時間,則撤消該程序,如果執行一個時間片後進程的已佔用CPU時間還未達所需要的執行時間,也就是程序還需要繼續執行,此時應將程序的優先數減1(即降低一級),然後把它插入就緒佇列等待CPU。每進行一次排程程式都列印一次執行程序、就緒佇列、以及各個程序的 PCB,以便進行檢查。  

3)重複以上過程,直到所要程序都完成為止。

排程演算法的流程圖如下 :


實驗結論

1)給出實驗源程式(附有詳細註釋)

2)程式執行截圖

#include <stdio.h>
#include <stdlib.h>

typedef struct pcb
{
	int name; // 程序的名稱
	char state;// 程序的狀態
	int arrivetime; //程序的到達時間
	int runtime;// 程序的執行時間
	int cputime;//cpu佔用的時間
	int count;//優先數
	struct pcb *next;
}pcb;
pcb *head = NULL; // 正常對列
pcb *head1 = NULL; // 未到達的對列
int n = 0;// 程序的數量
//建立頭指標
void createhead()
{
	pcb *p = (pcb*)malloc(sizeof(pcb));// 建立頭指標
	head = p;
	pcb *q = (pcb*)malloc(sizeof(pcb));// 建立頭指標
	head1 = q;
}
void sort()// 按照優先數進行排序
{
	pcb* t = head;
    pcb *q,*p,*r;
    int max;
    while(t->next != NULL)
    {
		p = t->next;
		r = t->next;
		max = r->count;
        while(r!= NULL)
        {
			if(r->count > max)
			{
				max = r->count;
                p = r;
			}
            r = r->next;
		}// p指向count最大的那一個數
        q = t;
		while (q->next != p)
			q = q->next;
		if(t->next != p)
		{
			q->next = p->next;
			p->next = t->next;
			t->next = p;
		}// 插入進行排序按照優先數
        t = t->next;
	}
}
bool create() //建立pcb操作
{
	createhead();
	pcb *p = head;
	pcb *q = head1;
	printf("請輸入程序數目:");
	scanf("%d",&n);
	pcb *temp;
    for(int i=1;i<=n;i++ )//尾插法建立就緒佇列
    {
		temp = (pcb*)malloc(sizeof(pcb));
        if(!temp) return false;
        printf("請輸入程序%d的要求執行時間,程序優先數,到達時間:",i);
		scanf("%d %d %d",&(temp->runtime),&(temp->count),&(temp->arrivetime));
		temp->cputime = 0;
        temp->name=i;
		temp->next = NULL;
        temp->state='W';
		if(temp->arrivetime!=0) // 對到達時間進行判斷
		{
			q->next = temp;
			q = temp;
		}
		else
		{
			p->next = temp;
			p = temp;
		}
	}
	sort(); // 排序
	return true;
}
void destory(pcb *rp)// 撤銷操作
{
	printf("****************程序%d已完成****************\n",rp->name);
	pcb *q = rp->next;
	head->next = q;
	free(rp);
}
void display(pcb *rp) // 展示當前的資訊
{
	printf("程序名字:%d",rp->name);
	printf("\n程序優先順序:%d",rp->count);
	printf("\n程序所佔時間片:%d",rp->runtime);
	printf("\n程序已執行時間:%d",rp->cputime);
	printf("\n程序當前狀態:%c",rp->state);
	printf("\n=====================================\n");
}
void arrivetime()// 對於到達時間-1的操作
{
	pcb *q = head1->next;
	pcb *r,*t;
	while(q!=NULL) // 判斷到達時間是否為0 此時是否到達
	{
		q->arrivetime--;
		if(q->arrivetime==0)
		{
			t = head1;
			while(t->next!=q)
				t = t->next;
			t->next = q->next;
			r = head->next;
			q->next = r;
			head->next = q;
		}
		q = q->next;
	}
}
void runpcb(pcb *rp)
{
	rp->cputime++; //修改cpu佔用的時間
	arrivetime();
	printf("----------正在執行的程序----------\n"); // 輸出正在執行的佇列
	display(rp);
	if(rp->cputime==rp->runtime)
	{
		destory(rp);
	}
	else
	{
		rp->count--;
		rp->state = 'W';
	}
	pcb *p = head;
	if(head->next==NULL&&head1->next==NULL) return;
	printf("----------處於就緒對列的程序----------\n"); // 輸出就緒的佇列
	while(p->next!=NULL)
	{
		display(p->next);
		p = p->next;
	}
	pcb *q = head1;
	while(q->next!=NULL)
	{
		display(q->next);
		q = q->next;
	}
	sort();
}
int main()
{
	create();// 創造程序
	pcb * p;
	while(head->next!=NULL || head1->next!=NULL) // 判斷兩個對列的程序是否都走完
	{
		if(head->next!=NULL)
		{
			p= head->next;
			p->state='R';
			runpcb(p);
		}
		else
		{
			arrivetime();
		}
	}
	return 0;
}