GeekOS学习(7)Project0,创建键盘输入进程
2012-04-13 22:41
579 查看
终于看完系统的启动代码了!!哈,基本上结构我们也都已经了解了,接下来就开始做project!
先来看第一个,project0,要求创建一个内核线程,打印一些信息,并且调用Wait_For_Key来供用户输入字符。
先找到Wait_For_Key函数来看看
位于./src/geekos/keyboard.c
因为键盘缓冲区属于临界区,所以使用关中断来保护。
gotKey为1则说明键盘缓冲区不空,并从缓冲区出一个键盘码。
gotKey为0则等待。
s_waitQueue是专为键盘缓冲区访问而设置的等待队列,在键盘中断函数中会唤醒此等待队列。
总结,Wait_For_Queue完成:从缓冲区中取数据,每次取一个,缓冲区中若无数据则等待,直到有数据为止。
好了,接下来只要创建一个内核线程并调用Wait_For_Queue就行。
参照Init_Scheduler函数中的Start_Kernel_Thread(Reaper, 0, PRIORITY_NORMAL, true)
来使用Start_Kernel_Thread(print_out, 0, PRIORITY_NORMAL, true)试试看!!
在Main函数上面加入print_out函数
唔,仔细看一下Wait_For_Queue函数就可以写出来了。
另外要注意print_out函数的参数和返回类型。
运行时发现按一个键会打印2个同样的字符,这是因为按下和松开都会产生扫描码,中断处理程序都识别并压入了缓冲区。
好了,project0完成了,^_^!!
让我们来玩一些简单而又更酷的。
试试启动两个进程,一个进程打印A,另一个进程打印B。
添加代码
Start_Kernel_Thread(print_A, 0, PRIORITY_NORMAL, true);
Start_Kernel_Thread(print_B, 0, PRIORITY_NORMAL, true);
在Main函数上方添加函数
重新编译运行试试!
^_^,果然,屏幕一会儿输出A,一会儿输出B。如果你完成了project0的话,你也可以输入字符,这不就是活生生的多任务么。
包括内核线程Idle和Reaper。系统里就运行着5个任务。。
下面再来细致的分析一下GeekOS中的多任务机制。
1.时钟中断产生线程切换
任务print_A---->时钟中断---->从通用Handle_Interrupt进入特定中断函数Timer_Interrupt_Handler---->加时钟滴答---->滴答未到期---->返回Handle_Interrupt恢复堆栈回来运行print_A
任务print_A---->时钟中断---->从通用Handle_Interrupt进入特定中断函数Timer_Interrupt_Handler---->加时钟滴答---->滴答到期,置全局标志g_needReschedule表示需要重新调度---->返回Handle_Interrupt调用Get_Next_Runnable将新要运行的线程结构体赋给g_currentThread,并恢复新线程的堆栈---->最后iret返回,运行新进程。
2.键盘中断产生线程切换
任务print_A---->按了一下键位,产生键盘中断---->从通用Handle_Interrupt进入特定中断函数Keyboard_Interrupt_Handler---->处理扫描码得到显示字符keycode,并将keycode放入队列,唤醒等待键盘缓冲区的进程之后,直接置全局标志g_needReschedule表示需要重新调度---->返回Handle_Interrupt调用Make_Runnable将新要运行的线程结构体赋给g_currentThread并恢复新线程的堆栈---->最后iret返回,运行新进程。
先来看第一个,project0,要求创建一个内核线程,打印一些信息,并且调用Wait_For_Key来供用户输入字符。
先找到Wait_For_Key函数来看看
位于./src/geekos/keyboard.c
/* * Wait for a keycode to arrive. * Uses the keyboard wait queue to sleep until * a keycode arrives. */ Keycode Wait_For_Key(void) { bool gotKey, iflag; Keycode keycode = KEY_UNKNOWN; iflag = Begin_Int_Atomic(); do { gotKey = !Is_Queue_Empty(); if (gotKey) keycode = Dequeue_Keycode(); else Wait(&s_waitQueue); } while (!gotKey); End_Int_Atomic(iflag); return keycode; }
因为键盘缓冲区属于临界区,所以使用关中断来保护。
gotKey为1则说明键盘缓冲区不空,并从缓冲区出一个键盘码。
gotKey为0则等待。
s_waitQueue是专为键盘缓冲区访问而设置的等待队列,在键盘中断函数中会唤醒此等待队列。
总结,Wait_For_Queue完成:从缓冲区中取数据,每次取一个,缓冲区中若无数据则等待,直到有数据为止。
好了,接下来只要创建一个内核线程并调用Wait_For_Queue就行。
参照Init_Scheduler函数中的Start_Kernel_Thread(Reaper, 0, PRIORITY_NORMAL, true)
来使用Start_Kernel_Thread(print_out, 0, PRIORITY_NORMAL, true)试试看!!
在Main函数上面加入print_out函数
static void print_out(ulong_t arg) { while(1) { int key = Wait_For_Key(); int finish = ('d' | KEY_CTRL_FLAG); if( key == finish ){ Print("finish input \n"); Exit(0); }else Print("%c", key); } }
唔,仔细看一下Wait_For_Queue函数就可以写出来了。
另外要注意print_out函数的参数和返回类型。
运行时发现按一个键会打印2个同样的字符,这是因为按下和松开都会产生扫描码,中断处理程序都识别并压入了缓冲区。
好了,project0完成了,^_^!!
让我们来玩一些简单而又更酷的。
试试启动两个进程,一个进程打印A,另一个进程打印B。
添加代码
Start_Kernel_Thread(print_A, 0, PRIORITY_NORMAL, true);
Start_Kernel_Thread(print_B, 0, PRIORITY_NORMAL, true);
在Main函数上方添加函数
static void print_A(ulong_t arg) { while(1) { Print("A"); } } static void print_B(ulong_t arg) { while(1) { Print("B"); } }
重新编译运行试试!
^_^,果然,屏幕一会儿输出A,一会儿输出B。如果你完成了project0的话,你也可以输入字符,这不就是活生生的多任务么。
包括内核线程Idle和Reaper。系统里就运行着5个任务。。
下面再来细致的分析一下GeekOS中的多任务机制。
1.时钟中断产生线程切换
任务print_A---->时钟中断---->从通用Handle_Interrupt进入特定中断函数Timer_Interrupt_Handler---->加时钟滴答---->滴答未到期---->返回Handle_Interrupt恢复堆栈回来运行print_A
任务print_A---->时钟中断---->从通用Handle_Interrupt进入特定中断函数Timer_Interrupt_Handler---->加时钟滴答---->滴答到期,置全局标志g_needReschedule表示需要重新调度---->返回Handle_Interrupt调用Get_Next_Runnable将新要运行的线程结构体赋给g_currentThread,并恢复新线程的堆栈---->最后iret返回,运行新进程。
2.键盘中断产生线程切换
任务print_A---->按了一下键位,产生键盘中断---->从通用Handle_Interrupt进入特定中断函数Keyboard_Interrupt_Handler---->处理扫描码得到显示字符keycode,并将keycode放入队列,唤醒等待键盘缓冲区的进程之后,直接置全局标志g_needReschedule表示需要重新调度---->返回Handle_Interrupt调用Make_Runnable将新要运行的线程结构体赋给g_currentThread并恢复新线程的堆栈---->最后iret返回,运行新进程。
相关文章推荐
- GeekOS project0 -- 接收键盘输入并在屏幕回显
- 使用BIOS进行键盘输入和磁盘读写(学习汇编)
- nginx 源码学习笔记(十六)—— ngx_start_worker_processes子进程创建
- 使用BIOS进行键盘输入和磁盘读写03 - 零基础入门学习汇编语言77(完)
- 同步或异步调用EXE(创建子进程并重定向子进程的输入、输出)
- Python模块学习 ---- subprocess 创建子进程
- Linux-C基础知识学习:C语言作业-从键盘输入一个三位数,以逆序输出。例如输入456,输出654
- 20135202闫佳歆--week6 进程的描述与创建--学习笔记
- 从键盘上输入文件的内容和要保存的文件名称,然后根据输入的名称创建文件,并将内容保存到文件中
- 【Visual C++】游戏编程学习笔记之七:键盘输入消息
- nginx 源码学习笔记(十六)—— ngx_start_worker_processes子进程创建
- 使用BIOS进行键盘输入和磁盘读写01 - 零基础入门学习汇编语言75
- linux进程学习-创建新进程
- 【TypeScript学习笔记】代码中反引号的作用-多行文本输入创建多行字符串
- 从键盘上输入文件的内容和要保存的文件名称,然后根据输入的名称创建文件,并将内容保存到文件中
- 和菜鸟一起深入学习国嵌实验之进程创建,exec函数,进程等待
- 【Visual C++】游戏编程学习笔记之七:键盘输入消息
- WPF and Silverlight 学习笔记:键盘输入、鼠标输入、焦点处理
- 通过键盘输入创建链表.c
- 使用BIOS进行键盘输入和磁盘读写01 - 零基础入门学习汇编语言75