1 程序整理(harib17a)

大家早上好,今天我们继续努力哦。昨天我们已经实现了应用程序的运行,今天我们来实现由应用程序对操作系统功能的调用(即API,也叫系统调用)。

为什么这样的功能称为“系统调用”(system call)呢?因为它是由应用程序来调用(操作)系统中的功能来完成某种操作,这个名字很直白吧。

“API”这个名字就稍微复杂些,是“application program interface”的缩写,即“应用程序(与系统之间的)接口”的意思。

请大家把这两个名字记住哦,考试题目中会有的哦……开玩笑啦,这些其实用不着记啦。有记这些单词的工夫,还不如多享受一下制作操作系统的乐趣呢。

以后,在本书中会更多地使用“API”这个名字,理由很简单,因为它比较短嘛(笑)!

这值得纪念的第一次,我们就来做个在命令行窗口中显示字符的API吧。BIOS中也有这个功能哦,如果忘了的话请重新看看第二天的内容。怎么样,找到了吧?无论什么样的操作系统,都会有功能类似的API,这可以说是必需的。

■■■■■

下面来改造一下我们操作系统,让它可以使用API吧……等等,现在这程序是怎么回事!尤其是console_task,简直太不像样了。看着如此混乱的程序代码,真是提不起任何干劲来进行改造,我们还是先把程序整理一下吧。

由于只是改变了程序的写法,并没有改变程序处理的内容,因此这里就不讲解了。原本很长的console_task,从249行改到了85行,哦耶!不过由于创建了很多函数,整体的行数反而比原来多了,叹。

