操作系統 實驗一 進程控制

實驗目的:利用簡單的結構和控制方法模擬進程結構、進程狀態轉換和進程控制。

方法:用PCB表示整個進程實體,利用鍵盤交互式命令控制方法模擬進程執行中產生的事件。

實現功能:


                     OS 進程控制                                                                          
           1、自動調度(省略 P 操作)                                                                  
          2、爲進程分配空間(OS起始地址爲100 原有空間大小爲440k)   
           3、結束進程後回收空間                                                                      
           4、重名進程判斷                                                                                  
           5、將操作過程存入文件RUNLOG.txt中                                            

創建進程(c)、結束進程(e)、進程阻塞(b)、激活進程(w)、調度進程(p)、時間片到(t)等事件;鍵盤模擬方法指定義6種按鍵代表以上6種事件。



主要思想:

通過鏈表建立起空白PCB和空閒的內存塊(memory)。

實現以上所有功能都有一個共同的特點,都是不斷的將結點從鏈表的尾部摘下然後利用尾插法插入到另一個鏈表上去。

數據結構:

![endif]-->!--[if>

.


實現過程:

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

FILE *out=fopen("RUNLOG.txt","w");

struct linklist
{
	char name[255];
	int startad,process_size;

	linklist *next;
};

struct memory
{
	int  size,saddress;

	memory *next;
};

memory *OS;

linklist *head_PCB,*rear_PCB;
linklist *head_READY,*rear_READY;
linklist *head_EXCUTE,*rear_EXCUTE;
linklist *head_BLOCK,*rear_BLOCK;


void init(int n) //建立空白PCB
{

	head_PCB=rear_PCB=NULL;
	head_READY=rear_READY=NULL;
	head_EXCUTE=rear_EXCUTE=NULL;
	head_BLOCK=rear_BLOCK=NULL;
	while(n--)
	{
		if(head_PCB==NULL)
		{
			rear_PCB=head_PCB=(linklist*)malloc(sizeof(linklist));
		}
		else
		{
			rear_PCB->next=(linklist*)malloc(sizeof(linklist));
			rear_PCB=rear_PCB->next;
		}
		rear_PCB->next=NULL;
	}
	OS=(memory*)malloc(sizeof(memory));
	OS->next=NULL;
	OS->saddress=100;
	OS->size=440;
	
}

linklist* delete_linklist(linklist *&head,linklist *&rear)//摘下結點
{
	linklist *p;
	p=head;
	if(p==NULL)
	{
		rear=NULL;
		return NULL;
	}
	head=head->next;
	p->next=NULL;
	return p;
	                
}

void insert_linklist(linklist *&head,linklist *&rear,linklist *p)//插入
{
	if(head==NULL)
	{
		head=rear=p;
	}
	else
	{
		rear->next=p;
		rear=p;
	}
}

void show()     //顯示當前進程
{
	linklist *r=head_READY,*e=head_EXCUTE,*b=head_BLOCK;
	printf("Ready process:     ");
	while(r)
	{
		printf("%s\t",r->name);
		r=r->next;
	}
	printf("\nEXCUTE process:     ");
	while(e)
	{
		printf("%s\t",e->name);
		e=e->next;
	}
	printf("\nBLOCK process:     ");
	while(b)
	{
		printf("%s\t",b->name);
		b=b->next;
	}
	printf("\nOS empty space  :\n");
	memory *s;
	s=OS;
	while(s)
	{
		printf("Start address :%d      Size :%d\n",s->saddress,s->size);
		s=s->next;
	}
	if(OS==NULL)
	{
		printf("No left memory!");
	}
	printf("\n");
}
void menu()
{

	printf("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n");
	printf("┃ C :  Create a process.You must input the name of process.      ┃ \n");
	printf("┃ E :  End the process.                                          ┃\n");
	printf("┃ B :  Block the process.You must input the name of process.     ┃ \n");
	printf("┃ W :  Wakeup the process.You must input the name of process.    ┃\n");
	printf("┃ T :  Time Over.	                                          ┃	\n");
	printf("┃ S :  Show All the process name.		                  ┃\n");
	printf("┃ H :  Help.                                                     ┃\n");
	printf("┃ # :  Exit.                                                     ┃\n");
	printf("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n");
}


void share(int &saddr,int &size)   //爲進程分配空間
{
	memory *p,*k,*best_fit,*m;	
	int min_place=10000000;
	
	best_fit=NULL;
	k=NULL;                        
	p=OS;
	
	while(p!=NULL)
	{
		if(p->size>=size && p->size-size<min_place)   /*在OS空閒空間中找出最佳分配的結點*/
		{
			best_fit=p;
			min_place=p->size-size;
			m=k;                         /*m保存了最佳分配的結點的前趨*/
		}
		k=p;  /*k保存p的前趨*/
		p=p->next;
	}
	
	saddr=best_fit->saddress;
	best_fit->size-=size;
	best_fit->saddress+=size;
	
	if(best_fit->size<4)        /*如果剩餘空間小於4k則釋放結點*/
	{
		if(m==NULL)
		{
			memory *s;
			s=OS;
			OS=OS->next;
			size+=best_fit->size;
			free(s);
		}
		else
		{
			m->next=best_fit->next;
			size+=best_fit->size;
			free(best_fit);
		}
	}


}
void recycle(int &addr,int &size)//回收
{
	memory *p,*k;   
	p=OS;
	k=NULL;
	if(p==NULL)        //OS原內存無空閒空間  
	{
		OS=(memory*)malloc(sizeof(memory));		
		OS->saddress=addr;
		OS->size=size;
		OS->next=NULL;
	}
	else
	{
		while(p!=NULL)
		{
			if(p->saddress+p->size<=addr)
			{
				k=p;
			}
			else
				break;
			p=p->next;	
		}
		if(k==NULL)
		{
			if(addr+size==p->saddress)//如果可以和下一個結點合併
			{
				p->saddress=addr;
				p->size+=size;
				return ;
			}
			else
			{
				memory *s;
				s=(memory *)malloc(sizeof(memory));
				s->saddress=addr;
				s->size=size;
				s->next=p;
				OS=s;
			}
		}
		else
		{
			if(k->saddress+k->size==addr)				/*與上一結點合併*/
			{
				k->size+=size;
				if(k->next!=NULL && k->saddress+k->size==k->next->saddress)				/*查看是否能與下一結點合併*/
				{
					k->size+=k->next->size;
					memory *s;
					s=k->next;
					k->next=s->next;
					free(s);
				}
			}
			else if(k->next!=NULL && addr+size==k->next->saddress)					/*上佔下空*/
			{
				k->next->saddress=addr;
				k->next->size+=size;
			}
			else							 /*上佔下佔*/
			{
				memory *s;
				s=(memory *)malloc(sizeof(memory));
				s->saddress=addr;
				s->size=size;
				s->next=k->next;
				k->next=s;
			}
		}	
	}
}

int os(int x)
{
	memory *p=OS;
	while(p!=NULL)
	{
		if(p->size>=x)
			return 1;
		p=p->next;
	}
	return 0;
}

int judgename(char *s)  //判斷是否有重名進程
{
	linklist *r,*e,*b;
	
	r=head_READY;
	e=head_EXCUTE;
	b=head_BLOCK;

	while(r!=NULL)
	{
		if(strcmp(r->name,s)==0)
			break;
		r=r->next;
	}
	if(r==NULL)
	{
		while(e!=NULL)
		{
			if(strcmp(e->name,s)==0)
				break;
			e=e->next;
		}
		if(e==NULL)
		{
			while(b!=NULL)
			{
				if(strcmp(b->name,s)==0)
					break;
				b=b->next;
			}
			if(b==NULL)
				return 1;		//沒有重名進程
			return 0;
		}
		else
			return 0;
	}
	else
	{
		return 0;//有重名進程
	}
}

void cometrue()  //功能實現
{
	char ch;	char a[255],b[255];
	while(1)
	{
		scanf("%c",&ch);
		if(ch!='s'&&ch!='S'&&ch!='#'&&ch!='\n')
			fprintf(out,"%c\n",ch);
		if(ch=='c'||ch=='C')  //創建進程
		{
			if(head_PCB==NULL)
			{
				printf("No PCB!");
				fprintf(out,"No PCB!\n");
			}
			else
			{
				linklist *p;
				p=delete_linklist(head_PCB,rear_PCB);
				printf("Please input the process's name: \n-");
				scanf("%s",p->name);
	
				if(judgename(p->name))
				{
					
					printf("Please input the place this process need: \n-");
					scanf("%d",&p->process_size);
					if(os(p->process_size))
					{
						share(p->startad,p->process_size);
						insert_linklist(head_READY,rear_READY,p);
						itoa(p->process_size,a,10);
						itoa(p->startad,b,10);
						printf("Create %s process success!	Start address is %d.	Size is %d.\n",p->name,p->startad,p->process_size);	
						
						fprintf(out,"Create  %s  process success!	Start address is %s.	Size is %s.\n",p->name,b,a);
						if(head_EXCUTE==NULL)
							insert_linklist(head_EXCUTE,rear_EXCUTE,delete_linklist(head_READY,rear_READY));
					}
					else
					{
						printf("OS memory limit!\n");
						fprintf(out,"OS memory limit!\n");
					}
				}
				else
				{
					while(judgename(p->name)==0)
					{
						printf("Error: Can not create process,the process exist.\n");
						fprintf(out,"Error: Can not create process,the process exist.\n");
						printf("Here is all exist process:\n");
						show();
						printf("Please input another name: \n-");
						scanf("%s",p->name);
					}
					printf("Please input the place this process need: \n-");
					scanf("%d",&p->process_size);
					if(os(p->process_size))
					{
						share(p->startad,p->process_size);
						insert_linklist(head_READY,rear_READY,p);
						itoa(p->process_size,a,10);
						itoa(p->startad,b,10);
						printf("Create %s process success!	Start address is %d.	Size is %d.\n",p->name,p->startad,p->process_size);
					
						fprintf(out,"Create  %s  process success!	Start address is %s.	Size is %s.\n",p->name,b,a);
						if(head_EXCUTE==NULL)
							insert_linklist(head_EXCUTE,rear_EXCUTE,delete_linklist(head_READY,rear_READY));
					}
					else
					{
						printf("OS memory limit!\n");
						fprintf(out,"OS memory limit!\n");
					}
				}
			
			}
			printf("In put your command \n>");
		}
		else if(ch=='b'||ch=='B')					//   阻塞
		{
			if(head_EXCUTE==NULL)
			{
				printf("Error: No excute process!\n");
				fprintf(out,"Error: No excute process!\n");
			}
			else
			{
				insert_linklist(head_BLOCK,rear_BLOCK,delete_linklist(head_EXCUTE,rear_EXCUTE));
				if(head_READY!=NULL)
					insert_linklist(head_EXCUTE,rear_EXCUTE,delete_linklist(head_READY,rear_READY));
			}
			printf("In put your command \n>");
		}
		else if(ch=='e'||ch=='E')        //結束進程
		{
			if(head_EXCUTE==NULL)
			{
				printf("Error: No excute process!\n");
				fprintf(out,"Error: No excute process!\n");
			}
			else 
			{
				linklist *p;
				p=delete_linklist(head_EXCUTE,rear_EXCUTE);
				recycle(p->startad,p->process_size);
				printf("End %s process success!\n",p->name);
				fprintf(out,"End %s process success!\n",p->name);
				if(head_READY!=NULL)
					insert_linklist(head_EXCUTE,rear_EXCUTE,delete_linklist(head_READY,rear_READY));
			}
			printf("In put your command \n>");
		}
		else if(ch=='w'||ch=='W')       //喚醒一個進程
		{ 
			if(head_BLOCK==NULL)
			{
				printf("Error: No block process!\n");
				fprintf(out,"Error: No block process!\n");
			}
			else
			{
				insert_linklist(head_READY,rear_READY,delete_linklist(head_BLOCK,rear_BLOCK));
				if(head_EXCUTE==NULL)
					insert_linklist(head_EXCUTE,rear_EXCUTE,delete_linklist(head_READY,rear_READY));
			}
			printf("In put your command \n>");
		}
		else if(ch=='t'||ch=='T')  //時間片到
		{
			if(head_EXCUTE!=NULL)
			{
				insert_linklist(head_READY,rear_READY,delete_linklist(head_EXCUTE,rear_EXCUTE));
				insert_linklist(head_EXCUTE,rear_EXCUTE,delete_linklist(head_READY,rear_READY));
			}
			else
			{
				printf("Error: No excute process!\n");
				fprintf(out,"Error: No excute process!\n");
			}
			printf("In put your command \n>");
		}
		else if(ch=='s'||ch=='S')     //顯示所有進程
		{
			show();
			printf("In put your command \n>");
		}
		else if(ch=='h'||ch=='H')     //幫助、顯示菜單
		{
			menu();
			printf("In put your command \n>");
		}
		else if(ch=='#')    //退出
		{
			return ;
		}
		else
		{
			printf("Bad command!\n>");
			fprintf(out,"Bad command!\n");
		}
		getchar();       //解決有時不識別scanf的問題
	}
}

void main()
{
	init(10);
	menu();
	printf("In put your command \n>");
	cometrue();
	fclose(out);
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章