第17天 命令行窗口
第17天 命令行窗口
2020.4.19
1. 閑置任務(harib14a)
-
在harib13e中,如果任務B0~B2沒有啟動,只有任務A啟動,當任務A進入休眠狀態,程序就會因為找不到其他的任務而導致運行出現異常。
- 在harib13e的bootpack.c的HariMain中將代碼:task_run(task_b[i], 2, i + 1); 注釋掉。
- make后用VMware運行:
-
當出現上面的情況的時候,最好的辦法就是讓CPU執行HLT休息。
-
讓HLT成為一個任務,放在最下層的LEVEL中。 這樣,即便任務A進入休眠狀態,CPU也會切換到這個HLT任務,這樣就不會因為找不到任務而出錯了。這個HLT任務,美名其曰:閑置任務(idle task)。
- 閑置任務task_idle(mtask.c中):void task_idle(void) {for (;;) {io_hlt();} }
- 這個閑置任務其實就是"哨兵"。
-
修改task_init,將閑置任務放到最底層LEVEL即可:
struct TASK *task_init(struct MEMMAN *memman) {int i;struct TASK *task, *idle;……idle = task_alloc();idle->tss.esp = memman_alloc_4k(memman, 64 * 1024) + 64 * 1024;idle->tss.eip = (int) &task_idle;idle->tss.es = 1 * 8;idle->tss.cs = 2 * 8;idle->tss.ss = 1 * 8;idle->tss.ds = 1 * 8;idle->tss.fs = 1 * 8;idle->tss.gs = 1 * 8;task_run(idle, MAX_TASKLEVELS - 1, 1); /*priority=1*/return task; } -
修改HariMain,將代碼task_run(task_b[i], 2, i + 1);注釋掉。然后make并在VMware上運行:
- 沒有出現錯誤,順利運行。
2. 創建命令行窗口(harib14b)
-
命令行窗口不屬于任務A,而是作為一個新的任務獨立存在。將任務B稍加修改就可以創建命令行窗口了。
-
修改HariMain:
void HariMain(void) {……/* sht_cons */sht_cons = sheet_alloc(shtctl);buf_cons = (unsigned char *) memman_alloc_4k(memman, 256 * 165);sheet_setbuf(sht_cons, buf_cons, 256, 165, -1); make_window8(buf_cons, 256, 165, "console", 0);make_textbox8(sht_cons, 8, 28, 240, 128, COL8_000000);task_cons = task_alloc();task_cons->tss.esp = memman_alloc_4k(memman, 64 * 1024) + 64 * 1024 - 8;task_cons->tss.eip = (int) &console_task;task_cons->tss.es = 1 * 8;task_cons->tss.cs = 2 * 8;task_cons->tss.ss = 1 * 8;task_cons->tss.ds = 1 * 8;task_cons->tss.fs = 1 * 8;task_cons->tss.gs = 1 * 8;*((int *) (task_cons->tss.esp + 4)) = (int) sht_cons;task_run(task_cons, 2, 2); /* level=2, priority=2 */……sheet_slide(sht_back, 0, 0);sheet_slide(sht_cons, 32, 4);sheet_slide(sht_win, 64, 56);sheet_slide(sht_mouse, mx, my);sheet_updown(sht_back, 0);sheet_updown(sht_cons, 1);sheet_updown(sht_win, 2);sheet_updown(sht_mouse, 3);…… } -
添加命令行任務console_task:
void console_task(struct SHEET *sheet) {struct FIFO32 fifo;struct TIMER *timer;struct TASK *task = task_now(); /*獲取當前命令行任務*/int i, fifobuf[128], cursor_x = 8, cursor_c = COL8_000000;fifo32_init(&fifo, 128, fifobuf, task);timer = timer_alloc();timer_init(timer, &fifo, 1);timer_settime(timer, 50);for (;;) {io_cli();if (fifo32_status(&fifo) == 0) {task_sleep(task); /*命令行任務休眠*/io_sti();} else {i = fifo32_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(sheet, cursor_x, 28, cursor_x + 8, 44);}}} }- 每一個任務都有一個自己的FIFO緩沖區。
- 命令行任務需要休眠,當執行到console_task時,說明正在CPU上運行的是命令行任務,因此可以通過task_now函數獲取命令行任務本身。
-
make后在VMware上運行:
- 命令行窗口的雛形做好了!
3. 切換輸入窗口(harib14c)
-
harib14b中,無論如何輸入字符,都是在task_a中輸入。現在,需要解決的問題是:向命令行窗口輸入字符。
-
向命令行窗口輸入字符,首先要選中命令行窗口。使用Tab鍵在命令行窗口和任務A之間切換。
-
切換窗口:先暫時將窗口標題欄的顏色改一改。也就是,當按Tab時,命令行窗口和任務A的窗口標題欄的顏色發生變化。(以此來告訴用戶選中了那個窗口)
-
harib14b中的make_window8函數完成了兩個功能:1.描繪窗口標題欄;2.描繪窗口剩余部分。
-
將make_window8函數改寫一下,將描繪標題欄的部分獨立出來形成一個新的函數make_wtitle8。:
void make_window8(unsigned char *buf, int xsize, int ysize, char *title, char act) {boxfill8(buf, xsize, COL8_C6C6C6, 0, 0, xsize - 1, 0 );boxfill8(buf, xsize, COL8_FFFFFF, 1, 1, xsize - 2, 1 );boxfill8(buf, xsize, COL8_C6C6C6, 0, 0, 0, ysize - 1);boxfill8(buf, xsize, COL8_FFFFFF, 1, 1, 1, ysize - 2);boxfill8(buf, xsize, COL8_848484, xsize - 2, 1, xsize - 2, ysize - 2);boxfill8(buf, xsize, COL8_000000, xsize - 1, 0, xsize - 1, ysize - 1);boxfill8(buf, xsize, COL8_C6C6C6, 2, 2, xsize - 3, ysize - 3);boxfill8(buf, xsize, COL8_848484, 1, ysize - 2, xsize - 2, ysize - 2);boxfill8(buf, xsize, COL8_000000, 0, ysize - 1, xsize - 1, ysize - 1);make_wtitle8(buf, xsize, title, act);return; }void make_wtitle8(unsigned char *buf, int xsize, char *title, char act) {static char closebtn[14][16] = {"OOOOOOOOOOOOOOO@","OQQQQQQQQQQQQQ$@","OQQQQQQQQQQQQQ$@","OQQQ@@QQQQ@@QQ$@","OQQQQ@@QQ@@QQQ$@","OQQQQQ@@@@QQQQ$@","OQQQQQQ@@QQQQQ$@","OQQQQQ@@@@QQQQ$@","OQQQQ@@QQ@@QQQ$@","OQQQ@@QQQQ@@QQ$@","OQQQQQQQQQQQQQ$@","OQQQQQQQQQQQQQ$@","O$$$$$$$$$$$$$$@","@@@@@@@@@@@@@@@@"};int x, y;char c, tc, tbc;if (act != 0) {tc = COL8_FFFFFF;tbc = COL8_000084;} else {tc = COL8_C6C6C6;tbc = COL8_848484;}boxfill8(buf, xsize, tbc, 3, 3, xsize - 4, 20);putfonts8_asc(buf, xsize, 24, 4, tc, title);for (y = 0; y < 14; y++) {for (x = 0; x < 16; x++) {c = closebtn[y][x];if (c == '@') {c = COL8_000000;} else if (c == '$') {c = COL8_848484;} else if (c == 'Q') {c = COL8_C6C6C6;} else {c = COL8_FFFFFF;}buf[(5 + y) * xsize + (xsize - 21 + x)] = c;}}return; }- 當act!=0時,字體顏色白色,背景顏色是暗藍。【選中】
- 當act=0時,字體顏色是亮灰,背景顏色是暗灰。【未選中】
-
修改HariMain:
void HariMain(void){……int key_to = 0;……for (;;) {io_cli();if (fifo32_status(&fifo) == 0) {……} else {i = fifo32_get(&fifo);io_sti();if (256 <= i && i <= 511) { /* 鍵盤數據 */……if (i == 256 + 0x0f) { /* Tab鍵 */if (key_to == 0) {key_to = 1;make_wtitle8(buf_win, sht_win->bxsize, "task_a", 0); /*未選中task_a*/make_wtitle8(buf_cons, sht_cons->bxsize, "console", 1); /*選中命令行*/} else {key_to = 0;make_wtitle8(buf_win, sht_win->bxsize, "task_a", 1);make_wtitle8(buf_cons, sht_cons->bxsize, "console", 0);}sheet_refresh(sht_win, 0, 0, sht_win->bxsize, 21); /*刷新圖層*/sheet_refresh(sht_cons, 0, 0, sht_cons->bxsize, 21); /*刷星圖層*/}/* 重新顯示光標 */boxfill8(sht_win->buf, sht_win->bxsize, cursor_c, cursor_x, 28, cursor_x + 7, 43);sheet_refresh(sht_win, cursor_x, 28, cursor_x + 8, 44);} else if (512 <= i && i <= 767) { /* 鼠標數據 */……} else if (i <= 1) { /* 任務A的光標定時器 */……}}} }- key_to,用于記錄鍵盤輸入的key應該輸出到哪里(to)。
- key_to=0:發送到任務A。
- key_to=1: 發送到命令行窗口任務。
- key_to,用于記錄鍵盤輸入的key應該輸出到哪里(to)。
-
make后在VMware運行:
- 接下來的任務就是:根據選中的窗口進行文本輸入。
4. 實現字符輸入(harib14d)
-
實現向命令行窗口輸入字符,只需要在鍵盤按下的時候向console_task的FIFO緩沖區寫入數據即可。
-
鍵盤產生中斷的時候,產生的數據是寫入HariMain的緩沖區的,這是keyboard.c中代碼’寫死’的。因此,想要向命令行窗口寫入數據,在HariMain中需要獲得console_task的緩沖區。
-
沒有哪個任務是不需要使用FIFO緩沖區的,因此,重新定義結構體TASK:
struct TASK {int sel, flags; int level, priority;struct FIFO32 fifo; /*緩沖區*/struct TSS32 tss; };- 因為在FIFO32的定義中就有struct TASK *task;,因此,這樣就把緩沖區和任務綁定起來了。通過任務能夠獲取緩沖區,通過緩沖區能夠獲取任務。struct FIFO32 {int *buf;int p, q, size, free, flags;struct TASK *task; };
- 類似于這樣的結構:
-
修改HariMain:
void HariMain(void) {……for (;;) {io_cli();if (fifo32_status(&fifo) == 0) {task_sleep(task_a);io_sti();} else {i = fifo32_get(&fifo);io_sti();if (256 <= i && i <= 511) { /* 鍵盤數據 */sprintf(s, "%02X", i - 256);putfonts8_asc_sht(sht_back, 0, 16, COL8_FFFFFF, COL8_008484, s, 2);if (i < 0x54 + 256 && keytable[i - 256] != 0) { /* 一般字符,能顯示 */if (key_to == 0) { /* 發送給任務A */if (cursor_x < 128) {/* 顯示一個字符后光標后移1位 */s[0] = keytable[i - 256];s[1] = 0;putfonts8_asc_sht(sht_win, cursor_x, 28, COL8_000000, COL8_FFFFFF, s, 1);cursor_x += 8;}} else { /* 發送給命令行窗口 */fifo32_put(&task_cons->fifo, keytable[i - 256] + 256); /*向命令行窗口的緩沖區寫入數據*/}}if (i == 256 + 0x0e) { /* 退格鍵 */if (key_to == 0) { /* 發送給任務A */if (cursor_x > 8) {putfonts8_asc_sht(sht_win, cursor_x, 28, COL8_000000, COL8_FFFFFF, " ", 1);cursor_x -= 8;}} else { /* 發送給命令行任務 */fifo32_put(&task_cons->fifo, 8 + 256);}}if (i == 256 + 0x0f) { /* Tab */……}……} else if (512 <= i && i <= 767) { /* 鼠標數據 */……} else if (i <= 1) { /* 光標定時器 */……}}} }- 當key_to不等于0時,OS會向命令行窗口發送鍵盤數據,支持一般的字符和退格鍵。由于命令行窗口也使用了定時器,為了不和鍵盤數據沖突,在寫入命令行緩沖區時,將數據加上256。
- 向命令行窗口發送數據的時候,不是直接發送從鍵盤接受到的原始數據,而是發送經過keytable轉化后的值。這樣就可以省略在命令行窗口任務中將按鍵編碼轉化為字符編碼的步驟了。
- 關于退格鍵,我們將它的字符編碼定義為8,在ASCII中,退格鍵就是8。
-
修改console_task:
void console_task(struct SHEET *sheet) {struct TIMER *timer;struct TASK *task = task_now();int i, fifobuf[128], cursor_x = 16, cursor_c = COL8_000000;char s[2];fifo32_init(&task->fifo, 128, fifobuf, task);timer = timer_alloc();timer_init(timer, &task->fifo, 1);timer_settime(timer, 50);/* 顯示提示符 */putfonts8_asc_sht(sheet, 8, 28, COL8_FFFFFF, COL8_000000, ">", 1);for (;;) {io_cli();if (fifo32_status(&task->fifo) == 0) {task_sleep(task);io_sti();} else {i = fifo32_get(&task->fifo);io_sti();if (i <= 1) { /* 光標定時器 */if (i != 0) {timer_init(timer, &task->fifo, 0); cursor_c = COL8_FFFFFF;} else {timer_init(timer, &task->fifo, 1); cursor_c = COL8_000000;}timer_settime(timer, 50);}if (256 <= i && i <= 511) { /*鼠標數據*/if (i == 8 + 256) {/* 退格鍵 */if (cursor_x > 16) {/* 不能刪去提示符 */putfonts8_asc_sht(sheet, cursor_x, 28, COL8_FFFFFF, COL8_000000, " ", 1);cursor_x -= 8;}} else {/* 堦斒一般字符暥帤 */if (cursor_x < 240) {/* 后移光標 */s[0] = i - 256;s[1] = 0;putfonts8_asc_sht(sheet, cursor_x, 28, COL8_FFFFFF, COL8_000000, s, 1);cursor_x += 8;}}}/* 重新繪制光標 */boxfill8(sheet->buf, sheet->bxsize, cursor_c, cursor_x, 28, cursor_x + 7, 43);sheet_refresh(sheet, cursor_x, 28, cursor_x + 8, 44);}} }- 在harib14c的bootpack.c的console_task函數基礎上,將代碼struct FIFO32 fifo;刪除,改成使用&task->fifo。
-
make后用VMware運行:
- 可以輸入英文字母(大寫)、數字和部分符號。無法輸入“!”和“%”等符號。
5. 符號的輸入(harib14e)
-
實現輸入“!”和“%”。
-
首先,要處理Shift鍵:
- 輸入“!”需要按住Shift鍵輸入。
- Shift鍵分為左右Shift,它們的按鍵編碼如下:
按鍵按下抬起 左Shift 0x2a 0xaa 右Shift 0x36 0xb6 - 準備一個key_shift變量:
- 初始值為0,代表左右Shift都沒按下。
- 當左Shift按下,key_shift=1;
- 當右Shift按下,key_shift=2;
- 當兩個都按下,key_shift=3。
- 因此,當key_shift為0時,按照keytable0[]將按鍵編碼轉化成為字符編碼;當key_shift不為0時,按照keytable1[]進行轉換。
-
修改HariMain:
void HariMain(void) {……static char keytable0[0x80] = {0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '^', 0, 0,'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '@', '[', 0, 0, 'A', 'S','D', 'F', 'G', 'H', 'J', 'K', 'L', ';', ':', 0, 0, ']', 'Z', 'X', 'C', 'V','B', 'N', 'M', ',', '.', '/', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, '7', '8', '9', '-', '4', '5', '6', '+', '1','2', '3', '0', '.', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0x5c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x5c, 0, 0};static char keytable1[0x80] = {0, 0, '!', 0x22, '#', '$', '%', '&', 0x27, '(', ')', '~', '=', '~', 0, 0,'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '`', '{', 0, 0, 'A', 'S','D', 'F', 'G', 'H', 'J', 'K', 'L', '+', '*', 0, 0, '}', 'Z', 'X', 'C', 'V','B', 'N', 'M', '<', '>', '?', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, '7', '8', '9', '-', '4', '5', '6', '+', '1','2', '3', '0', '.', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, '_', 0, 0, 0, 0, 0, 0, 0, 0, 0, '|', 0, 0};int key_to = 0, key_shift = 0;……for (;;) {io_cli();if (fifo32_status(&fifo) == 0) {task_sleep(task_a);io_sti();} else {i = fifo32_get(&fifo);io_sti();if (256 <= i && i <= 511) { /* 鍵盤數據 */sprintf(s, "%02X", i - 256);putfonts8_asc_sht(sht_back, 0, 16, COL8_FFFFFF, COL8_008484, s, 2);if (i < 0x80 + 256) { /* 按鍵編碼轉化為字符編碼 */if (key_shift == 0) {s[0] = keytable0[i - 256];} else {s[0] = keytable1[i - 256];}} else { /*無法轉化的按鍵編碼*/s[0] = 0;}if (s[0] != 0) { /* 一般字符 */if (key_to == 0) { /* 發送給任務A */if (cursor_x < 128) {/* 光標后移 */s[1] = 0;putfonts8_asc_sht(sht_win, cursor_x, 28, COL8_000000, COL8_FFFFFF, s, 1);cursor_x += 8;}} else { /* 發送給命令行窗口任務 */fifo32_put(&task_cons->fifo, s[0] + 256);}}if (i == 256 + 0x0e) { /* 退格鍵 */……}if (i == 256 + 0x0f) { /* Tab */……}if (i == 256 + 0x2a) { /* 左Shift ON */key_shift |= 1;}if (i == 256 + 0x36) { /* 右Shift ON */key_shift |= 2;}if (i == 256 + 0xaa) { /* 左Shfit OFF */key_shift &= ~1;}if (i == 256 + 0xb6) { /* 右Shift OFF */key_shift &= ~2;}……} else if (512 <= i && i <= 767) { /* 鼠標數據 */……} else if (i <= 1) { /* 光標定時器 */……}}} }- 考慮到支持\和_的輸入,讓keytable0和keytable1支持到0x80。keytable0中對英文字母和小鍵盤的部分沒有進行改動。
-
make后在VMware上運行:
- 支持輸入“!”等需要使用Shift輸入的符號。下面需要支持小寫。
6. 大寫字母與小寫字母(harib14f)
-
區分大小寫,需要同時判斷Shift鍵的狀態和CapsLock的狀態。
- 關系如下:
CapsLockShift字母 OFF OFF 小寫 OFF ON 大寫 ON OFF 大寫 ON ON 小寫 - 轉化成小寫字母的條件:
- 輸入的字符是英文字母
- (CapsLockON && ShiftOFF) || (CapsLockOFF && ShiftON)
- 我們已經獲取了Shift的狀態。CapsLock的狀態BIOS知道。現在是32位模式,不能訪問BIOS。還好在asmhead.nas中將BIOS的狀態保存了下來。從BIOS獲取的鍵盤狀態就保存在binfo->leds中。
- binfo->leds是char類型,一個字節。數位含義如下:
- 關系如下:
-
修改HariMain:
void HariMain(void) {……int key_to = 0, key_shift = 0, key_leds = (binfo->leds >> 4) & 7; /*只取binfo->leds的4~6位存入key_leds*/……for (;;) {io_cli();if (fifo32_status(&fifo) == 0) {task_sleep(task_a);io_sti();} else {i = fifo32_get(&fifo);io_sti();if (256 <= i && i <= 511) { /* 鍵盤數據 */sprintf(s, "%02X", i - 256);putfonts8_asc_sht(sht_back, 0, 16, COL8_FFFFFF, COL8_008484, s, 2);if (i < 0x80 + 256) { /* 案件編碼轉化成為字符編碼 */if (key_shift == 0) {s[0] = keytable0[i - 256];} else {s[0] = keytable1[i - 256];}} else {s[0] = 0;}if ('A' <= s[0] && s[0] <= 'Z') { /* 英文字母 */if (((key_leds & 4) == 0 && key_shift == 0) ||((key_leds & 4) != 0 && key_shift != 0)) {s[0] += 0x20; /* 轉化成小寫 */}}if (s[0] != 0) { /* 一般字符 */……}……} else if (512 <= i && i <= 767) { /* 鼠標數據 */……} else if (i <= 1) { /* 光標定時器 */……}}} } -
make后在VMware運行:
- 現在能夠根據CapsLock的狀態切換大小寫字母了。我們按下CapsLock,鍵盤上CapsLock的燈沒亮,輸入字符依舊是小寫。
7. 對各種鎖定鍵的支持(harib14g)
-
鍵盤上的鎖定鍵按下時產生的數據:
- 0x3a:CapsLock
- 0x45: NumLock
- 0x46: ScrollLock
-
當HariMain的FIFO緩沖區接收到上述數據,將binfo->leds對應位改寫即可。 這樣就完成了鎖定鍵模式的切換。但是,只這樣做這些鎖定鍵的指示燈并不會亮起,但系統仍是處于CapsLock模式。
-
點亮熄滅鍵盤鎖定鍵指示燈的方法:
-
根據上述方法,修改HariMain:
#define KEYCMD_LED 0xedvoid HariMain(void) {……struct FIFO32 fifo, keycmd;int fifobuf[128], keycmd_buf[32];……int key_to = 0, key_shift = 0, key_leds = (binfo->leds >> 4) & 7, keycmd_wait = -1;……fifo32_init(&keycmd, 32, keycmd_buf, 0);……/* 為了避免和鍵盤當前狀態沖突,在一開始先進行設置 */fifo32_put(&keycmd, KEYCMD_LED);fifo32_put(&keycmd, key_leds);for (;;) {if (fifo32_status(&keycmd) > 0 && keycmd_wait < 0) {/* 如果存在向鍵盤控制器發送的數據,那么發送 */keycmd_wait = fifo32_get(&keycmd); /*獲取數據*/wait_KBC_sendready(); /*等待鍵盤*/io_out8(PORT_KEYDAT, keycmd_wait); /*寫入數據*/}io_cli();if (fifo32_status(&fifo) == 0) {task_sleep(task_a);io_sti();} else {i = fifo32_get(&fifo);io_sti();if (256 <= i && i <= 511) { /* 鍵盤數據 */……if (i == 256 + 0x3a) { /* CapsLock */key_leds ^= 4;fifo32_put(&keycmd, KEYCMD_LED);fifo32_put(&keycmd, key_leds);}if (i == 256 + 0x45) { /* NumLock */key_leds ^= 2;fifo32_put(&keycmd, KEYCMD_LED);fifo32_put(&keycmd, key_leds);}if (i == 256 + 0x46) { /* ScrollLock */key_leds ^= 1;fifo32_put(&keycmd, KEYCMD_LED);fifo32_put(&keycmd, key_leds);}if (i == 256 + 0xfa) { /* 收到鍵盤成功接收到數據的ACK */keycmd_wait = -1;}if (i == 256 + 0xfe) { /* 收到鍵盤失敗接收到數據的ACK */wait_KBC_sendready();io_out8(PORT_KEYDAT, keycmd_wait);}……} else if (512 <= i && i <= 767) { /* 鼠標數據 */……} else if (i <= 1) { /* 光標定時器 */……}}} }- 工作原理:
- 首先,創建了一個叫keycmd的FIFO緩沖區,這個緩沖區不是用來接收中斷產生的數據的,而是用來管理由任務A向鍵盤控制器發送數據的順序的。如果有數據要發送到鍵盤控制器,首先會在keycmd中積累起來。
- keycmd_wait變量。當keycmd_wait=-1時,可以從keycmd緩沖區獲取數據寫入鍵盤控制器。keycmd_wait!=-1時,代表要寫入鍵盤控制器的數據。只有接收到0xfa的ACK,keycmd才能等于-1,才能向鍵盤控制器寫入數據。
- 當接收到0xfe的ACK,重新發送剛才發送失敗的數據。
- 工作原理:
-
make后使用VMware運行,鎖定鍵可以使用,且指示燈能夠亮起。
8. 寫在今天
- 為了不讓自己久坐以致腰痛難耐,我已經琢磨出一個新的預防腰痛的學習方式:站著使用電腦和查閱書籍。
- 現在是2020.4.20 17:31。
- 今天的工作總體上來講不難,就是鎖定鍵那里有點晦澀。
- 今日還沒跑步,待會兒便去。
- 350頁了,真·50%.
- 講一件奇怪的事情:Github上上傳的圖片突然就訪問不了了。嘗試了幾種解決方法:換瀏覽器,chrome, firefox, 360, edge都不行;讓同學用電腦訪問,不行;用自己手機QQ訪問,不行;用手機Chrome訪問不行。用手機自帶瀏覽器訪問,可以;翻墻訪問,可以。這真是太奇怪了!
- 先不管這個奇怪吧。明天繼續加油,沖鴨!
總結
以上是生活随笔為你收集整理的第17天 命令行窗口的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用jQuery用键盘去控制图片移动
- 下一篇: NeHe OpenGL教程 第七课:光照