当前位置:文档之家› 实验报告一-中断处理

实验报告一-中断处理

实验报告一——中断处理:xxxx 学号:xxxx 班级:xxxxx 一、实习容•运用某种高级语言(如C或C++)模拟时钟中断的产生及设计一个对时钟中断事件进行处理的模拟程序。

二、实习目的•现代计算机系统的硬件部分都设有中断机构,中断机构能发现中断事件,且当发现中断事件后迫使正在处理器上执行的进程暂时停止执行,而让操作系统的中断处理程序占有处理器去处理出现的中断事件。

•本实习模拟“时钟中断事件”的处理,对其它中断事件的模拟处理,可根据各中断事件的性质确定处理原则,制定算法,自行设计。

•希望学生通过本实习了解中断及中断处理程序的作用。

三、实习题目1. 计算机系统工作过程中,若出现中断事件,硬件就把它记录在中断寄存器中。

中断寄存器的每一位可与一个中断事件对应,当出现某中断事件后,对应的中断寄存器的某一位就被置成“1”。

•处理器每执行一条指令后,必须查中断寄存器,当中断寄存器容不为“0”时,说明有中断事件发生。

硬件把中断寄存器容以及现行程序的断点存在主存的固定单元。

操作系统分析保存在主存固定单元中的中断寄存器容就可知道出现的中断事件的性质,从而作出相应的处理。

•本实习中,用从键盘读入信息来模拟中断寄存器的作用,用计数器加1来模拟处理器执行了一条指令。

每模拟一条指令执行后,从键盘读入信息且分析,当读入信息=0时,表示无中断事件发生,继续执行指令;当读入信息=1时,表示发生了时钟中断事件,转时钟中断处理程序。

2. 假定计算机系统有一时钟,它按电源频率(50Hz)产生中断请求信号,即每隔20毫秒产生一次中断请求信号,称时钟中断信号,时钟中断的间隔时间(20毫秒)称时钟单位。

•学生可按自己确定的频率在键盘上键入“0”或“1”来模拟按电源频率产生的时钟中断信号。

3. 中断处理程序应首先保护被中断的现行进程的现场(通用寄存器容、断点等),现场信息可保存在进程控制块中;然后处理出现的中断事件,根据处理结果修改被中断进程的状态;最后转向处理器调度,由处理器调度选择可运行的进程,恢复现场使其运行。

•本实习主要模拟中断事件的处理,为简单起见可省去保护现场和处理器调度的工作。

4. 为模拟时钟中断的处理,先分析一下时钟中断的作用。

利用时钟中断可计算日历时钟,也可作定时闹钟等。

•计算日历时钟——把开机时的时间存放在指定的称为“日历时钟”的工作单元中,用一计时器累计时钟中断次数。

根据时钟中断的次数和时钟单位(20毫秒)以及开机时的日历时钟可计算出当前的精确的日历时钟。

•定时闹钟——对需要定时的场合,可把轮到运行的进程的时间片值送到称为“定时闹钟”的工作单元中,每产生一次时钟中断就把定时闹钟值减1,当该值为“0”时,表示确定的时间已到,起到定时的作用。

5. 本实习的模拟程序可由两部分组成,一部分是模拟硬件产生时钟中断,另一部分模拟操作系统的时钟中断处理程序。

模拟程序的算法如图1-1。

其中,保护现场和处理器调度的工作在编程序时可省去。

约定处理器调度总是选择被中断进程继续执行。

6. 按模拟算法设计程序,要求显示或打印开机时间、定时闹钟初值、定时闹钟为“0”时的日历时钟。

确定三个不同的定时闹钟初值,运行设计的程序,观察得到的结果。

四、主要数据结构及符号说明star = localtime(& t);st=asctime(star);//获取开机时间作为起始时间定义每个时间单元为2说明:因为要输入数字模拟有无中断发生,输入频率无法保证和电脑同步,所以用一个数字来记录时间,输出的结束时间不是结束时电脑的时间,而是设每个时间但愿为2s计算的时间。

