日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > windows >内容正文

windows

[自制简单操作系统] 4、计时器(线性表实现优化中断)

發(fā)布時(shí)間:2024/4/17 windows 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [自制简单操作系统] 4、计时器(线性表实现优化中断) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

?

?

1、第一版:數(shù)組方式[09d]

>_<" 在bootpack.h里面的timer.c的聲明和結(jié)構(gòu)體:

1 /* timer.c */ 2 #define MAX_TIMER 500 //最多500個(gè)定時(shí)器 3 struct TIMER{ 4 unsigned int flags;//flags記錄各個(gè)寄存器狀態(tài) 5 unsigned int timeout;//用來(lái)記錄離超時(shí)還有多長(zhǎng)時(shí)間,一旦這個(gè)剩余時(shí)間為0,程序就往FIFO緩沖區(qū)里發(fā)送數(shù)據(jù),定時(shí)器就是用這種方法通知HariMain時(shí)間到了 6 struct FIFO8 *fifo;//消息隊(duì)列 7 unsigned char data;//該定時(shí)器標(biāo)志,用來(lái)向消息隊(duì)列寫(xiě)的標(biāo)志信息 8 }; 9 struct TIMERCTL{ 10 unsigned int count;//計(jì)數(shù) 11 struct TIMER timer[MAX_TIMER]; 12 }; 13 extern struct TIMERCTL timerctl; 14 void init_pit(void);//定時(shí)器初始化100hz 15 struct TIMER *timer_alloc(void);//分配定時(shí)器,遍歷所有找到第一個(gè)沒(méi)有使用的分配 16 void timer_free(struct TIMER *timer);//釋放定時(shí)器 17 void timer_init(struct TIMER *timer, struct FIFO8 *fifo, unsigned char data);//初始化定時(shí)器,fifo和標(biāo)志符data 18 void timer_settime(struct TIMER *timer, unsigned int timeout);//定時(shí)器設(shè)置,設(shè)定剩余時(shí)間 19 void inthandler20(int *esp);//定時(shí)器中斷函數(shù) 20 //void settimer(unsigned int timeout, struct FIFO8 *fifo, unsigned char data);//設(shè)置定時(shí)器 1 /* PIT 定時(shí)器 */ 2 3 #include "bootpack.h" 4 5 #define PIT_CTRL 0x0043 6 #define PIT_CNT0 0x0040 7 8 struct TIMERCTL timerctl; 9 //struct TIMERCTL timerctl;//計(jì)數(shù)器結(jié)構(gòu)體實(shí)例化 10 #define TIMER_FLAGS_ALLOC 1 //已配置狀態(tài) 11 #define TIMER_FLAGS_USING 2 //定時(shí)器運(yùn)行中 12 13 / 14 //功能:定時(shí)器初始化,要3次OUT指令,(0x34->0x34)(中斷周期低8位->0x40)(高8位->0x40) 15 //參數(shù): 16 //附加:設(shè)置結(jié)果為主頻/設(shè)置數(shù),這里中斷周期設(shè)置為0x2e9c,大約為100hz,具體搜:IRQ0中斷周期變更PIT 17 void init_pit(void) 18 { 19 int i; 20 io_out8(PIT_CTRL, 0x34); 21 io_out8(PIT_CNT0, 0x9c); 22 io_out8(PIT_CNT0, 0x2e); 23 timerctl.count=0;//初始化計(jì)數(shù)為0 24 // timerctl.timeout=0;//剩余時(shí)間為0 25 for(i=0;i<MAX_TIMER;i++){//初始化所有定時(shí)器未使用 26 timerctl.timer[i].flags=0;//未使用 27 } 28 return; 29 } 30 / 31 //功能:分配定時(shí)器 32 //參數(shù): 33 struct TIMER *timer_alloc(void) 34 { 35 int i; 36 for (i = 0; i < MAX_TIMER; i++) {//從開(kāi)始開(kāi)始找沒(méi)有使用的定時(shí)器,找到后設(shè)置為分配狀態(tài),反回 37 if (timerctl.timer[i].flags == 0) { 38 timerctl.timer[i].flags = TIMER_FLAGS_ALLOC; 39 return &timerctl.timer[i]; 40 } 41 } 42 return 0; /* 沒(méi)有找到 */ 43 } 44 / 45 //功能:釋放定時(shí)器,直接把標(biāo)志位設(shè)為0即可 46 //參數(shù): 47 void timer_free(struct TIMER *timer) 48 { 49 timer->flags = 0; /* 未使用 */ 50 return; 51 } 52 / 53 //功能:初始化定時(shí)器,賦值fifo,設(shè)置標(biāo)志位 54 //參數(shù): 55 void timer_init(struct TIMER *timer, struct FIFO8 *fifo, unsigned char data) 56 { 57 timer->fifo = fifo; 58 timer->data = data; 59 return; 60 } 61 / 62 //功能:設(shè)置timer 63 //參數(shù):輸入剩余時(shí)間 64 void timer_settime(struct TIMER *timer, unsigned int timeout) 65 { 66 timer->timeout = timeout; 67 timer->flags = TIMER_FLAGS_USING; 68 return; 69 } 70 71 72 / 73 //功能:定時(shí)器中斷處理程序,和鍵盤(pán)鼠標(biāo)中斷類似 74 //參數(shù): 75 void inthandler20(int *esp) 76 { 77 int i; 78 io_out8(PIC0_OCW2, 0x60); /* 把IRQ-00信號(hào)接受完了的信息通知給PIC */ 79 timerctl.count++;//計(jì)數(shù) 80 for (i = 0; i < MAX_TIMER; i++) {//遍歷所有的定時(shí)器 81 if (timerctl.timer[i].flags == TIMER_FLAGS_USING) {//有正在使用的就剩余時(shí)間-- 82 timerctl.timer[i].timeout--; 83 if (timerctl.timer[i].timeout == 0) {//剩余時(shí)間為0就直接將標(biāo)志位改為非使用,將消息寫(xiě)進(jìn)隊(duì)列 84 timerctl.timer[i].flags = TIMER_FLAGS_ALLOC; 85 fifo8_put(timerctl.timer[i].fifo, timerctl.timer[i].data);////剩余時(shí)間為0就向緩沖區(qū)寫(xiě)數(shù)據(jù),用這種方法通知main函數(shù) 86 } 87 } 88 } 89 return; 90 } 91 / 92 //功能:定時(shí)器設(shè)置,因?yàn)闆](méi)有設(shè)置好就發(fā)生中斷就會(huì)混亂,所以先關(guān)閉中斷,然后恢復(fù)中斷 93 //參數(shù):初始剩余時(shí)間,fifo,標(biāo)志data(向緩沖區(qū)寫(xiě)的數(shù)據(jù)) 94 //void settimer(unsigned int timeout, struct FIFO8 *fifo, unsigned char data) 95 //{ 96 // int eflags; 97 // eflags = io_load_eflags(); 98 // io_cli(); 99 // timerctl.timeout = timeout; 100 // timerctl.fifo = fifo; 101 // timerctl.data = data; 102 // io_store_eflags(eflags); 103 // return; 104 //} timer.c

