操作系统实验报告【太原理工大学】
操作系统实验报告
温馨提示:仅供参考!
目录
一、进程调度程序设计
1.程序清单
#include<stdio.h>
#include<stdlib.h>
#define furthest 5
struct process /*PCB STRUCTURE*/
{
int id;
int priority;
int cputime;
int alltime;
char state;
int next;
}prochain[furthest+1]; //队列中有5项实际的内容,而数组0号内放着head,next指向下一个数组的0号
int procnum;
int rand();
int algo;
int run,head,tail,j;
void init();//声明函数
void prisch();//声明函数
void print(); //声明函数
void timesch();//声明函数
void insert(int q);//声明函数
void insert2(); //17-22行对函数进行了声明,如果使用自己定义的函数,这个函数在调用它的函数的后面(main函数后面),
//必须在调用之前进行函数声明。因为程序是从上到下逐行编译的,若无函数声明,则会无法识别函数。
//则函数头必须写在main函数的前面如果使用自己定义的函数,这个函数在调用它的函数的后面(main函数后面)。
int main(){
agan: printf("type the algorithm is (1:RR,2:PRIO):");
scanf("%d",&algo);
if(algo==2){
printf("output of priority.n"); //优先级
init();
prisch();
}
else{
if(algo==1){
printf("output of round robin.n"); //轮转法
init();
timesch();}
else{
printf("try again,pleasen");
goto agan;
}
}
for(j=1;j<=40;j++)
{ printf("="); }
printf("nn");
for(j=1;j<=40;j++)
{ printf("="); }
printf("nn");
printf("system finishedn");
}
void print(){
int k,p;
for(k=1;k<=40;k++)
printf("=");
printf("nrunning proc. ");
printf("waiting queue.");
printf("n %d ",prochain[run].id);
p=head;
while(p!=0){
printf("%5d",p);
p=prochain[p].next;}
printf("n");
for(k=1;k<=40;k++)
printf("=");
printf("n");
printf(" id ");
for(k=1;k<furthest+1;k++)
printf("%5d",prochain[k].id);
printf("n");
printf("priority ");
for(k=1;k<furthest+1;k++)
printf("%5d",prochain[k].priority);
printf("n");
printf("cputime ");
for(k=1;k<furthest+1;k++)
printf("%5d",prochain[k].cputime);
printf("n");
printf("alltime ");
for(k=1;k<furthest+1;k++)
printf("%5d",prochain[k].alltime);
printf("n");
printf("state ");
for(k=1;k<furthest+1;k++)
printf("%5c",prochain[k].state);
printf("n");
printf("next ");
for(k=1;k<furthest+1;k++)
printf("%5d",prochain[k].next);
printf("n");
}
void insert(int q) /*INSERT A PROCESS*/
{
int p,s;
p=head;
s=prochain[head].next;
while((prochain[q].priority<prochain[s].priority)&&(s!=0)){
p=s;
s=prochain[s].next;
}
prochain[p].next=q;
prochain[q].next=s;
}
void insert2() /*PUT A PROCESS ONTO THE TAIL OF THE QUEUE*/
{
prochain[tail].next=run;
tail=run;
prochain[run].next=0;
}
void init() /*CREATE A WAITING QUEUE*/
{
int i;
head=0;
if(algo==2){
for (i=1;i<furthest+1;i++){
prochain[i].id=i; //进程标识符id
prochain[i].priority=(rand()+11)%41; //优先数/轮转时间片数
prochain[i].cputime=0; //占用CPU时间片数
prochain[i].alltime=(rand()+1)%7; //进程所需时间片数
prochain[i].state='W'; //进程状态
prochain[i].next=0; //链指针
if((prochain[i].priority<prochain[head].priority)&&(head!=0))
insert(prochain[i].id);
else{
prochain[i].next=head;
head=prochain[i].id;
}
}
}
else{
for (i=1;i<furthest+1;i++){
prochain[i].id=i;
prochain[i].priority=(rand()+1)%3+1;
prochain[i].cputime=0;
prochain[i].alltime=(rand()+1)%7;
prochain[i].state='W';
prochain[i].next=(i+1)%(furthest+1);}
head=1;
tail=furthest;
prochain[furthest].next=0;
}
run=head;
prochain[run].state='R';
head=prochain[head].next;
prochain[run].next=0;
print();
}
//prisch为优先级
void prisch() /*THE PROCESS WITH PRIO ALGORITHM*/
{
while(run!=0){
if(prochain[run].alltime==0){
prochain[run].state='F';
prochain[run].next=0;
if(head!=0){
run=head;
prochain[run].state='R';
head=prochain[head].next;}
else{
prochain[0].id=prochain[run].id;
run=0;
}
} //运行中要先用if语句判断一下第一个运行的alltime是否为0,若为0,
//则直接从RUN状态变为FINISH状态,接着才能运行下面的内容,否则
//alltime为负值则会一直无限循环下去
prochain[run].cputime+=1;
prochain[run].priority-=3;
prochain[run].alltime-=1;
/*下面的运行后也要再用if语句判断一下运行后的alltime是否为0,
若为0, 则直接从RUN状态变为FINISH状态,接着才能运行下面的内
容,否则alltime为负值也会一直无限循环下去 */
if(prochain[run].alltime==0){
prochain[run].state='F';
prochain[run].next=0;
if(head!=0){
run=head;
prochain[run].state='R';
head=prochain[head].next;}
else{
prochain[0].id=prochain[run].id;
run=0;
}
}
else{
if((prochain[run].priority<prochain[head].priority)&&(head!=0)){
prochain[run].state='W';
insert(run);
run=head;
prochain[run].state='R';
head= prochain[head].next;
}
}
print();
}
}
/*
下面轮转法中timesch函数下的重要性就相当于用priority表示,使用priority次数用尽
后,继续执行下一个进程,在进程都结束后,占用cpu时间开始累加直至结束。
*/
void timesch() /*THE PROCESS WITH RR ALRORITHM*/
{
while(run!=0){
if(prochain[run].alltime==0){
prochain[run].state='F';
prochain[run].next=0;
if(head!=0){
run=head;
prochain[run].state='R';
head=prochain[head].next;
}
else{
prochain[0].id=prochain[run].id;
run=0;
}
}
//上述if语句同优先级方法类似,先判断alltime是否为0,可以解决死循环问题
prochain[run].alltime-=1;
prochain[run].cputime+=1;
if(prochain[run].alltime==0){
prochain[run].state='F';
prochain[run].next=0;
if(head!=0){
run=head;
prochain[run].state='R';
head=prochain[head].next;
}
else{
prochain[0].id=prochain[run].id;
run=0;
}
}
else{
if((prochain[run].cputime==prochain[run].priority)&&(head!=0)){
prochain[run].state='W';
prochain[run].cputime=0;
insert2();
run=head;
prochain[run].state='R';
head=prochain[head].next;
}
}
print();
}
}
2.运行结果
① 简单轮转法:
② 优先数法
3.分析总结
此实验运用了俩种方法进行了程序的调度。在简单轮转方法中,本程序代码中timesch函数下的重要性用priority表示,使用priority次数用尽后,继续执行下一个进程,在进程都结束后,占用cpu时间才开始累加直至结束。
而在优先数方法中,每一次都要判断一下优先级最高的进程,然后alltime进行减1,cputime加1处理,直到alltime为0后,进程状态才由“R”变为“F”。
在本实验纠错过程中,两种方法下程序在第一次不判断alltime是否为0时就会出现所谓的“死”循环,在时间片减1、优先数减3或者时间片减1、cpu时间加1后,还要再次进行alltime是否为0的判断,两者都要存在才能保证程序的正常运行。
二、页式虚拟存储管理程序设计
1.程序清单
#include<stdio.h>
#define number 7
#define null -1
struct page_table
{
int page_number;
int sign;
int block;
int modify;
int place;
};
struct page_table work_page[number]={{0,1,5,0,11},{1,1,8,0,12},{2,1,9,0,13},
{3,1,1,0,21},{4,0,null,0,22},{5,0,null,0,23},{6,0,null,0,121}};
struct performance_list
{
int list_number;
char operation[8];
int page_number;
int page_address;
};
struct performance_list work_list[12]={{1,"+",0,70},{2,"+",1,50},
{3,"*",2,15},{4,"存",3,21},{5,"取",0,56},{6,"-",6,40},{7,"移位",4,53},
{8,"+",5,23},{9,"存",1,37},{10,"取",2,78},{11,"+",4,1},{12,"存",6,84}};
int main(){
int new_number,new_sign,new_block,new_modify,new_list_number,j;
char new_place[6],new_operation[8];
int p[4]={0,1,2,3};//四块主存块
int k=0;
int m=4;
long new_address;
printf("n 序号t 操作t 页号t 页内地址t 标志位t 绝对地址t 页号变化t 块号t绝对地址n");
for(int i=0;i<12;i++)
{
new_list_number=work_list[i].list_number;
printf("%5d",new_list_number); //输出序号
new_number=work_list[i].page_number;
new_sign=work_page[new_number].sign;
new_block=work_page[i].block;
new_modify=work_page[i].modify;
if(new_sign==1)
new_address=work_page[new_number].block*1024+work_list[i].page_address;
else{
j=p[k];
p[k]=new_number;
k=(k+1)%m;
work_page[new_number].sign=1; //修改标志位改为1
work_page[new_number].block=work_page[j].block;
work_page[j].block=-1;
work_page[j].sign=0;
work_page[j].modify=0;
new_address=work_page[new_number].block*1024+work_list[i].page_address;
}
if(work_list[i].operation=="存")
work_page[new_number].modify=1;
printf(" %5s",work_list[i].operation);//输出操作
printf(" %d",new_number);//输出页号
printf(" %2d",work_list[i].page_address);//输出页内地址
printf(" %d",new_sign);//输出标志位
if(new_sign==1)
printf(" %d",new_address);// 输出绝对地址
else
printf(" *%d",work_list[i].page_number);//输出*页号
if(new_sign==1)
printf(" t");//无地址转换输出空格
else
printf(" %d->%dt",work_list[i].page_number,j);//展示地址的变化
printf(" %d",work_page[new_number].block);//输出相应的块号
printf(" %d",new_address);
printf("n");
}
}
2.运行结果
3.分析总结
首先将作业的页表与作业的指令序列链接起来,形成一个新表,然后根据新表通过判断是否为标志位以及是否为“存”指令进行绝对地址的计算。在页表中通过增加是否修改过的标志,(当执行“存”指令、“写”指令时把对应页的修改标志置成“1”,表示该页修改过,否则为“0”,表示该页未修改过),来对“存”指令以及页面是否调出进行了判断。实验中标志位为“0”时,进行了页号的修改,修改后进行绝对地址的计算。
三、几种操作系统界面的熟悉
1.程序清单
① C语言编写9*9乘法表
② python 编写9*9乘法表
2.运行结果
3.分析总结
熟悉多种操作系统的界面,在熟练使用机器的基础上,了解了各种操作命令和系统调用在系统中的大致工作过程。熟悉系统实用程序的调用方法和各种系统调用模块的功能和作用,从而有效地使用计算机。