时钟中断处理模拟算法五、实现代码为:#include<time.h>#include<stdio.h>#include<stdlib.h>int main(){//初始化,显示开机时间time_t t;double p;int a,m,r,n,e,o,u;int count=0,clock_alarm,w,Timer=0;int i;char *st,s[27];struct tm * star;t = time(NULL);star = localtime(& t);st=asctime(star);for(i=0;i<27;i++){s[i]=*st;st++;}printf("*****a simulation program of clock to deal with disruptions*****\n");printf("star time:");for( i=4;i<25;i++){printf("%c",s[i]);}//时间存储在数组中,从第5位开始为月份、时间、年份printf("set clock alarm :");scanf("%d",&clock_alarm);//设置定时闹钟printf("the clock alarm is %d,timer is 0\n",clock_alarm);while(clock_alarm!=0){ //模拟时钟中断do{printf("A piece of order have been finished\n");count++;//模拟一条指令被执行,计数器加1printf("input a number(1 means an interrupt,while 0 means there is no interrupt!\n");scanf("%d",&w);//读键盘信息}while(w==0);//模拟时钟中断处理if(w==1)printf("the spot have been saved!\n");//保护现场,计时器加1,定时闹钟减1,处理器调度Timer++;clock_alarm--;printf("processor finished assignment\n");}//计算当前日历时间p=Timer*2;//define the time unit is 2a=(int)Timer*2;if((p-a)>=0.5)p=a+1;elsep=a;m=(int)p;printf("time have passed :%d\n",m);r=s[17]-48;//计算运行时间n=s[18]-48;e=r*10+n;p=p+e;if(p<60){s[17]=((int)p/10)+48;s[18]=((int)p%10)+48;for( i=4;i<27;i++){printf("%c",s[i]);}}else{s[14]=s[14]-48;s[15]=s[15]-48;o=s[14]*10+s[15];o=o+(int)p/60;if(o<60){s[14]=(o/10)+48;s[15]=(o%10)+48;s[17]=((int)p%60)/10+48;s[18]=((int)p%60)%10+48;for( i=4;i<27;i++){printf("%c",s[i]);}}else{s[11]=s[11]-48;s[12]=s[12]-48;u=s[11]*10+s[12];u=u+o/60;if(u<24){s[11]=u/10+48;s[12]=u%10+48;s[14]=(o%60)/10+48;s[15]=(o%60)%10+48;s[17]=((int)p%60)/10+48;s[18]=((int)p%60)%10+48;for( i=4;i<25;i++){printf("%c",s[i]);}}}}}六、在虚拟机上的具体操作及结果七、思考题将进程调度策略结合到本实习中,可选用时间片轮转的调度策略。

给每个进程分配一个相同的时间片,每产生一次时钟中断经处理后,被中断进程时间片减1,时间片值≠0时,该进程优先运行,若时间片值=0且该进程尚未运行结束,则将它排入队尾,再给它分配一个时间片,直到所有的进程运行结束。

应怎样设计进程控制块?各进程的状态怎样变化?在本实习的程序中加入处理器调度程序。

