[自制简单操作系统] 9、命令行与应用程序 整体回顾

  1. 云栖社区>
  2. 博客>
  3. 正文

[自制简单操作系统] 9、命令行与应用程序 整体回顾

史迪奇2号 2016-06-05 00:44:00 浏览748
展开阅读全文


 

>_<" 下面是整个操作系统的编译框架,这里bootpack是主程序部分,通过调用其他.c文件里的功能函数及必须用汇编写的功能函数(naskfun.nas)来实现操作系统的各项功能,这里统一把他们编译集成到bootpack.bim中,ipl10.asm是引导部分,asmhead.asm是用汇编写的用来实现汇编和C语言的桥梁及一些初始32位编程的设置。此外为了实现命令行读取文件和运行应用程序的功能,这里把2号蓝色的部分文件也加载到操作系统。此外这里1号红色框内展示的是c文件和字库转换成obj的具体过程。

 

>_<" naskfunc.nas主要是C语言有些函数无法实现必须用汇编实现,这里就是那些汇编实现的功能函数:它们包括让CPU休眠的函数,开中断,关中断,IO读写,获取某个特定寄存器或给某个特定寄存器赋值函数以及far jmp功能函数。

naskfunc.nas

>_<" graphic.c主要是调色板、画矩形、显示字符、画主窗口、画鼠标等绘图的底层函数集,供bootpack.c调用实现绘制窗口等功能~

 graphic.c

>_<" dsctbl.c主要负责GDT IDT分段相关。这里我们要定义两个结构体:SEGMENT_DESCRIPTOR 和 GATE_DESCRIPTOR,如下:

复制代码
 1 /* dsctbl.c about GDT IDT that's Global Descriptor Table and Interrupt Descriptor Table*/
 2 struct SEGMENT_DESCRIPTOR {//8 bytes segment infomation,total 8192 parts [here similar to the method of the setting palette] 
 3     short limit_low, base_low;//address of segment base[high:mid:low=1:1:2]=4 bytes =32 bits
 4     char base_mid, access_right;//segment limit[high:low=1:2],only 20 bits = high byte's low 4 bits + low 2bytes' 16bits
 5     char limit_high, base_high;//segment property access[limit_high:right=1:1],only 12 bits = limit_high's high 4 bits + access_right's 8 bits
 6 };
 7 //PS 1):segment limit equals the number of GDT's effective bytes -1 
 8 //PS 2):the segment limit just only has 20 bits, which can represent 1MB, and the segment property has 1 bit flag, 
 9 //if this flag =1,and the limit's unit uses page to replace byte(here 1 page = 4kb) 
10 //PS 3):the segment property has 16 bits liking that:xxxx0000 xxxxxxxx 
11 //the high 4 bits are extended access
12 //the low 8 bits are:
13 //  0x00:unused description table
14 //  0x92:system exclusive,readable and writable,non-executable
15 //  0x9a:system exclusive,readable and non-writable,executable
16 //  0xf2:application useing,readable and writable,non-executable
17 //  0xfa:application useing,readable and non-writable,executable
18 
19 struct GATE_DESCRIPTOR {//
20     short offset_low, selector;
21     char dw_count, access_right;
22     short offset_high;
23 };
复制代码

 dsctbl.c

>_<" int.c文件中是中断初始化函数和int27号中断句柄函数~另外鼠标和键盘的中断句柄放在了他们各自的.c文件中~

 int.c

>_<" fifo.c是存放FIFO结构及相关操作的函数集合,这里FIFO结构是用来存放鼠标、键盘等消息,用来在中断和普通函数之间传递消息~下面是FIFO的结构体及其说明。其功能函数包括初始化、放入、取出、读取FIFO状态等函数。

1 struct FIFO32 {//FIFO缓冲区数据结构
2     int *buf;//缓冲区
3     int p, q, size, free, flags;//下一个数据的写入地址,下一个数据的读出地址,缓冲区的大小,free是缓冲区没有数据的字节数,flag是是否溢出
4         struct TASK *task;//当FIFO中写数据的时候将任务唤醒,用于记录要唤醒任务的信息
5 };


fifo.c

>_<" memory.c是内存管理相关函数集,首先要定义两个结构体:FREEINFO(可用信息结构体),MEMMAN(内存管理结构体)。功能函数中包括内存检测、内存初始化、内存分配、内存释放等相关函数,其中以4K倍数分配和释放内存即找到不小于size的最小4k倍数的内存释放。

复制代码
1 struct FREEINFO {    /* 可用信息 */
2     unsigned int addr, size;
3 };
4 struct MEMMAN {        /* 内存管理 */
5     int frees, maxfrees, lostsize, losts;
6     struct FREEINFO free[MEMMAN_FREES];
7 };
复制代码

 memory.c