>_<" 這里定義一個(gè)計(jì)時(shí)器結(jié)構(gòu)體和一個(gè)管理計(jì)時(shí)器的結(jié)構(gòu)體,其中TIMERCTL中含有一個(gè)timer的數(shù)組,用來(lái)實(shí)現(xiàn)最多MAX_TIMER個(gè)計(jì)時(shí)器的管理。這里:

  • 初始化的時(shí)候只是將所有的定時(shí)器的flags賦值為0

  • 分配定時(shí)器函數(shù)是從開(kāi)始遍歷所有定時(shí)器,一旦有未使用的就置標(biāo)志為TIMER_FLAGS_ALLOC,然后返回~

  • 釋放計(jì)時(shí)器只是簡(jiǎn)單的把標(biāo)志置0,恢復(fù)未使用狀態(tài)

  • 計(jì)時(shí)器初始化函數(shù)是給計(jì)時(shí)器的fifo,和定時(shí)器標(biāo)志賦值,這里的計(jì)時(shí)器標(biāo)志是等計(jì)時(shí)器計(jì)時(shí)完畢時(shí)向fifo發(fā)送的消息,用來(lái)區(qū)分不同的計(jì)時(shí)器

  • 設(shè)置定時(shí)器就是給定時(shí)器設(shè)定一個(gè)時(shí)間,然后置flags為正在使用

  • 中斷處理函數(shù)每次count++實(shí)現(xiàn)時(shí)間累加,然后遍歷所有正在使用的定時(shí)器,讓他們的剩余時(shí)間--,如果發(fā)現(xiàn)剩余時(shí)間為0,就向fifo發(fā)送對(duì)應(yīng)消息~

PS: 很顯然,這種處理速度是很慢很慢的!接下來(lái)要一步步的優(yōu)化~


?

2、有序數(shù)組[09g] ? ? ? ? ?? ?

>_<" 在bootpack.h里面的timer.c的聲明和結(jié)構(gòu)體:

