第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运行:
- 在harib13e的bootpack.c的HariMain中将代码:
-
当出现上面的情况的时候,最好的办法就是让CPU执行HLT休息。
-
让HLT成为一个任务,放在最下层的LEVEL中。 这样,即便任务A进入休眠状态,CPU也会切换到这个HLT任务,这样就不会因为找不到任务而出错了。这个HLT任务,美名其曰:闲置任务(idle task)。
- 闲置任务task_idle(mtask.c中):
void task_idle(void) { for (;;) { io_hlt(); } }
- 这个闲置任务其实就是"哨兵"。
- 闲置任务task_idle(mtask.c中):
-
修改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