操作系統(tǒng)內(nèi)核開發(fā):利用時鐘中斷實現(xiàn)光標閃爍特效

代碼講解及運行特效請參看視頻:
Linux kernel Hacker, 從零構(gòu)建自己的內(nèi)核

上一節(jié)纹腌,我們已經(jīng)實現(xiàn)了時鐘超時功能褪测,但一個操作系統(tǒng)砌溺,肯定是能支持多個時鐘的,本節(jié)尤勋,我們就看看如何從上一節(jié)的單時鐘向多時鐘轉(zhuǎn)變喘落,同時利用時鐘超時機制實現(xiàn)光標的閃爍特效。

上節(jié)最冰,我們的時鐘控制器對象只對應(yīng)于一個時鐘瘦棋,現(xiàn)在,我們要把有個時鐘的信息抽取出來暖哨,這樣的話赌朋,就使得一個控制器能對應(yīng)管理很多個時鐘對象,因此我們對timer.h 做如下改動:

#define PIT_CTRL   0x0043
#define PIT_CNT0   0x0040

#define MAX_TIMER  500

void init_pit(void);

struct TIMER {
    unsigned int timeout, flags;
    struct FIFO8 *fifo;
    unsigned char data;
};

struct TIMERCTL {
    unsigned int count;
    
    struct TIMER timer[MAX_TIMER];
    
};

struct TIMER* timer_alloc(void);

void timer_free(struct TIMER *timer);

void timer_init(struct TIMER *timer, struct FIFO8 *fifo, unsigned char data) ;

void timer_settime(struct TIMER *timer, unsigned int timeout);

大家看到鹿蜀,原來在TIMERCTL中的一些信息已經(jīng)抽取出來箕慧,獨立成為一個TIMER對象,而在控制器里包含的是一組TIMER數(shù)組茴恰,這樣颠焦,一個控制器就能對應(yīng)很多個時鐘對象了。timer_alloc用來分配一個TIMER對象往枣,一個TIMER對象被分配出來后伐庭,需要用timer_init初始化,然后使用timer_settime設(shè)置時間片分冈。

我們看看相關(guān)函數(shù)的對應(yīng)實現(xiàn)圾另,在timer.c中:

struct TIMER* timer_alloc(void) {
    int i;
    for (i = 0; i < MAX_TIMER; i++) {
        if (timerctl.timer[i].flags == 0) {
            timerctl.timer[i].flags = TIMER_FLAGS_ALLOC;
            return &timerctl.timer[i];
        }
    }

    return 0;
}

void timer_free(struct TIMER *timer) {
    timer->flags = 0;
    return;
}

void timer_init(struct TIMER *timer, struct FIFO8 *fifo, unsigned char data) {
    timer->fifo = fifo;
    timer->data = data;
    return;
}

void timer_settime(struct TIMER *timer, unsigned int timeout) {
    timer->timeout = timeout;
    timer->flags = TIMER_FLAGS_USING;
    return;
}

TIMER對象的分配,其實就是從時鐘控制器的TIMER數(shù)組中找到一個還沒有被使用的對象雕沉,將其它的狀態(tài)從free 轉(zhuǎn)換為alloc, 也就是表明當前時鐘對象已經(jīng)被占用集乔,然后從數(shù)組中直接返回時鐘對象。

timer_settime 就是把時間片信息設(shè)置到對應(yīng)的TIMER對象而已坡椒。需要注意的是intHandlerForTimer函數(shù)的更改:

void intHandlerForTimer(char *esp) {
    io_out8(PIC0_OCW2, 0x60);
    timerctl.count++;

    int i;
    for (i = 0; i < MAX_TIMER; i++) {
        if (timerctl.timer[i].flags == TIMER_FLAGS_USING) {
            timerctl.timer[i].timeout--;
            if (timerctl.timer[i].timeout == 0) {
                timerctl.timer[i].flags = TIMER_FLAGS_ALLOC;
                fifo8_put(timerctl.timer[i].fifo, timerctl.timer[i].data);
            }
        }
    }

    return;
}

每次時鐘中斷發(fā)生是扰路,我們的中斷處理函數(shù)會變量時鐘控制器中的時鐘數(shù)組尤溜,把數(shù)組中時鐘對象的時間片減一,如果有哪個時鐘的時間片已經(jīng)消耗完畢汗唱,那么就往對應(yīng)時鐘的數(shù)據(jù)隊列里寫入一個數(shù)據(jù)宫莱,用于通知內(nèi)核觸發(fā)對應(yīng)的超時操作。

有了多時鐘功能后哩罪,內(nèi)核就可以利用該機制授霸,創(chuàng)建多個時鐘,然后響應(yīng)多個超時事件了际插,內(nèi)核的改動如下碘耳,在write_vga_desktop.c中:

void CMain(void) {
   .....
struct TIMER *timer, *timer2, *timer3;
    static struct FIFO8 timerfifo2, timerfifo3;
    static char timerbuf2[8], timerbuf3[8];

    init_pit();
    fifo8_init(&timerinfo, 8, timerbuf);
    timer = timer_alloc();
    timer_init(timer, &timerinfo, 1);
    timer_settime(timer, 500);

    fifo8_init(&timerfifo2, 8, timerbuf2);
    timer2 = timer_alloc();
    timer_init(timer2, &timerfifo2, 1);
    timer_settime(timer2, 300);

    fifo8_init(&timerfifo3, 8, timerbuf3);
    timer3 = timer_alloc();
    timer_init(timer3, &timerfifo3, 1);
    timer_settime(timer3, 50);
   ....
}