1 /* timer.c */ 2 #define MAX_TIMER 500 //最多500個(gè)定時(shí)器 3 struct TIMER{ 4 unsigned int flags;//flags記錄各個(gè)寄存器狀態(tài) 5 unsigned int timeout;//用來(lái)記錄離超時(shí)還有多長(zhǎng)時(shí)間,一旦這個(gè)剩余時(shí)間為0,程序就往FIFO緩沖區(qū)里發(fā)送數(shù)據(jù),定時(shí)器就是用這種方法通知HariMain時(shí)間到了 6 struct FIFO8 *fifo;//消息隊(duì)列 7 unsigned char data;//該定時(shí)器標(biāo)志,用來(lái)向消息隊(duì)列寫(xiě)的標(biāo)志信息 8 }; 9 struct TIMERCTL { 10 unsigned int count, next, using;//using表示有幾個(gè)定時(shí)器處于活動(dòng)中,next是下一個(gè)設(shè)定時(shí)間點(diǎn),count是累加時(shí)間軸 11 struct TIMER *timers[MAX_TIMER];//記錄按照某種順序存好的定時(shí)器地址 12 struct TIMER timers0[MAX_TIMER]; 13 }; 14 extern struct TIMERCTL timerctl; 15 void init_pit(void);//定時(shí)器初始化100hz 16 struct TIMER *timer_alloc(void);//分配定時(shí)器,遍歷所有找到第一個(gè)沒(méi)有使用的分配 17 void timer_free(struct TIMER *timer);//釋放定時(shí)器 18 void timer_init(struct TIMER *timer, struct FIFO8 *fifo, unsigned char data);//初始化定時(shí)器,fifo和標(biāo)志符data 19 void timer_settime(struct TIMER *timer, unsigned int timeout);//定時(shí)器設(shè)置,設(shè)定剩余時(shí)間 20 void inthandler20(int *esp);//定時(shí)器中斷函數(shù) 21 //void settimer(unsigned int timeout, struct FIFO8 *fifo, unsigned char data);//設(shè)置定時(shí)器 1 /* PIT 定時(shí)器 */ 2 3 #include "bootpack.h" 4 5 #define PIT_CTRL 0x0043 6 #define PIT_CNT0 0x0040 7 8 struct TIMERCTL timerctl; 9 //struct TIMERCTL timerctl;//計(jì)數(shù)器結(jié)構(gòu)體實(shí)例化 10 #define TIMER_FLAGS_ALLOC 1 //已配置狀態(tài) 11 #define TIMER_FLAGS_USING 2 //定時(shí)器運(yùn)行中 12 13 / 14 //功能:定時(shí)器初始化,要3次OUT指令,(0x34->0x34)(中斷周期低8位->0x40)(高8位->0x40) 15 //參數(shù): 16 //附加:設(shè)置結(jié)果為主頻/設(shè)置數(shù),這里中斷周期設(shè)置為0x2e9c,大約為100hz,具體搜:IRQ0中斷周期變更PIT 17 void init_pit(void) 18 { 19 int i; 20 io_out8(PIT_CTRL, 0x34); 21 io_out8(PIT_CNT0, 0x9c); 22 io_out8(PIT_CNT0, 0x2e); 23 timerctl.count=0;//初始化計(jì)數(shù)為0 24 timerctl.next=0xffffffff;//初始時(shí)沒(méi)有計(jì)時(shí)器所以下一個(gè)為無(wú)窮大 25 timerctl.using=0;//正在使用的定時(shí)器為0 26 27 for(i=0;i<MAX_TIMER;i++){//初始化所有定時(shí)器未使用 28 timerctl.timers0[i].flags=0;//未使用 29 } 30 return; 31 } 32 / 33 //功能:分配定時(shí)器 34 //參數(shù): 35 struct TIMER *timer_alloc(void) 36 { 37 int i; 38 for (i = 0; i < MAX_TIMER; i++) {//從開(kāi)始開(kāi)始找沒(méi)有使用的定時(shí)器,找到后設(shè)置為分配狀態(tài),反回 39 if (timerctl.timers0[i].flags == 0) { 40 timerctl.timers0[i].flags = TIMER_FLAGS_ALLOC; 41 return &timerctl.timers0[i]; 42 } 43 } 44 return 0; /* 沒(méi)有找到 */ 45 } 46 / 47 //功能:釋放定時(shí)器,直接把標(biāo)志位設(shè)為0即可 48 //參數(shù): 49 void timer_free(struct TIMER *timer) 50 { 51 timer->flags = 0; /* 未使用 */ 52 return; 53 } 54 / 55 //功能:初始化定時(shí)器,賦值fifo,設(shè)置標(biāo)志位 56 //參數(shù): 57 void timer_init(struct TIMER *timer, struct FIFO8 *fifo, unsigned char data) 58 { 59 timer->fifo = fifo; 60 timer->data = data; 61 return; 62 } 63 / 64 //功能:設(shè)置timer 65 //參數(shù):輸入定時(shí)時(shí)間 66 void timer_settime(struct TIMER *timer, unsigned int timeout) 67 { 68 int e, i, j; 69 timer->timeout = timeout + timerctl.count;//當(dāng)前時(shí)間+定時(shí)器定時(shí)時(shí)間 70 timer->flags = TIMER_FLAGS_USING;//設(shè)置成正在使用 71 e = io_load_eflags();//保存寄存器,關(guān)中斷 72 io_cli(); 73 /* 搜索注冊(cè)位置 */ 74 for (i = 0; i < timerctl.using; i++) {//把所有timeout從小到大排列,找出新建的定時(shí)器插入位置 75 if (timerctl.timers[i]->timeout >= timer->timeout) { 76 break; 77 } 78 } 79 /* i之后的全部后移1位 */ 80 for (j = timerctl.using; j > i; j--) { 81 timerctl.timers[j] = timerctl.timers[j - 1]; 82 } 83 timerctl.using++; 84 /* 插入到空位上 */ 85 timerctl.timers[i] = timer; 86 timerctl.next = timerctl.timers[0]->timeout; 87 io_store_eflags(e);//恢復(fù)寄存器 88 return; 89 } 90 91 92 / 93 //功能:定時(shí)器中斷處理程序,和鍵盤(pán)鼠標(biāo)中斷類似 94 //參數(shù): 95 void inthandler20(int *esp) 96 { 97 int i,j; 98 io_out8(PIC0_OCW2, 0x60); /* 把IRQ-00信號(hào)接受完了的信息通知給PIC */ 99 timerctl.count++;//計(jì)數(shù) 100 if(timerctl.next>timerctl.count){//如果下一個(gè)還沒(méi)計(jì)數(shù)完畢就直接返回 101 return; 102 } 103 for(i=0;i<timerctl.using;i++){ 104 if(timerctl.timers[i]->timeout>timerctl.count){ 105 break; 106 }//從前往后遍歷,一旦發(fā)現(xiàn)有計(jì)時(shí)未完成的計(jì)時(shí)器就跳出循環(huán) 107 /*除了上面的情況,都是定時(shí)已達(dá)的定時(shí)器*/ 108 timerctl.timers[i]->flags = TIMER_FLAGS_ALLOC; 109 fifo8_put(timerctl.timers[i]->fifo, timerctl.timers[i]->data); 110 } 111 /*從上面循環(huán)結(jié)束后,i的值就是前面有幾個(gè)超時(shí)的定時(shí)器*/ 112 timerctl.using-=i;//所以減去超時(shí)的定時(shí)器 113 for(j=0;j<timerctl.using;j++){//將后面的定時(shí)器前移 114 timerctl.timers[j]=timerctl.timers[i+j]; 115 } 116 if(timerctl.using>0){//判斷是否還有正在使用的定時(shí)器,有就用下一個(gè)剩余時(shí)間更新next 117 timerctl.next=timerctl.timers[0]->timeout; 118 }else{//沒(méi)有,就直接設(shè)為無(wú)窮大 119 timerctl.next=0xffffffff; 120 } 121 return; 122 } timer.c