本次的console.c节选

  1. struct CONSOLE {
  2. struct SHEET *sht;
  3. int cur_x, cur_y, cur_c;
  4. };
  5. void console_task(struct SHEET *sheet, unsigned int memtotal)
  6. {
  7. struct TIMER *timer;
  8. struct TASK *task = task_now();
  9. struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
  10. int i, fifobuf[128], *fat = (int *) memman_alloc_4k(memman, 4 * 2880);
  11. struct CONSOLE cons;
  12. char cmdline[30];
  13. cons.sht = sheet;
  14. cons.cur_x = 8;
  15. cons.cur_y = 28;
  16. cons.cur_c = -1;
  17. fifo32_init(&task->fifo, 128, fifobuf, task);
  18. timer = timer_alloc();
  19. timer_init(timer, &task->fifo, 1);
  20. timer_settime(timer, 50);
  21. file_readfat(fat, (unsigned char *) (ADR_DISKIMG + 0x000200));
  22. /*显示提示符*/
  23. cons_putchar(&cons, '>', 1);
  24. for (;;) {
  25. io_cli();
  26. if (fifo32_status(&task->fifo) == 0) {
  27. task_sleep(task);
  28. io_sti();
  29. } else {
  30. i = fifo32_get(&task->fifo);
  31. io_sti();
  32. if (i <= 1) { /*光标用定时器*/
  33. if (i != 0) {
  34. timer_init(timer, &task->fifo, 0); /*下次置0 */
  35. if (cons.cur_c >= 0) {
  36. cons.cur_c = COL8_FFFFFF;
  37. }
  38. } else {
  39. timer_init(timer, &task->fifo, 1); /*下次置1 */
  40. if (cons.cur_c >= 0) {
  41. cons.cur_c = COL8_000000;
  42. }
  43. }
  44. timer_settime(timer, 50);
  45. }
  46. if (i == 2) { /*光标ON */
  47. cons.cur_c = COL8_FFFFFF;
  48. }
  49. if (i == 3) { /*光标OFF */
  50. boxfill8(sheet->buf, sheet->bxsize, COL8_000000,
  51. cons.cur_x, cons.cur_y, cons.cur_x + 7, cons.cur_y + 15);
  52. cons.cur_c = -1;
  53. }
  54. if (256 <= i && i <= 511) { /*键盘数据(通过任务A)*/
  55. if (i == 8 + 256) {
  56. /*退格键*/
  57. if (cons.cur_x > 16) {
  58. /*用空格擦除光标后将光标前移一位*/
  59. cons_putchar(&cons, ' ', 0);
  60. cons.cur_x -= 8;
  61. }
  62. } else if (i == 10 + 256) {
  63. /*回车键*/
  64. /*将光标用空格擦除后换行 */
  65. cons_putchar(&cons, ' ', 0);
  66. cmdline[cons.cur_x / 8 - 2] = 0;
  67. cons_newline(&cons);
  68. cons_runcmd(cmdline, &cons, fat, memtotal); /*运行命令*/
  69. /*显示提示符*/
  70. cons_putchar(&cons, '>', 1);
  71. } else {
  72. /*一般字符*/
  73. if (cons.cur_x < 240) {
  74. /*显示一个字符之后将光标后移一位*/
  75. cmdline[cons.cur_x / 8 - 2] = i - 256;
  76. cons_putchar(&cons, i - 256, 1);
  77. }
  78. }
  79. }
  80. /*重新显示光标*/
  81. if (cons.cur_c >= 0) {
  82. boxfill8(sheet->buf, sheet->bxsize, cons.cur_c, cons.cur_x, cons.cur_y,
  83. cons.cur_x + 7, cons.cur_y + 15);
  84. }
  85. sheet_refresh(sheet, cons.cur_x, cons.cur_y, cons.cur_x + 8, cons.cur_y + 16);
  86. }
  87. }
  88. }
  89. void cons_putchar(struct CONSOLE *cons, int chr, char move)
  90. {
  91. char s[2];
  92. s[0] = chr;
  93. s[1] = 0;
  94. if (s[0] == 0x09) { /*制表符*/
  95. for (;;) {
  96. putfonts8_asc_sht(cons->sht, cons->cur_x, cons->cur_y, COL8_FFFFFF, COL8_000000, " ", 1);
  97. cons->cur_x += 8;
  98. if (cons->cur_x == 8 + 240) {
  99. cons_newline(cons);
  100. }
  101. if (((cons->cur_x - 8) & 0x1f) == 0) {
  102. break; /*被32整除则break*/
  103. }
  104. }
  105. } else if (s[0] == 0x0a) { /*换行*/
  106. cons_newline(cons);
  107. } else if (s[0] == 0x0d) { /*回车*/
  108. /*先不做任何操作*/
  109. } else { /*一般字符*/
  110. putfonts8_asc_sht(cons->sht, cons->cur_x, cons->cur_y, COL8_FFFFFF, COL8_000000, s, 1);
  111. if (move != 0) {
  112. /* move为0时光标不后移*/
  113. cons->cur_x += 8;
  114. if (cons->cur_x == 8 + 240) {
  115. cons_newline(cons);
  116. }
  117. }
  118. }
  119. return;
  120. }
  121. void cons_newline(struct CONSOLE *cons)
  122. {
  123. int x, y;
  124. struct SHEET *sheet = cons->sht;
  125. if (cons->cur_y < 28 + 112) {
  126. cons->cur_y += 16; /*到下一行*/
  127. } else {
  128. /*滚动*/
  129. for (y = 28; y < 28 + 112; y++) {
  130. for (x = 8; x < 8 + 240; x++) {
  131. sheet->buf[x + y * sheet->bxsize] = sheet->buf[x + (y + 16) * sheet->bxsize];
  132. }
  133. }
  134. for (y = 28 + 112; y < 28 + 128; y++) {
  135. for (x = 8; x < 8 + 240; x++) {
  136. sheet->buf[x + y * sheet->bxsize] = COL8_000000;
  137. }
  138. }
  139. sheet_refresh(sheet, 8, 28, 8 + 240, 28 + 128);
  140. }
  141. cons->cur_x = 8;
  142. return;
  143. }
  144. void cons_runcmd(char *cmdline, struct CONSOLE *cons, int *fat, unsigned int memtotal)
  145. {
  146. if (strcmp(cmdline, "mem") == 0) {
  147. cmd_mem(cons, memtotal);
  148. } else if (strcmp(cmdline, "cls") == 0) {
  149. cmd_cls(cons);
  150. } else if (strcmp(cmdline, "dir") == 0) {
  151. cmd_dir(cons);
  152. } else if (strncmp(cmdline, "type ", 5) == 0) {
  153. cmd_type(cons, fat, cmdline);
  154. } else if (strcmp(cmdline, "hlt") == 0) {
  155. cmd_hlt(cons, fat);
  156. } else if (cmdline[0] != 0) {
  157. /*不是命令,也不是空行*/
  158. putfonts8_asc_sht(cons->sht, 8, cons->cur_y, COL8_FFFFFF, COL8_000000, "Bad command.", 12);
  159. cons_newline(cons);
  160. cons_newline(cons);
  161. }
  162. return;
  163. }
  164. void cmd_mem(struct CONSOLE *cons, unsigned int memtotal)
  165. {
  166. struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
  167. char s[30];
  168. sprintf(s, "total %dMB", memtotal / (1024 * 1024));
  169. putfonts8_asc_sht(cons->sht, 8, cons->cur_y, COL8_FFFFFF, COL8_000000, s, 30);
  170. cons_newline(cons);
  171. sprintf(s, "free %dKB", memman_total(memman) / 1024);
  172. putfonts8_asc_sht(cons->sht, 8, cons->cur_y, COL8_FFFFFF, COL8_000000, s, 30);
  173. cons_newline(cons);
  174. cons_newline(cons);
  175. return;
  176. }
  177. void cmd_cls(struct CONSOLE *cons)
  178. {
  179. int x, y;
  180. struct SHEET *sheet = cons->sht;
  181. for (y = 28; y < 28 + 128; y++) {
  182. for (x = 8; x < 8 + 240; x++) {
  183. sheet->buf[x + y * sheet->bxsize] = COL8_000000;
  184. }
  185. }
  186. sheet_refresh(sheet, 8, 28, 8 + 240, 28 + 128);
  187. cons->cur_y = 28;
  188. return;
  189. }
  190. void cmd_dir(struct CONSOLE *cons)
  191. {
  192. struct FILEINFO *finfo = (struct FILEINFO *) (ADR_DISKIMG + 0x002600);
  193. int i, j;
  194. char s[30];
  195. for (i = 0; i < 224; i++) {
  196. if (finfo[i].name[0] == 0x00) {
  197. break;
  198. }
  199. if (finfo[i].name[0] != 0xe5) {
  200. if ((finfo[i].type & 0x18) == 0) {
  201. sprintf(s, "filename.ext %7d", finfo[i].size);
  202. for (j = 0; j < 8; j++) {
  203. s[j] = finfo[i].name[j];
  204. }
  205. s[ 9] = finfo[i].ext[0];
  206. s[10] = finfo[i].ext[1];
  207. s[11] = finfo[i].ext[2];
  208. putfonts8_asc_sht(cons->sht, 8, cons->cur_y, COL8_FFFFFF, COL8_000000, s, 30);
  209. cons_newline(cons);
  210. }
  211. }
  212. }
  213. cons_newline(cons);
  214. return;
  215. }
  216. void cmd_type(struct CONSOLE *cons, int *fat, char *cmdline)
  217. {
  218. struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
  219. struct FILEINFO *finfo = file_search(cmdline + 5, (struct FILEINFO *) (ADR_DISKIMG + 0x002600), 224);
  220. char *p;
  221. int i;
  222. if (finfo != 0) {
  223. /*找到文件的情况*/
  224. p = (char *) memman_alloc_4k(memman, finfo->size);
  225. file_loadfile(finfo->clustno, finfo->size, p, fat, (char *) (ADR_DISKIMG + 0x003e00));
  226. for (i = 0; i < finfo->size; i++) {
  227. cons_putchar(cons, p[i], 1);
  228. }
  229. memman_free_4k(memman, (int) p, finfo->size);
  230. } else {
  231. /*没有找到文件的情况*/
  232. putfonts8_asc_sht(cons->sht, 8, cons->cur_y, COL8_FFFFFF, COL8_000000, "File not found.", 15);
  233. cons_newline(cons);
  234. }
  235. cons_newline(cons);
  236. return;
  237. }
  238. void cmd_hlt(struct CONSOLE *cons, int *fat)
  239. {
  240. struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
  241. struct FILEINFO *finfo = file_search("HLT.HRB", (struct FILEINFO *) (ADR_DISKIMG + 0x002600), 224);
  242. struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *) ADR_GDT;
  243. char *p;
  244. if (finfo != 0) {
  245. /*找到文件的情况*/
  246. p = (char *) memman_alloc_4k(memman, finfo->size);
  247. file_loadfile(finfo->clustno, finfo->size, p, fat, (char *) (ADR_DISKIMG + 0x003e00));
  248. set_segmdesc(gdt + 1003, finfo->size - 1, (int) p, AR_CODE32_ER);
  249. farjmp(0, 1003 * 8);
  250. memman_free_4k(memman, (int) p, finfo->size);
  251. } else {
  252. /*没有找到文件的情况*/
  253. putfonts8_asc_sht(cons->sht, 8, cons->cur_y, COL8_FFFFFF, COL8_000000, "File not found.", 15);
  254. cons_newline(cons);
  255. }
  256. cons_newline(cons);
  257. return;
  258. }