>_<" mouse.c文件存放的是和鼠标消息处理相关,首先还是定义一个MOUSE_DEC的结构体,用来存放鼠标消息,如下。其功能函数包括鼠标事件响应句柄函数、鼠标使能函数、鼠标信息解码函数。其中鼠标信息解码是把鼠标发过来的原信息转换为相应的鼠标信息保存在鼠标结构体中。

1 struct MOUSE_DEC {
2     unsigned char buf[3], phase;
3     int x, y, btn;
4 };

 nouse.c
>_<" mtask.c是任务管理相关函数集,首先要声明4个结构体,分别是TSS32结构体,即任务状态段,用来保存任务的相关寄存器等信息,当发生中断时,将相关数据保存在此结构体中,当恢复中断时再将此结构体内的信息加载,从而实现中断前的保存现场和中断后的恢复现场的功能;Task结构体,即任务结构体,上面的TSS32仅仅是任务状态段,一个完整的任务还要包含任务的GDT号、优先级、FIFO缓冲区等信息,所以该任务结构体封装了这些信息用来保存一个任务;TASKLEVEL,是为了实现二维的优先级,所谓的二维优先级是当高优先级的层存在任务时低优先级的层的任务被屏蔽,任务只在高优先级层内进行切换;TASKCTL是任务管理结构体,负责记录所有任务的的信息。其功能函数包括初始化任务、分配任务、添加任务、删除任务、获取任务、切换任务、闲置任务、挂起任务等和任务相关的各种函数。
复制代码
 1 struct TSS32 {//task status segment 任务状态段
 2     int backlink, esp0, ss0, esp1, ss1, esp2, ss2, cr3;//保存的不是寄存器的数据,而是与任务设置相关的信息,在执行任务切换的时候这些成员不会被写入(backlink除外,某些情况下会被写入)
 3     int eip, eflags, eax, ecx, edx, ebx, esp, ebp, esi, edi;//32位寄存器
 4     int es, cs, ss, ds, fs, gs;//16位寄存器
 5     int ldtr, iomap;//有关任务设置部分
 6 };
 7 struct TASK {
 8     int sel, flags; /* sel用来存放GDT的编号 */
 9     int level, priority;
10     struct FIFO32 fifo;//把FIFO绑定到任务里
11     struct TSS32 tss;
12 };
13 struct TASKLEVEL {
14     int running; /* 正在运行的任务量数 */
15     int now; /* 这个变量用来记录当前正在运行的任务是哪一个 */
16     struct TASK *tasks[MAX_TASKS_LV];
17 };
18 struct TASKCTL {
19     int now_lv; /* 正在运行的level */
20     char lv_change; /* 在下次任务切换时是否需要改变LEVEL */
21     struct TASKLEVEL level[MAX_TASKLEVELS];//最多10个level
22     struct TASK tasks0[MAX_TASKS];
23 };
复制代码

 

 
 mtask.c

>_<" sheet.c主要是窗口管理函数集,主要解决多窗口叠加问题,其中涉及刷屏,窗口叠加等,这里的多窗口的管理的数据结构和上面多任务管理的数据结构很像,都是采用链表的思路,这样插入删除都比较快速,加速了处理速度。其中结构体SHEET,即图层结构体,包括图层的大小、位置、高度、设置信息、描述窗口的缓冲区;结构体SHTCTL,即图层管理结构体,包括所有图层信息和当前最上层的图层的标记等信息。功能函数包括初始化图层控制、获取图层、设定图层、刷新图层、设定图层高度、设定图层位置、释放图层等和图层操作相关的函数。

复制代码
 1 struct SHEET {//图层结构体
 2     unsigned char *buf;//所描绘内容的地址
 3     int bxsize, bysize, vx0, vy0, col_inv, height, flags;//图层大小,图层坐标,透明色色号,土层高度,存放有关图层的设定信息
 4     struct SHTCTL *ctl;
 5 };
 6 struct SHTCTL {//图层管理结构体
 7     unsigned char *vram, *map;
 8     int xsize, ysize, top;
 9     struct SHEET *sheets[MAX_SHEETS];
10     struct SHEET sheets0[MAX_SHEETS];
11 };//top存放最上面图层的高度,sheet0图层顺序混乱,要按照升序排列,然后将地址写入sheets中,方便使用
复制代码

 sheet.c

>_<" timer.c是定时器相关函数集,还是和图层和任务的管理方法很类似,首先定义一个计时器个体数据结构TIMER,用来保存一个定时器所需的信息,然后定义一个计时器管理数据结构TIMERCTL,用来整体管理计时器。功能函数包括初始化、分配、释放、设置以及中断处理函数。