>_<" 這里和上一個(gè)的最大的不同之處是:上一個(gè)采用暴力遍歷每一個(gè)的情況,而這個(gè)則采用插入和刪除等操作時(shí)就事先調(diào)整好數(shù)組。此外為了方便實(shí)現(xiàn)這一數(shù)據(jù)結(jié)構(gòu),TIMERCTL里除了用timers0[]數(shù)組保存計(jì)時(shí)器外,還聲明一個(gè)timers[]數(shù)組用來(lái)記錄按照某種順序排好的定時(shí)器,這里的using是出于活動(dòng)中的定時(shí)器數(shù),next是下一個(gè)設(shè)定的時(shí)間:

  • 初始化函數(shù)改變比較少,只是加了個(gè)using=0,next=0xffffffff等初始化賦值操作

  • 分配定時(shí)器基本無(wú)變化

  • 設(shè)定時(shí)間函數(shù)則從前往后遍歷查找該新的定時(shí)器要插入的位置,因?yàn)檫@里是有序排列的,而且只遍歷正在使用中的定時(shí)器,所以比上一個(gè)純暴力要快

  • 中斷函數(shù),是將當(dāng)前前面的已經(jīng)超時(shí)的定時(shí)器發(fā)送消息及取消使用狀態(tài),然后從有序列表里面刪除這些(具體做法就是前移后面的部分覆蓋這部分超時(shí)的部分)


?

3、線性表[10h] ? ? ? ? ? ? ? ? ??

>_<" 在bootpack.h里面的timer.c的聲明和結(jié)構(gòu)體:

1 /* timer.c */ 2 #define MAX_TIMER 500 //最多500個(gè)定時(shí)器 3 struct TIMER{ 4 struct TIMER *next;//用來(lái)指下一個(gè)即將超時(shí)的定時(shí)器地址 5 unsigned int flags;//flags記錄各個(gè)寄存器狀態(tài) 6 unsigned int timeout;//用來(lái)記錄離超時(shí)還有多長(zhǎng)時(shí)間,一旦這個(gè)剩余時(shí)間為0,程序就往FIFO緩沖區(qū)里發(fā)送數(shù)據(jù),定時(shí)器就是用這種方法通知HariMain時(shí)間到了 7 struct FIFO32 *fifo;//消息隊(duì)列 8 int data;//該定時(shí)器標(biāo)志,用來(lái)向消息隊(duì)列寫(xiě)的標(biāo)志信息 9 }; 10 struct TIMERCTL { 11 unsigned int count, next, using;//using表示有幾個(gè)定時(shí)器處于活動(dòng)中,next是下一個(gè)設(shè)定時(shí)間點(diǎn),count是累加時(shí)間軸 12 struct TIMER *t0;//記錄按照某種順序存好的定時(shí)器地址,頭指針 13 struct TIMER timers0[MAX_TIMER]; 14 }; 15 extern struct TIMERCTL timerctl; 16 void init_pit(void);//定時(shí)器初始化100hz 17 struct TIMER *timer_alloc(void);//分配定時(shí)器,遍歷所有找到第一個(gè)沒(méi)有使用的分配 18 void timer_free(struct TIMER *timer);//釋放定時(shí)器 19 void timer_init(struct TIMER *timer, struct FIFO32 *fifo, int data);//初始化定時(shí)器,fifo和標(biāo)志符data 20 void timer_settime(struct TIMER *timer, unsigned int timeout);//定時(shí)器設(shè)置,設(shè)定剩余時(shí)間 21 void inthandler20(int *esp);//定時(shí)器中斷函數(shù) 1 /* PIT 定時(shí)器 */ 2 3 #include "bootpack.h" 4 5 #define PIT_CTRL 0x0043 6 #define PIT_CNT0 0x0040 7 8 struct TIMERCTL timerctl; 9 //struct TIMERCTL timerctl;//計(jì)數(shù)器結(jié)構(gòu)體實(shí)例化 10 #define TIMER_FLAGS_ALLOC 1 //已配置狀態(tài) 11 #define TIMER_FLAGS_USING 2 //定時(shí)器運(yùn)行中 12 13 / 14 //功能:定時(shí)器初始化,要3次OUT指令,(0x34->0x34)(中斷周期低8位->0x40)(高8位->0x40) 15 //參數(shù): 16 //附加:設(shè)置結(jié)果為主頻/設(shè)置數(shù),這里中斷周期設(shè)置為0x2e9c,大約為100hz,具體搜:IRQ0中斷周期變更PIT 17 void init_pit(void) 18 { 19 int i; 20 io_out8(PIT_CTRL, 0x34); 21 io_out8(PIT_CNT0, 0x9c); 22 io_out8(PIT_CNT0, 0x2e); 23 timerctl.count=0;//初始化計(jì)數(shù)為0 24 timerctl.next=0xffffffff;//初始時(shí)沒(méi)有計(jì)時(shí)器所以下一個(gè)為無(wú)窮大 25 timerctl.using=0;//正在使用的定時(shí)器為0 26 27 for(i=0;i<MAX_TIMER;i++){//初始化所有定時(shí)器未使用 28 timerctl.timers0[i].flags=0;//未使用 29 } 30 return; 31 } 32 / 33 //功能:分配定時(shí)器 34 //參數(shù): 35 struct TIMER *timer_alloc(void) 36 { 37 int i; 38 for (i = 0; i < MAX_TIMER; i++) {//從開(kāi)始開(kāi)始找沒(méi)有使用的定時(shí)器,找到后設(shè)置為分配狀態(tài),反回 39 if (timerctl.timers0[i].flags == 0) { 40 timerctl.timers0[i].flags = TIMER_FLAGS_ALLOC; 41 return &timerctl.timers0[i]; 42 } 43 } 44 return 0; /* 沒(méi)有找到 */ 45 } 46 / 47 //功能:釋放定時(shí)器,直接把標(biāo)志位設(shè)為0即可 48 //參數(shù): 49 void timer_free(struct TIMER *timer) 50 { 51 timer->flags = 0; /* 未使用 */ 52 return; 53 } 54 / 55 //功能:初始化定時(shí)器,賦值fifo,設(shè)置標(biāo)志位 56 //參數(shù): 57 void timer_init(struct TIMER *timer, struct FIFO32 *fifo, int data) 58 { 59 timer->fifo = fifo; 60 timer->data = data; 61 return; 62 } 63 / 64 //功能:設(shè)置timer 65 //參數(shù):輸入定時(shí)時(shí)間 66 void timer_settime(struct TIMER *timer, unsigned int timeout) 67 { 68 int e; 69 struct TIMER *t,*s; 70 timer->timeout = timeout + timerctl.count;//當(dāng)前時(shí)間+定時(shí)器定時(shí)時(shí)間 71 timer->flags = TIMER_FLAGS_USING;//設(shè)置成正在使用 72 e = io_load_eflags();//保存寄存器,關(guān)中斷 73 io_cli(); 74 75 timerctl.using++; 76 if (timerctl.using == 1) { 77 /* 處于運(yùn)行狀態(tài)的只有一個(gè) */ 78 timerctl.t0 = timer; 79 timer->next = 0; /* 沒(méi)有下一個(gè) */ 80 timerctl.next = timer->timeout; 81 io_store_eflags(e); 82 return; 83 } 84 t = timerctl.t0; 85 if (timer->timeout <= t->timeout) { 86 /* 插入最前面 */ 87 timerctl.t0 = timer; 88 timer->next = t; /* 下面是t */ 89 timerctl.next = timer->timeout; 90 io_store_eflags(e); 91 return; 92 } 93 /* 搜尋插入位置 */ 94 for (;;) { 95 s = t; 96 t = t->next; 97 if (t == 0) { 98 break; /* 最后面 */ 99 } 100 if (timer->timeout <= t->timeout) { 101 /* 插入到s和t之間 */ 102 s->next = timer; /* s的先一個(gè)是timer */ 103 timer->next = t; /* timer的下一個(gè)是t */ 104 io_store_eflags(e); 105 return; 106 } 107 } 108 /* 插入最后面的情況 */ 109 s->next = timer; 110 timer->next = 0; 111 io_store_eflags(e); 112 return; 113 } 114 115 / 116 //功能:定時(shí)器中斷處理程序,和鍵盤(pán)鼠標(biāo)中斷類似 117 //參數(shù): 118 void inthandler20(int *esp) 119 { 120 int i,j; 121 struct TIMER *timer; 122 io_out8(PIC0_OCW2, 0x60); /* 把IRQ-00信號(hào)接受完了的信息通知給PIC */ 123 timerctl.count++;//計(jì)數(shù) 124 if(timerctl.next>timerctl.count){//如果下一個(gè)還沒(méi)計(jì)數(shù)完畢就直接返回 125 return; 126 } 127 timer=timerctl.t0;//把最前面的地址賦址給timer 128 for(i=0;i<timerctl.using;i++){ 129 if(timer->timeout>timerctl.count){ 130 break; 131 }//從前往后遍歷,一旦發(fā)現(xiàn)有計(jì)時(shí)未完成的計(jì)時(shí)器就跳出循環(huán) 132 /*除了上面的情況,都是定時(shí)已達(dá)的定時(shí)器*/ 133 timer->flags = TIMER_FLAGS_ALLOC; 134 fifo32_put(timer->fifo, timer->data); 135 timer=timer->next;//下一個(gè)定時(shí)器的地址賦址給timer 136 } 137 /*從上面循環(huán)結(jié)束后,i的值就是前面有幾個(gè)超時(shí)的定時(shí)器*/ 138 timerctl.using-=i;//所以減去超時(shí)的定時(shí)器 139 timerctl.t0=timer;//新移位 140 //timectl.next設(shè)定 141 if(timerctl.using>0){//判斷是否還有正在使用的定時(shí)器,有就用下一個(gè)剩余時(shí)間更新next 142 timerctl.next=timerctl.t0->timeout; 143 }else{//沒(méi)有,就直接設(shè)為無(wú)窮大 144 timerctl.next=0xffffffff; 145 } 146 return; 147 } timer.c

