3 强制结束应用程序(harib19c)

现在我们的系统已经可以对付大部分恶意破坏和bug,变得越来越优秀了,不过,我们还需要一些别的功能,比如强制结束应用程序。

本次的bug2.c

  1. void HariMain(void)
  2. {
  3. for (;;) { }
  4. }

如果运行这样一个程序,将永远循环下去而无法结束。中断并没有被禁用,因此其他的任务还可以照常工作,不过这个任务总归要消耗一定的CPU运行时间,系统整体的速度就会变慢,还会白白浪费电。如果操作系统没有强制结束应用程序的功能,那么bug2.hrb也可以算是一个不错的恶意破坏程序了。

■■■■■

怎样实现强制结束功能呢?将某一个按键设定为强制结束键,按一下就可以结束程序,这样看起来不错。笔者本来想在console.c的console_task中编写当按下强制结束键时结束应用程序的处理,但是命令行窗口任务在应用程序运行的时候不会去读取FIFO缓冲区,强制结束键也就不管用了,因此我们还是换个方式吧。

于是,我们只好把强制结束处理写在其他的任务中,而bootpack.c看起来很适合。

强制结束键我们就定义为“Shift+F1”吧,当然,用其他的组合键也完全没问题,大家请按照自己的喜好修改吧。

本次的bootpack.c节选

  1. void HariMain(void)
  2. {
  3. (中略)
  4. struct CONSOLE *cons;
  5. (中略)
  6. for (;;) {
  7. (中略)
  8. if (fifo32_status(&fifo) == 0) {
  9. (中略)
  10. } else {
  11. (中略)
  12. if (256 <= i && i <= 511) { /*键盘数据*/
  13. (中略)
  14. if (i == 256 + 0x3b && key_shift != 0 && task_cons->tss.ss0 != 0) { /* Shift+F1 */
  15. cons = (struct CONSOLE *) *((int *) 0x0fec);
  16. cons_putstr0(cons, "\nBreak(key):\n");
  17. io_cli(); /*不能在改变寄存器值时切换到其他任务*/
  18. task_cons->tss.eax = (int) &(task_cons->tss.esp0);
  19. task_cons->tss.eip = (int) asm_end_app;
  20. io_sti();
  21. }
  22. (中略)
  23. } else if (512 <= i && i <= 767) { /*鼠标数据*/
  24. (中略)
  25. } else if (i <= 1) { /*光标用定时器*/
  26. (中略)
  27. }
  28. }
  29. }
  30. }

asm_app_end是将naskfunc.nas中的end_app改名之后得来的函数。

上述程序的工作原理是,当按下强制结束键时,改写命令行窗口任务的的寄存器值,并goto到asm_end_app,仅此而已。

这样一来程序会被强制结束,但也有个问题,那就是当应用程序没有在运行的时候,按下强制结束键会发生误操作。这样可不行,必须要确认task_cons —> tss.ss0不为0时才能继续进行处理。为此,我们还得进行一些修改,使得当应用程序运行时,该值一定不为0;而当应用程序没有运行时,该值一定为0。

本次的naskfunc.nas节选

  1. _asm_end_app:
  2. ; EAXtss.esp0的地址
  3. MOV ESP,[EAX]
  4. MOV DWORD [EAX+4],0 ; 这里!
  5. POPAD
  6. RET ; 返回cmd_app

本次的mtask.c节选

  1. struct TASK *task_alloc(void)
  2. {
  3. int i;
  4. struct TASK *task;
  5. for (i = 0; i < MAX_TASKS; i++) {
  6. if (taskctl->tasks0[i].flags == 0) {
  7. task = &taskctl->tasks0[i];
  8. task->flags = 1; /*正在使用的标志*/
  9. task->tss.eflags = 0x00000202; /* IF = 1; */
  10. task->tss.eax = 0; /*将其置为0*/
  11. (中略)
  12. task->tss.iomap = 0x40000000;
  13. task->tss.ss0 = 0; /*这里!*/
  14. return task;
  15. }
  16. }
  17. return 0; /*已经全部正在使用*/
  18. }

■■■■■

我们来“make run”,结果如下,按下“Shift+F1”就可以轻松结束应用程序了。

3 强制结束应用程序(harib19c) - 图1

顺利结束了

我们再来创建一个bug3.hrb,该程序负责不断显示字符“a”。

本次的bug3.c

  1. void api_putchar(int c);
  2. void api_end(void);
  3. void HariMain(void)
  4. {
  5. for (;;) {
  6. api_putchar('a');
  7. }
  8. }

“make run”的结果如下。按下强制结束键就可以顺利停止了。

3 强制结束应用程序(harib19c) - 图2

停止了的样子

也许在这个阶段就准备强制结束和异常处理还有点为时过早,因为我们还有很多功能想尽快实现。不过早点做好这些基础工作,笔者在后面制作示例程序时就会轻松很多(更容易发现bug),所以我们就把这部分内容放在今天做了。