GeekOS project0

 

GeekOS project0

  • 话说

记得自己前几天做 GeekOS 的实验时,总以为没有什么,看什么都是粗粗一逛。虽然开始很顺利,但上天总是不会让我养成如此的习惯的,

扔了一个砖头给我,搞的我好几天头蒙蒙的。后来才知道,自己只是因为少看了一行“最没必要”看的。后悔莫及,害我苦苦想了 N 天只有“天才”(分析 Linux 内核)才会去思考的问题。结果只花了吃饭的时间就搞定了那个问题。


GeekOS project0 说白了就是先让你练练手,以免对它产生畏惧。所以在作这个实验的过程中,有再大的困难也要忍住,坚持一下,未来海阔天空。

  • 简述

GeekOS project0 是让自己实现一个类似于 Dos Linux 字符界面的效果,当然,功能只有简单的输入输出。


我们着重说“输入输出”,因为我们是在说它吗!哈哈!开始喽!


输入设备:键盘,标准输入端

输出设备:屏幕,标准输出端

所以,我们要用到的源文件是: keyboard.c screen.c 。当然少不了 main.c


先凭自己的想像,想像以下输入输出的过程:

1 、在开机,并且电脑上操作系统可以至少实现键盘输入字符和屏幕输出字符的前提下!!;

2 、按键;

3 、按键产生的电流解析为二进制串(应该至少有 8 位,一个字节,字符就占一个字节),二进制串通过查键盘扫描码表(先记住有这个东西就成了,不要计较,就是这样定的),找到对应的字符。

但是我们的键盘上还有其他伟大的键呢! Shift Ctrl Alt Caps Lock Del Ins Esc Home PgUp…… 他们呢?再说键 1 还有!的附加功能呢?我们把他们归类吧。有附加功能的一般是通过 Shift Fn (目前不会用到,我也不会啊,哈哈), CapsLock 键是个特例,其他键我还没研究,不过 Del Ins Del 键是一个不错的对象。因此我们可以再扩展以下二进制串的位数,把上面的键也加进去,当作标示位,后面的自然就是字符位了,所以二进制串应该为 16 位,也就是两个字节。

4 、将字符放入“某个地方”, GeekOS 中是缓冲区(队列或栈)。

5 、将字符从“某个地方”取出,输出到屏幕上。

以上只是把按键输出到屏幕上,没有 Del Ins 之类的操作。若要实现 Del Ins ,则要用到源文件 screen.c


上面就是输入输出的简单过程。其实在 project0 中,我们的任务只是把“某个地方”的字符输出到屏幕上,并且已经提供了所有的函数,我们只是简单的把函数组装以下罢了。但了解更多也不错!哈哈!


  • 实现

在头文件 keyboard.h 中,定义了我们将会用到的一切(除非你认为你有必要了解或领悟或扩展其他的功能,否则你可以忽略它的存在):

· 定义键盘的 I/O 端口(状态和数据);

……

· 定义“释放按键”(当我们按键的时候会触发两个事件——按下和释放(弹起)事件,我们一般只接收按下事件(习惯问题));

· 定义标示位(就是上面所说的 Shift 之类的特殊按键,还有功能键,还有按键是否释放);

· 对每一个特殊按键以及功能键的定义;

……

· 定义函数头;

在源文件 keyboard.c 中,定义了两个数组,分别是按下或未按下 Shift 键时,二进制串与字符的对应关系,一看就会明白的。还有一些其他的:

· 字符队列(用来存储从键盘输入的字符),还有对队列处理的一些函数,如判断对空或堆满,入队出队;

· 处理键盘终端的函数(中断的概念百度就可以了,理解最好)——理解这个函数不是很困难哦,现在只要知道它将按键字符插入了字符队列就可以了;

· 初始化函数(不去管它,只要知道它的功能就可以了);

· 函数 bool Read_Key(Keycode* keycode) 和函数 Keycode Wait_For_Key(void) 的功能是相仿的,它们是我们将要用到的函数。功能是在“字符队列”中读取一个字符,就是出队操作。我们要做的就是把出队的字符打印到屏幕,用 Print 函数就可以实现。


main.c 函数中,开始是几个初始化函数,下面是打印函数 Print 。函数 TODO 是一个死循环,所以要注释掉。我们要做的就是实现一个函数,从 Wait_For_Key Read_Key 获取字符,用 Print 输出按键是“按下状态”(未释放 )的非特殊 字符。

代码贴出:


#define END_PRINT ('D' | KEY_SHIFT_FLAG | KEY_CTRL_FLAG)


void Printf(ulong_t arg)

{

Keycode key;


while(1)

{

if(Read_Key(&key))

{

if(key == END_PRINT)

{

Exit(1);

}

else

{

if( !( (key & KEY_SPECIAL_FLAG) || (key & KEY_RELEASE_FLAG) ) )

{

if(key == '/r')

{

Print("/n");

}

else

{

Print("%c", key);

}

}

}

}

}

}


长篇大论也许就这一段有用,哈哈!

希望大家实现更丰富的功能,例如删除和插入、大写功能等等功能键。

我会时刻更新的,也希望大家多多提供好的意见,好的实现。




 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值