>_<" 通過(guò)上面2個(gè)優(yōu)化的實(shí)例發(fā)現(xiàn),用數(shù)組避免不了大量數(shù)據(jù)的前移和后移,于是我們就想到了用指針來(lái)構(gòu)成線性表,這樣交換插入都可以在幾步之能完成!這里在結(jié)構(gòu)體TIMER里加入了*next指針,用來(lái)存放下一個(gè)即將超時(shí)的定時(shí)器地址。

  • 這里中斷處理函數(shù)只是把上面數(shù)組實(shí)現(xiàn)的有序數(shù)組改成用指針實(shí)現(xiàn)的有序鏈表,這樣交換和插入數(shù)據(jù)就不用一塊一塊的移位了,直接切換一下指針就能夠完成了,所以能夠優(yōu)化中斷處理能力!

  • 這里的settimer函數(shù)也類似,這里不做詳細(xì)介紹,直接看代碼就能理解啦!

PS: 在使用線性表之后發(fā)現(xiàn)TIMERCTR結(jié)構(gòu)體里的TIMER數(shù)組可以只要一個(gè)首地址就行了,于是也簡(jiǎn)化為*t0


?

4、使用“哨兵”簡(jiǎn)化程序[10i]

>_<" 在bootpack.h里面的timer.c的聲明和結(jié)構(gòu)體:

