構建命令行窗口

更詳細的講解和代碼調試演示過程,請參看視頻
Linux kernel Hacker, 從零構建本身的內核微信

操做系統有一個重要的應用,就是命令控制檯,像Linux系統,命令控制檯集合是使用系統的主要工具。本節,咱們將爲系統開發一個命令控制檯,從此咱們會爲系統開發應用程序,而且很多程序將會經過控制檯來運行。markdown

咱們的控制檯程序將依賴於前面完成的進程機制,主進程繪製出控制檯的窗口後,啓動一個專有進程,把窗口提交給進程,讓新進程來負責更新窗口信息已經響應用戶輸入,咱們看看繪製控制檯窗口的代碼,在write_vga_desktop.c中:數據結構

void  launch_console() {
    struct SHEET *sht_cons = sheet_alloc(shtctl);
    unsigned char *buf_cons = (unsigned char *)memman_alloc_4k(memman, 256*165);
    sheet_setbuf(sht_cons, buf_cons, 256, 165, COLOR_INVISIBLE);
    make_window8(shtctl, sht_cons, "console");
    make_textbox8(sht_cons, 8, 28, 240, 128, COL8_000000);

    struct TASK *task_console = task_alloc();
    int addr_code32 = get_code32_addr();
    task_console->tss.ldtr = 0;
    task_console->tss.iomap = 0x40000000;
    task_console->tss.eip =  (int)(console_task - addr_code32);

    task_console->tss.es = 0;
    task_console->tss.cs = 1*8;//6 * 8;
    task_console->tss.ss = 4*8;
    task_console->tss.ds = 3*8;
    task_console->tss.fs = 0;
    task_console->tss.gs = 2*8;
    task_console->tss.esp -= 8;
    *((int*)(task_console->tss.esp + 4)) = (int)sht_cons;
    task_run(task_console, 1, 5);

    sheet_slide(shtctl,sht_cons, 32, 4);
    sheet_updown(shtctl, sht_cons, 1);
}

launch_console 先是申請了內存以及得到SHEET圖層對象,而後經過相關的窗口繪製函數make_window8 和 make_textbox8 將控制檯窗口繪製出來。而後獲取一股進程對象,也就是TASK 數據結構,設置相關信息,並把控制檯的圖層對象設置到新進程的堆棧上,以便進程更新控制檯窗口。app

調用task_run 運行控制檯進程,同時經過sheet_slide 和 sheet_updown將控制檯窗口移動到合適位置。ide

咱們看看進程函數的實現:函數

void console_task(struct SHEET *sheet) {

    struct FIFO8 fifo;
    struct TIMER *timer;
    struct TASK *task = task_now();

    int i, fifobuf[128], cursor_x = 8, cursor_c = COL8_000000;
    fifo8_init(&fifo, 128, fifobuf, task);
    timer = timer_alloc();
    timer_init(timer, &fifo, 1);
    timer_settime(timer, 50);

    for(;;) {

        io_cli();
        if (fifo8_status(&fifo) == 0) {
   //         task_sleep(task);
            io_sti();
        } else {
            i = fifo8_get(&fifo);
            io_sti();
            if (i <= 1) {
                if (i != 0) {
                    timer_init(timer, &fifo, 0);
                    cursor_c = COL8_FFFFFF;
                } else {
                    timer_init(timer, &fifo, 1);
                    cursor_c = COL8_000000;
                }

                timer_settime(timer, 50);
                boxfill8(sheet->buf, sheet->bxsize, cursor_c, cursor_x,
                28, cursor_x + 7, 43);
                sheet_refresh(shtctl, sheet, cursor_x, 28, cursor_x+8, 44);
            }
        }

    }
}

console_task 是新進程運行的主函數,它啓動了一個定時器,這個定時器的做用是在控制檯上繪製光標。在主循環裏,每當定時器超時後,else 部分的代碼會被執行,代碼會根據超時時,隊列中數值的不一樣,選取不一樣的顏色來繪製光標,每次超時時,代碼把光標的顏色轉回成白色或黑色,從而形成一種光標閃爍的特效。工具

上面的代碼編譯後,加載到虛擬機中,效果以下,代碼的深刻講解和系統運行時的動態效果,請參看視頻。ui


本文分享自微信公衆號 - Coding迪斯尼(gh_c9f933e7765d)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。lua

相關文章
相關標籤/搜索