复制代码
 1 struct TIMER{
 2     struct TIMER *next;//用来指下一个即将超时的定时器地址
 3     unsigned int flags;//flags记录各个寄存器状态
 4     unsigned int timeout;//用来记录离超时还有多长时间,一旦这个剩余时间为0,程序就往FIFO缓冲区里发送数据,定时器就是用这种方法通知HariMain时间到了
 5     struct FIFO32 *fifo;//消息队列
 6     int data;//该定时器标志,用来向消息队列写的标志信息
 7 };
 8 struct TIMERCTL {
 9     unsigned int count, next;//next是下一个设定时间点,count是累加时间轴
10     struct TIMER *t0;//记录按照某种顺序存好的定时器地址,头指针
11     struct TIMER timers0[MAX_TIMER];
12 };
复制代码

 timer.c

>_<" window.c从名字就能看出来主要负责绘制窗口的函数集。他们分别包括绘制窗口、绘制标题、显示字符串、绘制文本编辑框等函数~

 window.c

>_<" keyboard.c是键盘处理函数集,类似鼠标但是比鼠标的简单些,因为键盘在硬件设计上原来就考虑到了且其信息编码也不像鼠标的那么麻烦。所以,对于键盘处理的相关函数只有初始化、中断处理及附属的一些函数,没了鼠标的复杂的解码函数。同时也不用一个键盘结构体来存放消息,这里只用一个int类型的keydata0保存键盘消息。

 keyboard.c

>_<" file.c是负责读取磁盘映像中的文件读出,如最上面的那副图蓝色2的部分,把3个文件读到操作系统磁盘映像,当操作系统运行时,想把这些内容读出,就要把FAT解压,同时根据文件保存格式解析文件信息,因此这里要定义一个FILEINFO,即文件信息结构体。

复制代码
1 struct FILEINFO {
2     unsigned char name[8], ext[3], type;
3     char reserve[10];
4     unsigned short time, date, clustno;
5     unsigned int size;
6 };//修改MakeFile中的语句,将haribote.sys、ipl10.nas、make.bat这3个文件制成操作系统镜像
7 //这样磁盘映像中0x002600字节以后的部分8(文件名)+3(文件格式)+1(文件属性)+10(留待)+2(时间)+2(日期)+2(簇号)+4(大小)字节
复制代码

 file.c

>_<" console.c是命令行及命令行的黑框相关的函数集合。因为有命令行窗口所以就需要定义一个CONSOLE结构体来保存窗口SHEET和当前的位置及背景颜色。这里命令行窗口是一个新的任务,所以存在console_task用来作为该任务的入口,也就相当于bootpack.c里的main函数,这里的新任务就像一个独立的部分做独立的运行与处理,这一点可以在多任务那部分找到的。而其他的几个函数是负责被该主函数调用实现命令行功能的功能函数。对于命令行命令这里封装成cons_runcmd函数,然后通过调用下面的CMD命令函数,实现cmd命令的功能。这里只有mem、hit、type、dir、cls命令,如果今后想扩展只要在这里写心得cmd命令函数然后在con_runcmd里加入相应的处理即可以了。其中hlt命令是运行独立的程序,如最上面的图中把hlt.asm程序编译并载入磁盘映像,在此处调用读磁盘函数,加载该应用程序并执行,实现了操作系统上运行应用程序的功能。

1 struct CONSOLE {
2     struct SHEET *sht;//console窗口图层
3     int cur_x, cur_y, cur_c;//当前位置和颜色
4 };

 

 console.c

>_<" 相关链接~

上述工程代码链接:http://pan.baidu.com/s/1pJkGdwn

[自制简单操作系统] 1、从0-1到汇编再到c语言的奥秘:http://www.cnblogs.com/zjutlitao/p/3945852.html

[自制简单操作系统] 2、鼠标及键盘中断处理事件[PIC\GDT\IDT\FIFO]:http://www.cnblogs.com/zjutlitao/p/3961048.html

[自制简单操作系统] 3、内存管理和窗口叠加:http://www.cnblogs.com/zjutlitao/p/3979306.html

[自制简单操作系统] 4、计时器(线性表实现优化中断):http://www.cnblogs.com/zjutlitao/p/3983279.html

[自制简单操作系统] 5、杂七杂八(高分辨率和键盘输入):http://www.cnblogs.com/zjutlitao/p/3991839.html

[自制简单操作系统] 6、多任务(一):http://www.cnblogs.com/zjutlitao/p/3993403.html

[自制简单操作系统] 7、多任务(二)——任务管理自动化&任务休眠:http://www.cnblogs.com/zjutlitao/p/3994405.html

[自制简单操作系统] 8、多任务(三)——多窗口与优先级 :http://www.cnblogs.com/zjutlitao/p/3995814.html

 

 



本文转自beautifulzzzz博客园博客,原文链接:http://www.cnblogs.com/zjutlitao/p/4020014.html,如需转载请自行联系原作者

网友评论

登录后评论
0/500
评论
史迪奇2号
+ 关注