1 /* timer.c */ 2 #define MAX_TIMER 500 //最多500個(gè)定時(shí)器 3 struct TIMER{ 4 struct TIMER *next;//用來(lái)指下一個(gè)即將超時(shí)的定時(shí)器地址 5 unsigned int flags;//flags記錄各個(gè)寄存器狀態(tài) 6 unsigned int timeout;//用來(lái)記錄離超時(shí)還有多長(zhǎng)時(shí)間,一旦這個(gè)剩余時(shí)間為0,程序就往FIFO緩沖區(qū)里發(fā)送數(shù)據(jù),定時(shí)器就是用這種方法通知HariMain時(shí)間到了 7 struct FIFO32 *fifo;//消息隊(duì)列 8 int data;//該定時(shí)器標(biāo)志,用來(lái)向消息隊(duì)列寫(xiě)的標(biāo)志信息 9 }; 10 struct TIMERCTL { 11 unsigned int count, next;//next是下一個(gè)設(shè)定時(shí)間點(diǎn),count是累加時(shí)間軸 12 struct TIMER *t0;//記錄按照某種順序存好的定時(shí)器地址,頭指針 13 struct TIMER timers0[MAX_TIMER]; 14 }; 15 extern struct TIMERCTL timerctl; 16 void init_pit(void);//定時(shí)器初始化100hz 17 struct TIMER *timer_alloc(void);//分配定時(shí)器,遍歷所有找到第一個(gè)沒(méi)有使用的分配 18 void timer_free(struct TIMER *timer);//釋放定時(shí)器 19 void timer_init(struct TIMER *timer, struct FIFO32 *fifo, int data);//初始化定時(shí)器,fifo和標(biāo)志符data 20 void timer_settime(struct TIMER *timer, unsigned int timeout);//定時(shí)器設(shè)置,設(shè)定剩余時(shí)間 21 void inthandler20(int *esp);//定時(shí)器中斷函數(shù) 1 /* PIT 定時(shí)器 */ 2 3 #include "bootpack.h" 4 5 #define PIT_CTRL 0x0043 6 #define PIT_CNT0 0x0040 7 8 struct TIMERCTL timerctl; 9 //struct TIMERCTL timerctl;//計(jì)數(shù)器結(jié)構(gòu)體實(shí)例化 10 #define TIMER_FLAGS_ALLOC 1 //已配置狀態(tài) 11 #define TIMER_FLAGS_USING 2 //定時(shí)器運(yùn)行中 12 13 / 14 //功能:定時(shí)器初始化,要3次OUT指令,(0x34->0x34)(中斷周期低8位->0x40)(高8位->0x40) 15 //參數(shù): 16 //附加:設(shè)置結(jié)果為主頻/設(shè)置數(shù),這里中斷周期設(shè)置為0x2e9c,大約為100hz,具體搜:IRQ0中斷周期變更PIT 17 void init_pit(void) 18 { 19 int i; 20 struct TIMER *t; 21 io_out8(PIT_CTRL, 0x34); 22 io_out8(PIT_CNT0, 0x9c); 23 io_out8(PIT_CNT0, 0x2e); 24 timerctl.count=0;//初始化計(jì)數(shù)為0 25 for(i=0;i<MAX_TIMER;i++){//初始化所有定時(shí)器未使用 26 timerctl.timers0[i].flags=0;//未使用 27 } 28 t=timer_alloc();//取得一個(gè) 29 t->timeout=0xffffffff; 30 t->flags=TIMER_FLAGS_USING; 31 t->next=0;//末尾 32 timerctl.t0=t;//現(xiàn)在就一個(gè) 33 timerctl.next=0xffffffff;//下一個(gè)計(jì)時(shí)器為哨兵,所以下一個(gè)為無(wú)窮大 34 return; 35 } 36 / 37 //功能:分配定時(shí)器 38 //參數(shù): 39 struct TIMER *timer_alloc(void) 40 { 41 int i; 42 for (i = 0; i < MAX_TIMER; i++) {//從開(kāi)始開(kāi)始找沒(méi)有使用的定時(shí)器,找到后設(shè)置為分配狀態(tài),反回 43 if (timerctl.timers0[i].flags == 0) { 44 timerctl.timers0[i].flags = TIMER_FLAGS_ALLOC; 45 return &timerctl.timers0[i]; 46 } 47 } 48 return 0; /* 沒(méi)有找到 */ 49 } 50 / 51 //功能:釋放定時(shí)器,直接把標(biāo)志位設(shè)為0即可 52 //參數(shù): 53 void timer_free(struct TIMER *timer) 54 { 55 timer->flags = 0; /* 未使用 */ 56 return; 57 } 58 / 59 //功能:初始化定時(shí)器,賦值fifo,設(shè)置標(biāo)志位 60 //參數(shù): 61 void timer_init(struct TIMER *timer, struct FIFO32 *fifo, int data) 62 { 63 timer->fifo = fifo; 64 timer->data = data; 65 return; 66 } 67 / 68 //功能:設(shè)置timer 69 //參數(shù):輸入定時(shí)時(shí)間 70 void timer_settime(struct TIMER *timer, unsigned int timeout) 71 { 72 int e; 73 struct TIMER *t,*s; 74 timer->timeout = timeout + timerctl.count;//當(dāng)前時(shí)間+定時(shí)器定時(shí)時(shí)間 75 timer->flags = TIMER_FLAGS_USING;//設(shè)置成正在使用 76 e = io_load_eflags();//保存寄存器,關(guān)中斷 77 io_cli(); 78 79 t=timerctl.t0; 80 if (timer->timeout <= t->timeout) { 81 /* 插入最前面的情況 */ 82 timerctl.t0 = timer; 83 timer->next = t; /* 下面是設(shè)定t */ 84 timerctl.next = timer->timeout; 85 io_store_eflags(e); 86 return; 87 } 88 /* 搜尋插入位置 */ 89 for (;;) { 90 s = t; 91 t = t->next; 92 if (timer->timeout <= t->timeout) { 93 /* 插入s和t之間 */ 94 s->next = timer; /* s下一個(gè)是timer */ 95 timer->next = t; /* timer下一個(gè)是t */ 96 io_store_eflags(e); 97 return; 98 } 99 } 100 return; 101 } 102 103 / 104 //功能:定時(shí)器中斷處理程序,和鍵盤(pán)鼠標(biāo)中斷類似 105 //參數(shù): 106 void inthandler20(int *esp) 107 { 108 struct TIMER *timer; 109 io_out8(PIC0_OCW2, 0x60); /* 把IRQ-00信號(hào)接受完了的信息通知給PIC */ 110 timerctl.count++; 111 if (timerctl.next > timerctl.count) {//如果下一個(gè)還沒(méi)計(jì)數(shù)完畢就直接返回 112 return; 113 } 114 timer = timerctl.t0; //把最前面的地址賦址給timer 115 for (;;) { 116 if (timer->timeout > timerctl.count) { 117 break; 118 }//從前往后遍歷,一旦發(fā)現(xiàn)有計(jì)時(shí)未完成的計(jì)時(shí)器就跳出循環(huán) 119 /*除了上面的情況,都是定時(shí)已達(dá)的定時(shí)器*/ 120 timer->flags = TIMER_FLAGS_ALLOC; 121 fifo32_put(timer->fifo, timer->data); 122 timer = timer->next;//下一個(gè)定時(shí)器的地址賦址給timer 123 } 124 timerctl.t0 = timer;//新移位 125 timerctl.next = timer->timeout;//timectl.next設(shè)定 126 return; 127 } timer.c

