10 变得更像真正的操作系统(2)(harib22j)

当然不能就这样放弃,我们来找找失败的原因。在对有可能出问题的地方排查一遍之后,我们发现只要将bootpack.c的第117行keywin_on(key_win);这一句删掉1,重启的毛病就没了。不过这样一来,启动之后光标没有显示出来,必须要按Tab键或者点击窗口将窗口手工切换一下才行。

1 可能有人会问,你是怎样发现这一句有问题的呢?其实笔者寻找bug的基本思路是搞清楚“为什么之前还运行得好好的程序,现在就无法运行了呢”。因此,导致程序无法正常运行的原因肯定在于我们添加的或者删除的那部分代码里,我们可以采取逐个还原的方式来排查。

harib22i的bootpack.c节选

  1. void HariMain(void)
  2. {
  3. (中略)
  4. sheet_slide(sht_back, 0, 0);
  5. sheet_slide(sht_cons[1], 56, 6);
  6. sheet_slide(sht_cons[0], 8, 2);
  7. sheet_slide(sht_mouse, mx, my);
  8. sheet_updown(sht_back, 0);
  9. sheet_updown(sht_cons[1], 1);
  10. sheet_updown(sht_cons[0], 2);
  11. sheet_updown(sht_mouse, 3);
  12. key_win = sht_cons[0];
  13. keywin_on(key_win); ←将这一行删掉的话,重启的毛病就没了
  14. (中略)
  15. }

看来,只要检查一下keywin_on函数就能找到自动重启的原因了。

harib22i的bootpack.c节选

  1. void keywin_on(struct SHEET *key_win)
  2. {
  3. change_wtitle8(key_win, 1);
  4. if ((key_win->flags & 0x20) != 0) {
  5. fifo32_put(&key_win->task->fifo, 2); /*命令行窗口光标ON */
  6. }
  7. return;
  8. }

keywin_on这个函数的功能很简单,先是改变窗口的颜色,然后向命令行窗口任务的FIFO发送2这个值用来显示光标。我们将刚才出问题的keywin_on(key_win);这一句改成change_wtitle8(key_win, 1);试了一下,没有发生重启的问题,看来问题的原因就在fifo32_put这里了。

■■■■■

不过,fifo32_put这个函数我们已经用了很久了,从来没有出过问题,应该不会是程序的bug,因此我们来检查一下发送数据的目的地key_win —> task —> fifo。

这个FIFO缓冲区是否处于正常状态呢?想到这里,我们来找找看对这个FIFO缓冲区进行初始化的代码在哪里,啊,找到了,位于console_task最开头的地方。

这样肯定不行,因为命令行窗口任务的优先级比较低,只有当bootpack.c的HariMain休眠之后才会运行命令行窗口任务,而如果不运行这个任务的话,FIFO缓冲区就不会被初始化,这就相当于我们在向一个还没初始化的FIFO强行发送数据,于是造成fifo32_put混乱而导致重启。

搞清楚原因,改起来就简单了。我们只要将console_task中对FIFO进行初始化的代码移动到HariMain中就可以了。

本次的bootpack.c节选

  1. void HariMain(void)
  2. {
  3. (中略)
  4. int fifobuf[128], keycmd_buf[32], *cons_fifo[2]; /*这里!*/
  5. (中略)
  6. /* sht_cons */
  7. for (i = 0; i < 2; i++) {
  8. (中略)
  9. sht_cons[i]->task = task_cons[i];
  10. sht_cons[i]->flags |= 0x20; /*有光标*/
  11. cons_fifo[i] = (int *) memman_alloc_4k(memman, 128 * 4); /*从此开始*/
  12. fifo32_init(&task_cons[i]->fifo, 128, cons_fifo[i], task_cons[i]); /*到此结束*/
  13. }
  14. (中略)
  15. }

本次的console.c节选

  1. void console_task(struct SHEET *sheet, int memtotal)
  2. {
  3. struct TASK *task = task_now();
  4. struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
  5. int i, *fat = (int *) memman_alloc_4k(memman, 4 * 2880); /*这里!(删掉了fifobuf[128]) */
  6. struct CONSOLE cons;
  7. char cmdline[30];
  8. cons.sht = sheet;
  9. cons.cur_x = 8;
  10. cons.cur_y = 28;
  11. cons.cur_c = -1;
  12. task->cons = &cons;
  13. /*删掉了这里的fifo32_init(&task->fifo, 128, fifobuf, task); */
  14. cons.timer = timer_alloc();
  15. timer_init(cons.timer, &task->fifo, 1);
  16. (中略)
  17. }

虽然我们只修改了5行代码,但是完全可以解决我们的问题,话说,要是还解决不了可真该头大了,因为笔者的上眼皮和下眼皮已经开始打架了(笑)。总之,我们来“make run”试试看吧。

貌似成功了,那个碍事的task_a已经不见了,系统运行也没有问题,太好了。

10 变得更像真正的操作系统(2)(harib22j) - 图1

启动后的画面

好了,我们今天就到这里吧!