1、数据结构设计struct dsh{int year;int month;int day;int hour;int min;int sec;int msec;}clock[2]; typedef struct PCB{char name[10];int timep;int time;struct PCB *next;}PCB,*Pnode;//定义结构体2、算法设计#include<stdio.h>#include<stdlib.h>void creat(Pnode L)//用指针连接需要处理的进程{Pnode p,q;int i;i=i;printf("\n 请输入中断时需要处理的一个进程\n");p=(Pnode)malloc(sizeof(PCB));printf("\n 请输入该进程的名字及需要服务的时间\n");scanf("%s%d",p->name,&p->time);p->next=NULL;p->timep=5;q=L;while(q->next)q=q->next;q->next=p;}void disp(Pnode L)//显示出每次中断后,各个进程的信息{Pnode p;p=L->next;if(p!=NULL){printf("\n 目前进程的信息为:\n");printf("\n 名字还需服务时间时间片时间\n");while(p){printf("\n %s\t\t%d\t\t%d\n",p->name,p->tim e,p->timep);p=p->next;}}}void chang(){clock[1].msec=clock[2].msec;clock[1].sec=clock[2].sec;clock[1].min=clock[2].min;clock[1].hour=clock[2].hour;clock[1].day=clock[2].day;clock[1].month=clock[2].month;clock[1].year=clock[2].year;}void disp1()//显示当前时间函数{// ptr=localtime(&lt);// printf(asctime(ptr),"\n");printf("\n 年\t月\t日\t时\t分\t秒\t毫秒\n");printf("\n %d\t%d\t%d\t%d\t%d\t%d\t%d\n", clock[1].year,clock[1].month,clock[1].day,clock[1].hour,clock[1].min,clock[1].sec,clock[1].msec);}void cut(Pnode L,int count)//中断产生后,进程的运行情况{Pnode p,q;int i,j,z,d,m,x,y;x=1;if(L->next==NULL)printf("\n 所有进程已经运行完毕!\n");else{q=L;p=L->next;p->time=p->time-1;p->timep=p->timep-1;if(p->time==0)//如果进程需要服务时间为0,则表示该进程已运行完毕,释放该进程{chang();printf("\n 此进程已经运行结束,它的名字为:%s\n",p->name);L->next=p->next;clock[1].msec=clock[1].msec+count*20;//计算产生中断到该进程运行结束所经历的时间if(clock[1].msec>=1000){i=clock[1].msec/1000;clock[1].sec=clock[1].sec+i;clock[1].msec=clock[1].msec-i*1000;if(clock[1].sec>=60){j=clock[1].sec/60; clock[1].min=clock[1].min+j;clock[1].sec=clock[1].sec-j*60;if(clock[1].min>=60){z=clock[1].min/60;clock[1].hour=clock[1].hour+z;clock[1].min=clock[1].min-z*60;if(clock[1].hour>=24){d=clock[1].hour/24;clock[1].day=clock[1].day+d;clock[1].hour=clock[1].hour-d*24;if(clock[1].day>28){if(clock[1].year%400==0||(clock[1].year%4== 0&&clock[1].year%100!=0)){while(clock[1].day>28&&x==1){x=0;if(clock[1].day>31&&(clock[1].month==1||clock[ 1].month==3||clock[1].month==5||clock[1].m onth==7||clock[1].month==8||clock[1].month ==10||clock[1].month==12)){clock[1].day=clock[1].day-31;clock[1].month=clock[1].month+1;x=1;}if(clock[1].month==2&&clock[1].day>29){clock[1].day=clock[1].day-29;clock[1].month=clock[1].month+1;x=1;}if(clock[1].day>30&&(clock[1].month==4||clock [1].month==6||clock[1].month==9||clock[1].m onth==11)){clock[1].day=clock[1].day-30;clock[1].month=clock[1].month+1;x=1;}}}else{ while(clock[1].day>29&&x==1){x=0;if(clock[1].day>31&&(clock[1].month==1||clock[ 1].month==3||clock[1].month==5||clock[1].m onth==7||clock[1].month==8||clock[1].month ==10||clock[1].month==12)){clock[1].day=clock[1].day-31;clock[1].month=clock[1].month+1;x=1;}if(clock[1].month==2){clock[1].day=clock[1].day-28;clock[1].month=clock[1].month+1;x=1;}else{clock[1].day=clock[1].day-30;clock[1].month=clock[1].month+1;x=1;}}}if(clock[1].month>12){y=clock[1].month/12;clock[1].year=clock[1].year+y;clock[1].month=clock[1].month-y*12;}}}}}}printf("\n 此进程到结束所经历的时间为:\n");disp1();free(p);if(L->next==NULL)disp(L);}if(p->timep==0&&p->time!=0)//如果时间片时间为0,而进程需要服务的时间不为0,//则把该插到队尾,并为该进程分配时间片{L->next=p->next;p->next=NULL;while(q->next)q=q->next;q->next=p;p->timep=5;// p->num++;}disp(L);}}int main(){Pnode L;int count,p,i;L=(Pnode)malloc(sizeof(PCB));L->next=NULL;count=0;printf("\n*----------------------------------------------------------*\n");printf("|**********************中断处理算法模拟********************|\n");printf("*----------------------------------------------------------*\n\n");printf("\n 请置开机时间:\n");printf("\n 年\t月\t日\t时\t分\t秒\t毫秒\n");scanf("%d%d%d%d%d%d%d",&clock[2].year,& clock[2].month,&clock[2].day,&clock[2].hour,&cl ock[2].min,&clock[2].sec,&clock[2].msec);printf("\n 开机时间为\n");chang();disp1(L);while(p!=0){creat(L);printf("\n 进程输入完毕,则输入0,否则输入其它值\n");scanf("%d",&p);}disp(L);for(i=0;i<100;i++){printf("\n 已经执行了一条指令\n");printf("\n 请输入中断的信息\n");scanf("%d",&i);if(i==1){count++;cut(L,count);if(L->next==NULL){printf("\n 打回车退出\n");getch();exit(0);}}if(i==0)printf("\n 没有中断产生\n");}return 0;}八、实验总结通过本次实验明白了中断处理的详细过程,即中断处理程序应首先保护被中断的现行进程的现场,然后处理出现的中断事件,根据处理结果修改被中断进程的状态;最后转向处理器调度,由处理器调度选择可运行的进程,恢复现场使其运行。

相关主题