實驗目的:
1 理解操作系統內核與應用程序的差別,哪些信號和操作是操作系統內核能捕捉到而應用程序無法捕捉到的?可以用什麼樣的操作去代替?
2 理解操作系統如何完成進程的控制(創建、撤消、阻塞、喚醒)
3 理解操作系統是如何利用進程控制塊來管理和控制進程的?
程序功能:
1 提供觸發進程創建、撤銷、阻塞、喚醒的界面和操作
2 完成進程的創建、撤銷、阻塞、喚醒功能
3 界面能在每次操作後分別顯示當前處於就緒態、阻塞態、運行態進程的狀態、優先權、進程id
4 實現進程調度的模擬,用基於優先權的調度算法實現進程調度。
程序功能實現:
通過界面選項選擇進程創建、撤銷、阻塞、喚醒操作。
就緒隊列,阻塞隊列、運行隊列通過全局變量的結構體指針實現。
創建函數通過全局變量分配唯一進程ID,進程需要運行時間,優先級手動輸入。時間片大小默認爲5。
#include <stdio.h>
#include <stdlib.h>
#include<windows.h>
/*進程控制塊結構體*/
struct task_struct
{
int id; //進程id
int state; //-1就緒, 0運行, >0 阻塞(本程序默認爲1,不區分阻塞隊列)
int priority; //優先級
int needtime; //運行完畢所需時間
int arrivedtime; //已運行時間
int slicetime; //時間片剩餘時間,初始化爲5
struct task_struct* next;
};
/*進程隊列*/
struct task_struct* runnableTask; //運行
struct task_struct* unrunnableTask; //就緒
struct task_struct* stoppedTask; //阻塞
//進程id控制,每次自增1
int id = 1;
/*函數名聲明*/
void taskController();
void createTask();
void stopTask();
void awakeTask();
void runTask();
void showTask();
void scheduleTask();
void getBigPriorityTask();
void deleteTask();
int main()
{
runnableTask = NULL;
unrunnableTask = NULL;
stoppedTask = NULL;
printf("進程模擬\n");
while(1)
{
taskController();
}
return 0;
}
/*
本函數模擬進程控制程序
本函數執行一次運行,當前執行進程時間片減一
本函數創建進程不佔當前執行進程時間
*/
void taskController()
{
char select;
printf("本函數爲進程控制函數\n");
printf(" 1.創建進程\n");
printf(" 2.阻塞當前進程\n");
printf(" 3.喚醒選定進程\n");
printf(" 4.撤銷進程\n");
printf(" 5.無操作\n");
printf(" 6.退出\n");
printf("\n請輸入你的選擇(1--6):");
do
{
select=getchar();
}
while(select!='1'&&select!='2'&&select!='3'&&select!='4' &&select!='5' &&select!='6');
switch(select)
{
case '1':
createTask();
break;
case '2':
stopTask();
break;
case '3':
awakeTask();
break;
case '4':
deleteTask();
break;
case '5':
break;
case '6':
exit(0);
break;
default:
return ;
}
runTask();
showTask();
}
/*
創建進程,新創建進程添加到就緒進程隊尾
*/
void createTask()
{
printf("\n\n\n\n創建進程開始\n");
if(unrunnableTask == NULL) //判斷是否已有就緒進程 //判斷是否爲首指針
{
unrunnableTask = malloc(sizeof(struct task_struct));
unrunnableTask->id = id++;
printf("進程優先級:\n");
scanf("%d",&unrunnableTask->priority);
printf("進程運行需要的時間:\n");
scanf("%d",&unrunnableTask->needtime);
unrunnableTask->arrivedtime=0;
unrunnableTask->state=-1;
unrunnableTask->slicetime=0;
unrunnableTask->next = NULL;
}
else
{
struct task_struct* test = unrunnableTask;
while(test->next != NULL)
{
test = test->next;
}
test->next = malloc(sizeof(struct task_struct));
test->next->id = id++;
printf("進程優先級:\n");
scanf("%d",&test->next->priority);
printf("進程運行需要的時間:\n");
scanf("%d",&test->next->needtime);
test->next->arrivedtime=0;
test->next->state=-1;
test->next->next = NULL;
test->next->slicetime=0;
test = test->next;
}
}
/*
撤銷內存程序
*/
void deleteTask()
{
//撤銷運行進程
char select;
printf("撤銷運行進程輸入Y/y,不撤銷輸入N/n。\n");
do
{
select=getchar();
}
while(select!='y'&&select!='n'&&select!='Y'&&select!='N');
if(select=='y' || select=='Y')//進行撤銷
{
free(runnableTask);
runnableTask = NULL;
scheduleTask();
return ;
}
//撤銷阻塞進程
printf("撤銷阻塞進程輸入Y/y,不撤銷輸入N/n。\n");
do
{
select=getchar();
}
while(select!='y'&&select!='n'&&select!='Y'&&select!='N');
if(select=='y' || select=='Y')//選擇撤銷
{
struct task_struct* test = stoppedTask;
while(test != NULL) //循環輸出阻塞進程信息
{
printf("本進程信息爲\n");
printf("\n 進程名 優先級 需要時間 已用時間 剩餘時間片 進程狀態 \n");
printf("%8d %8d %8d %10d %10d %10d \n",test->id,test->priority,test->needtime,test->arrivedtime, test->slicetime, test->state);
printf("撤銷本進程輸入Y/y,不撤銷輸入N/n。\n");
do
{
select=getchar();
}
while(select!='y'&&select!='n'&&select!='Y'&&select!='N');
if(select=='y' || select=='Y') //選擇撤銷該進程
{
//從進程隊列刪除撤銷進程
if(stoppedTask == test) //判斷是否爲隊首
{
stoppedTask=test->next;
}
else //撤銷進程非隊首
{
struct task_struct* test3 = stoppedTask;
while(test3->next != test)
{
test3 = test3->next;
}
test3->next = test->next;
}
free(test);
scheduleTask();
return ;
}
}
}
//撤銷就緒進程
printf("撤銷就緒進程輸入Y/y,不撤銷輸入N/n。\n");
do
{
select=getchar();
}
while(select!='y'&&select!='n'&&select!='Y'&&select!='N');
if(select=='y' || select=='Y')//選擇撤銷
{
struct task_struct* test = unrunnableTask;
while(test != NULL) //循環輸出阻塞進程信息
{
printf("本進程信息爲\n");
printf("\n 進程名 優先級 需要時間 已用時間 剩餘時間片 進程狀態 \n");
printf("%8d %8d %8d %10d %10d %10d \n",test->id,test->priority,test->needtime,test->arrivedtime, test->slicetime, test->state);
printf("撤銷本進程輸入Y/y,不撤銷輸入N/n。\n");
do
{
select=getchar();
}
while(select!='y'&&select!='n'&&select!='Y'&&select!='N');
if(select=='y' || select=='Y') //選擇撤銷該進程
{
//從進程隊列刪除撤銷進程
if(unrunnableTask == test) //判斷是否爲隊首
{
unrunnableTask=test->next;
}
else //撤銷進程非隊首
{
struct task_struct* test2 = unrunnableTask;
while(test2->next != test)
{
test2 = test2->next;
}
test2->next = test->next;
}
free(test);
scheduleTask();
return ;
}
}
}
}
/*
阻塞進程程序
*/
void stopTask()
{
if(runnableTask == NULL)
{
printf("無運行進程!\n");
return ;
}
runnableTask->state = 1; //阻塞進程狀態默認爲1,將進程放入阻塞隊列由runTask實現
}
/*
喚醒程序,喚醒優先級最大的進程,若有優先級相同進程,喚醒先進入隊列的進程
*/
void awakeTask()
{
//無阻塞進程,退出
if(stoppedTask == NULL)
{
printf("無阻塞進程!\n");
return ;
}
int max = -100;
struct task_struct* test = stoppedTask;
while(test != NULL)
{
if(max < test->priority)
{
max = test->priority;
}
test = test->next;
}
if(max == stoppedTask->priority) //判斷是否爲隊首
{
//將進程放入就緒隊列中
if(unrunnableTask == NULL)//判斷就緒隊列是否爲空
{
unrunnableTask = stoppedTask;
unrunnableTask->state=0;
stoppedTask = stoppedTask->next;
unrunnableTask->next = NULL;
}
else//放到就緒隊列隊尾
{
struct task_struct* test2 = unrunnableTask;
while(test2->next != NULL)
{
test2 = test2->next;
}
stoppedTask = stoppedTask->next;
test2->next = stoppedTask;
test2->next->state=-1;
test2->next->next=NULL;
}
}
else //喚醒進程不在隊首
{
//確定應喚醒進程在阻塞進程隊列的位置
struct task_struct* test3 = stoppedTask;
while(test3->next->priority != max)
{
test3 = test3->next;
}
//將進程放入就緒隊列中
if(unrunnableTask == NULL) //判斷就緒隊列是否爲空
{
unrunnableTask = test3->next;
unrunnableTask->state=-1;
test3->next = test3->next->next;
unrunnableTask->next=NULL;
}
else //放到就緒隊列隊尾
{
printf("test3");
struct task_struct* test2 = unrunnableTask;
while(test2->next != NULL)
{
test2 = test2->next;
}
test2->next = test3->next;
test2->next->state=-1;
test3->next = test3->next->next;
test2->next->next=NULL;
}
}
scheduleTask();
}
/*
模擬運行運行狀態進程
運行進程時間片時間減1
已用時間加1
判斷是否啓動進程調度程序
*/
void runTask()
{
printf("\n\n\n\n運行進程開始\n");
if(runnableTask != NULL)
{
printf("進程運行中……\n");
runnableTask->arrivedtime += 1;
runnableTask->slicetime -= 1;
if(runnableTask->arrivedtime == runnableTask->needtime) //當運行進程完成
{
printf("當前運行進程執行完畢\n");
printToScreen(runnableTask);
printf("運行進程執行完畢,執行進程調度程序\n");
free(runnableTask);
runnableTask = NULL;
scheduleTask();
}
else if(runnableTask->slicetime == 0) //當運行進程時間片用完
{
//改變進程優先級,運行進程優先級-1,阻塞進程優先級+2
runnableTask->priority -= 1;
//將運行完進程放回就緒進程
if(unrunnableTask == NULL)
{
unrunnableTask = runnableTask;
unrunnableTask->state=-1;
}
else
{
struct task_struct* test = unrunnableTask;
test->priority += 2;
while(test->next != NULL)
{
test = test->next;
test->priority += 2;
}
test->next = runnableTask;
test->next->state = -1;
test->next->next=NULL;
}
runnableTask = NULL;
printf("運行進程時間片用完,執行進程調度程序\n");
scheduleTask();
}
else if(runnableTask->state > 0) //當運行進程被阻塞
{
//將被阻塞進程放入阻塞進程
if(stoppedTask == NULL)
{
stoppedTask = runnableTask;
stoppedTask->state=1;
stoppedTask->next=NULL;
}
else
{
struct task_struct* test = stoppedTask;
while(test->next != NULL)
{
test = test->next;
}
test->next = runnableTask;
test->next->state=1;
test->next->next=NULL;
}
runnableTask = NULL;
printf("運行進程被阻塞,執行進程調度程序\n");
scheduleTask();
}
}
else
{
printf("無正在運行進程,調用進程調度程序\n");
scheduleTask();
}
}
/*
模擬進程調度程序
*/
void scheduleTask()
{
if(runnableTask==NULL||runnableTask->slicetime==0||runnableTask->needtime==runnableTask->arrivedtime||runnableTask->state>0) //判斷是否符合切換運行進程條件
{
printf("\n\n\n\n運行調度開始\n");
if(unrunnableTask != NULL) //判斷有無就緒進程
{
if(runnableTask==NULL||runnableTask->slicetime==0||runnableTask->needtime==runnableTask->arrivedtime||runnableTask->state>0)
{
getBigPriorityTask();
}
else //運行進程隊列不需切換進程但進入
{
printf("進程調度程序出現未知錯誤\n");
}
}
else //無就緒進程
{
printf("無就緒進程可供調度\n");
}
}
else
{
printf("進入進程調度程序錯誤\n");
}
}
/*
對進程排序,並將最大優先級的進程給運行進程
*/
void getBigPriorityTask()
{
int max = -100;
struct task_struct* test = unrunnableTask;
while(test != NULL)
{
if(max < test->priority)
{
max = test->priority;
}
test = test->next;
}
if(max == unrunnableTask->priority) //判斷是否爲隊首
{
runnableTask = unrunnableTask;
runnableTask->state=0;
unrunnableTask = unrunnableTask->next;
runnableTask->next = NULL;
runnableTask->slicetime=5;
}
else
{
test = unrunnableTask;
while(test->next != NULL)
{
if(test->next->priority == max)
{
runnableTask=test->next;
runnableTask->state=0;
test->next = test->next->next;
runnableTask->next = NULL;
runnableTask->slicetime=5;
}
break;
}
}
}
/*
顯示進程狀態
*/
void showTask()
{
printf("----------運行進程----------\n");
if(runnableTask != NULL)
{
printToScreen(runnableTask);
}
printf("----------就緒進程----------\n");
if(unrunnableTask != NULL)
{
printToScreen(unrunnableTask);
}
printf("----------阻塞進程----------\n");
if(stoppedTask != NULL)
{
printToScreen(stoppedTask);
}
}
/*
向屏幕輸出進程狀態
*/
void printToScreen(struct task_struct* test)
{
printf("\n 進程名 優先級 需要時間 已用時間 剩餘時間片 進程狀態 \n");
while(test != NULL)
{
printf("%8d %8d %8d %10d %10d %10d \n",test->id,test->priority,test->needtime,test->arrivedtime, test->slicetime, test->state);
test = test->next;
}
}