GeekOS课程设计-project0

要求

项目0要求实现一个内核进程,功能是实现从键盘接收一个按键,并在屏幕上显示。主要是让学生熟悉GeekOS的编译、运行过程,了解计算机系统的启动原理。

分析

在这个项目里面主要用到两部分的内容:内核线程和键盘处理,相应的文件是kthread.c和keyboard.c。GeekOS 在/src/geekos/keyboard.c 和/include/geekos/keyboard.h 分别给出了从键盘获 取字符函数 Read_Key()的实现以及相应键位所对应的函数返回值,我们在实现 project0() 这个函数的功能时需要调用到 Read_Key()这个函数,然后根据其返回值分析出所输入的 字符属于什么类型,如果是特殊键就暂时不做处理,等待遇到非特殊键再进行处理。 GeekOS 的启动函数是/src/geekos/main.c 中的 Main(),我们需要在系统初始化完成之后开始执行我们想要执行的代码(即 project0()中的代码),因此需要创建一个内核线 程并将 project0()这个函数作为参数传入,随后系统会自动调度执行。

1、Start_Kernel_Thread函数

①Start_Kernel_Thread函数(在kthread.c中)主要功能:建立一个内核线程。

内核线程结构的定义如下:

struct Kernel_Thread {
     unsigned long esp;
     volatile unsigned long numTicks;
     int priority;
     DEFINE_LINK( Thread_Queue, Kernel_Thread );
     void* stackPage;
     struct User_Context* userContext;
     struct Kernel_Thread* owner;
     int refCount;
     Boolean alive;
    struct Mutex joinLock;
    struct Condition joinCond;
  };

esp字段用来存放一个线程挂起的堆栈指针;

stackPage字段指向内核线程的堆栈页面

numTicks和priority分别被调度程序用来实现基于先占权和基于优先权的时间片调度。

DEFINE_LINK宏定义一个内核线程在线程队列上时的前一个和后一个字段。

userContext字段如果不为空,则指向一个线程用户环境,它是一个允许线程执行用户模式的代码和数据的组合段。

内核线程有两种方式创建。在内核里独立运行的线程可通过Start_Kernel_Thread()函数来创建,该函数通过一个指针指向一个执行线程体的启动函数。线程所执行的用户模式的程序由Start_User_Thread()函数创建,并且用一指针指向一个用户环境和用户环境内存中代码入口点的地址。调用Exit()函数销毁内核线程。
首先在主程序里调用Start_Kernel_Thread 开始创建一条内核线程:Mythread=Start_Kernel_Thread (&MyFunction,0,PRIORITY_NORMAL,false);
入口参数分别为:函数地址,函数参数(无参数就写0),优先级设定,线程属性(false为内核线程,true为用户线程),返回值Mythread 的数据类型是static struct Kernel_Thread* thread

②Start_Kernel_Thread 完成的工作:
Create_Thread(priority, detached)         //根据优先级创建一条线程
kthread = Alloc_Page()                    //为线程分配内存空间
        stackPage = Alloc_Page()
        Init_Thread(kthread, stackPage, priority, detached)
       Add_To_Back_Of_All_Thread_List(&s_allThreadList, kthread)
Setup_Kernel_Thread(kthread, startFunc, arg)//配置内核线程的初始化
Make_Runnable_Atomic(kthread);           //设置线程运行的原子性操作
       Disable_Interrupts();             //禁止中断
               Make_Runnable(kthread);   //线程运Enable_Interrupts();                     //使能中断

2、Geekos是如何处理键盘代码

在keyboard.c里面提供了一个功用函数Keycode Wait_For_Key(void),循环等待一个键盘事件,然后返回一个16位的数据 Keycode型的, 在keyboard.h里定义了所有的键盘代码。Read_Key(Keycode* keycode)函数可以处理队列键盘按键,可以保存到队列中并输出。关于Keycode的定义是:

低8位用来表示键盘值,通过s_scanTableNoShift和s_scanTableWithShift这两个数组来转换相应的键盘码为所表示字符的ASCII码,高六位分别是:
KEY_SPECIAL_FLAG (特殊键,比如F1,F2) 用返回的值key&0x0100 就可以判断是否按下特殊健,1为有效,说明是特殊健,0则不是,以下的几种情况类似

KEY_KEYPAD_FLAG (小键盘键) 0x0200
KEY_SHIFT_FLAG (左,右SHIFT) 0x1000
KEY_ALT_FLAG (左,右ALT) 0x2000
KEY_CTRL_FLAG (左,右CTRL) 0x4000
KEY_RELEASE_FLAG (键弹起来标志位) 0x8000

实现

1) 编写一个C语言函数,函数功能是:接收键盘输入的按键,并将键值在显示器显示出来,当输入ctrl+d就退出;
/project0/src/geekos/main.c:

void project0(){
    Print("To Exit hit Ctrl + d.\n");
    Keycode keycode;
    while(1)
    {
        if(Read_Key(&keycode))
        {
            if(!((keycode & KEY_SPECIAL_FLAG) || (keycode & KEY_RELEASE_FLAG)))// 不是特殊键或者弹起
            {
                int asciiCode = keycode & 0xff;//d
                if((keycode & KEY_CTRL_FLAG)==KEY_CTRL_FLAG && asciiCode=='d')//ctrl+d
                {
                    Print("\n---------BYE!---------\n");
                    Exit(1);
                }else
                {
                    Print("%c",(asciiCode=='\r') ? '\n' : asciiCode);
                }
            }
        }
    }
}

2) 在Main函数体内调用Start_Kernel_Thread函数,将步骤1编写的函数地址传递给参数startFunc,利用Setup_Kernel_Thread函数建立一个待运行的线程。

struct Kernel_Thread *thread;
thread = Start_Kernel_Thread(&project0,0,PRIORITY_NORMAL,false);

3) 在Linux环境下编译系统得到GeekOS镜像文件。
进入Build目录下:

$ make depend
$ make

4) 编写一个相应的bochs配置文件。
cd ~/geekos-0.3.0/src/project0/build/
gedit .bochsrc

megs: 8
boot: a
floppya: 1_44=fd.img, status=inserted
Log: ./bochs.out

5) 在bochs中运行GeekOS系统显示结果。
运行Bochs模拟器,执行GeekOS内核。

$ cd  ……/build
$ bochs

运行后启动界面:

这里写图片描述

此时可以从键盘向虚拟机输入一下文字,输入完毕后按“Ctrl+d”组合键可退出程序,测试结果如下:

这里写图片描述

Project0 项目完成。
附完整代码下载链接:GeekOS课程设计-project0-CSDN下载 http://download.csdn.net/download/qq_35008279/10190102
  • 19
    点赞
  • 77
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值