>_<" “哨兵”聽(tīng)起來(lái)高大上,其實(shí)就是在10g的線性表的基礎(chǔ)上多加一個(gè)空結(jié)點(diǎn),這樣就能把插入結(jié)點(diǎn)時(shí)的判斷條件減少很多,用來(lái)達(dá)到精簡(jiǎn)代碼的目的~其實(shí)由于多了一個(gè)空結(jié)點(diǎn),這種處理雖然代碼精簡(jiǎn)了,但是其速度就沒(méi)有上面純的線性表快了~這里就不仔細(xì)介紹細(xì)節(jié)的東西了,相信大家一看就懂~


?

5、工程代碼鏈接: ? ? ? ?

包含上面項(xiàng)目工程的所有代碼:http://pan.baidu.com/s/1bnEkjWN

LZ主頁(yè):http://www.cnblogs.com/zjutlitao/

1 /* 2 同一占用一個(gè)fifo,這里: 3 0~1 光標(biāo)閃爍用定時(shí)器 4 3 3秒定時(shí)器 5 10 10秒定時(shí)器 6 256~511 鍵盤(pán)輸入(從鍵盤(pán)控制器讀入的值再加上256) 7 512~767 鼠標(biāo)輸入(從鍵盤(pán)控制器讀入的值再加上512) 8 */

?

轉(zhuǎn)載于:https://www.cnblogs.com/zjutlitao/p/3983279.html

總結(jié)

以上是生活随笔為你收集整理的[自制简单操作系统] 4、计时器(线性表实现优化中断)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。