本次的file.c节选

  1. struct FILEINFO *file_search(char *name, struct FILEINFO *finfo, int max)
  2. {
  3. int i, j;
  4. char s[12];
  5. for (j = 0; j < 11; j++) {
  6. s[j] = ' ';
  7. }
  8. j = 0;
  9. for (i = 0; name[i] != 0; i++) {
  10. if (j >= 11) { return 0; /*没有找到*/ }
  11. if (name[i] == '.' && j <= 8) {
  12. j = 8;
  13. } else {
  14. s[j] = name[i];
  15. if ('a' <= s[j] && s[j] <= 'z') {
  16. /*将小写字母转换为大写字母*/
  17. s[j] -= 0x20;
  18. }
  19. j++;
  20. }
  21. }
  22. for (i = 0; i < max; ) {
  23. if (finfo[i].name[0] == 0x00) {
  24. break;
  25. }
  26. if ((finfo[i].type & 0x18) == 0) {
  27. for (j = 0; j < 11; j++) {
  28. if (finfo[i].name[j] != s[j]) {
  29. goto next;
  30. }
  31. }
  32. return finfo + i; /*找到文件*/
  33. }
  34. next:
  35. i++;
  36. }
  37. return 0; /*没有找到*/
  38. }

■■■■■

嗯嗯,比之前的代码易读多了。你看,只要想把代码写得清爽些就一定能做到的,连笔者都做到了嘛(笑)。这个例子说明,如果持续增加新的功能,一个函数的代码就会变得很长,像这样定期整理一下还是很有帮助的。

好了,我们来“make run”,输入一些命令试试看。和之前运行的情况一样,很好。