我們看到,內(nèi)核入口函數(shù)申請了三個時鐘對象腹鹉,并將他們初始化藏畅,第一個時鐘的時間片是5秒,第二個時鐘的時間片是3秒功咒,第三個時鐘的時間片是0.5秒愉阎。有了三個時鐘,我們就需要對三個時鐘的超時做不同處理力奋。繼續(xù)看代碼:

void CMain(void) {
   .....

for(;;) {
       char* pStr = intToHexStr(timer->timeout);
       boxfill8(shtMsgBox->buf, 160, COL8_C6C6C6, 40, 28, 119, 43);
       showString(shtctl, shtMsgBox, 40, 28, COL8_000000,pStr);

       io_cli();
       if (fifo8_status(&keyinfo) + fifo8_status(&mouseinfo) +
           fifo8_status(&timerinfo) + fifo8_status(&timerfifo2) 
           + fifo8_status(&timerfifo3) == 0) {
 
           io_sti();
       }
       ....
       else if (fifo8_status(&timerinfo) != 0) {
           io_sti();
           fifo8_get(&timerinfo);
           showString(shtctl, sht_back, 0, 0, COL8_FFFFFF, " new 5[sec]");
       } else if (fifo8_status(&timerfifo2) != 0) {
           fifo8_get(&timerfifo2);
           io_sti();
           showString(shtctl, sht_back, 0, 16, COL8_FFFFFF, "3[sec]");
       }else if (fifo8_status(&timerfifo3) != 0) {
           int i = fifo8_get(&timerfifo3);
           io_sti();
           if (i != 0) {
              timer_init(timer3, &timerfifo3, 0);
              boxfill8(buf_back, xsize, COL8_FFFFFF, 8, 96, 15, 111);
           } else {
              timer_init(timer3, &timerfifo3, 1);
              boxfill8(buf_back, xsize, COL8_008484, 8, 96, 15, 111);
           }

           timer_settime(timer3, 50);
           sheet_refresh(shtctl, sht_back, 8, 96, 16, 112);
       }
   ....   
}

第一個時鐘超時時榜旦,我們還是在桌面左上角顯示一個字符串,第二個時鐘超時時景殷,我們也同樣在左上角顯示一個字符串溅呢,對于第三個時鐘的處理,需要我們注意猿挚,在初始化第三個時鐘是咐旧,我們會傳入一個數(shù)值,也就是上一節(jié)描述的時鐘data, 當超時后绩蜻,這個數(shù)值會被放入回時鐘對應(yīng)的隊列里面铣墨,那么我們可以根據(jù)這個值采取不同的動作去處理超時。

如果第三個時鐘超時了办绝,同時在隊列里面的數(shù)值不等于0伊约,那么我們就在桌面上畫一個白色的小方塊,然后再次初始化該時鐘孕蝉,并把數(shù)值0傳進去屡律,下次時鐘再超時,那么內(nèi)核得到的數(shù)值就是0降淮,于是內(nèi)核把上次繪制的小方塊給擦掉超埋,這樣的話,就形成一個效果,就是一個白色小方塊在桌面上閃來閃去霍殴,就好像一個光標一樣窍蓝。

上面代碼編譯成內(nèi)核運行后,效果如下(動態(tài)效果請參看視頻):

這里寫圖片描述
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末繁成,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子淑玫,更是在濱河造成了極大的恐慌巾腕,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件絮蒿,死亡現(xiàn)場離奇詭異尊搬,居然都是意外死亡,警方通過查閱死者的電腦和手機土涝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進店門佛寿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人但壮,你說我怎么就攤上這事冀泻。” “怎么了蜡饵?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵弹渔,是天一觀的道長。 經(jīng)常有香客問我溯祸,道長肢专,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任焦辅,我火速辦了婚禮博杖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘筷登。我一直安慰自己剃根,他們只是感情好,可當我...
    茶點故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布仆抵。 她就那樣靜靜地躺著跟继,像睡著了一般。 火紅的嫁衣襯著肌膚如雪镣丑。 梳的紋絲不亂的頭發(fā)上舔糖,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天,我揣著相機與錄音莺匠,去河邊找鬼金吗。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的摇庙。 我是一名探鬼主播旱物,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼卫袒!你這毒婦竟也來了宵呛?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤夕凝,失蹤者是張志新(化名)和其女友劉穎宝穗,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體码秉,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡逮矛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了转砖。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片须鼎。...
    茶點故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖府蔗,靈堂內(nèi)的尸體忽然破棺而出晋控,到底是詐尸還是另有隱情,我是刑警寧澤礁竞,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布糖荒,位于F島的核電站,受9級特大地震影響模捂,放射性物質(zhì)發(fā)生泄漏捶朵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一狂男、第九天 我趴在偏房一處隱蔽的房頂上張望综看。 院中可真熱鬧,春花似錦岖食、人聲如沸红碑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽析珊。三九已至,卻和暖如春蔑穴,著一層夾襖步出監(jiān)牢的瞬間忠寻,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工存和, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留奕剃,地道東北人衷旅。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像纵朋,于是被迫代替她去往敵國和親柿顶。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,543評論 2 349

推薦閱讀更多精彩內(nèi)容