首页 理论教育 Shell消息处理过程及实现

Shell消息处理过程及实现

时间:2023-10-21 理论教育 版权反馈
【摘要】:缺省情况下,一个线程在创建的同时会创建一个消息队列,该消息队列与线程的控制结构进行绑定。在EntryPoint的实现中,首先打印出用户提示标识符,然后进入一个循环,循环调用GetMessage函数,从自己的线程队列中获取消息进行处理。DispatchMessage函数完成消息分发的功能,当前情况下,其实现十分简单,只是把KernelThreadMessage中的参数分离出来,然后调用消息处理函数EventHandler。根据按键的不同,分三种情况进行处理。这时候输入help命令,即可显示出系统中所有可用的命令。

Shell消息处理过程及实现

缺省情况下,一个线程在创建的同时会创建一个消息队列,该消息队列与线程的控制结构(核心线程对象)进行绑定。其他的线程可以调用SendMessage函数向该线程发送消息,发送的消息类型是__KERNEL_THREAD_MESSAGE。线程可以调用GetMessage函数从自己的消息队列中获取消息,该函数以KernelThreadMessage的地址指针)为参数。若该函数成功地从消息队列中获取了一个消息,则返回TRUE,KernelThreadMessage结构体里面存储了所获得的消息的内容;若当前线程消息队列为空,则该函数会阻塞当前线程的运行,等待消息的到来。

线程之间的消息有许多种类型,比如键盘消息、鼠标消息以及用户自己定义的消息。在EntryPoint的实现中,首先打印出用户提示标识符,然后进入一个循环,循环调用GetMessage函数,从自己的线程队列中获取消息进行处理。

GetMessage和SendMessage函数的实现在另外的章节中会有描述。DispatchMessage函数完成消息分发的功能,当前情况下,其实现十分简单,只是把KernelThreadMessage中的参数分离出来,然后调用消息处理函数EventHandler。其中,EventHandler函数作为一个指针,传递给DispatchMessage函数,该函数的实现代码如下:

978-7-111-41444-5-Chapter03-54.jpg

978-7-111-41444-5-Chapter03-55.jpg

当前的实现中,EventHandler函数只处理键盘消息。其中,KernelThreadMessage的wCommand变量存储了具体的消息类型,目前情况下,定义了两种键盘消息:MSG_KEY_DOWN和MSG_KEY_UP,分别在用户按下键盘和放开按键的时候由键盘驱动程序发送。其中,EventHandler函数只处理键盘按下消息MSG_KEY_DOWN。wCommand成员标明了消息类型,而dwParam变量(KernelThreadMessage的另一个成员)则包含了对应于特定消息的相关参数,比如,在按键消息中,dwParam的最低一个字节存放了键盘被按下的ASCII码,这样EventHandler函数就可以根据dwParam的最低一个字节确定按下的是哪个键。根据按键的不同,分三种情况进行处理。

(1)若按下的键是回车键(VK_RETURN),则EventHandler函数判断当前键盘缓冲队列(CmdBuffer是一个键盘缓冲队列,BufferPtr则指明了当前队列中元素的数量)是否为空,若为空(BufferPtr为0),则只会换一行,重新打印出提示字符串“[system-view]”,然后返回。若不为空,则说明用户已经在提示符下输入了命令。这时候EventHandler函数会调用DoCommand函数来处理用户输入的命令。在目前的实现中,CmdBuffer是一个全局变量数组,因此DoCommand函数可直接访问该数组,不需要任何参数。DoCommand函数的实现在后面进行详细介绍。

(2)若按下的键是一个退格键(Backspace),则判断当前命令缓冲区(CmdBuffer)是否为空,若为空,则不作任何处理;若不为空,则删除缓冲区的最后一个元素,并把显示器上的光标后移一格(GotoPrev函数),最终的表现就是用户按Backspace键,删除了输入的一个字符。

(3)若按下的键不是上述两者之一,则EventHandler函数会判断当前命令缓冲区是否满(长度是否达到了MAX_BUFFER_LEN,目前定义为512)。若已经满了,则不做任何处理,直接返回,否则,会把用户按下的键的ASCII字符存到CmdBuffer当中,并更新BufferPtr。(www.xing528.com)

与DOS命令提示符类似,EventHandler函数实际上实现了一个简单的行编辑器,用户可以输入字符,通过Backspace键删除字符,并通过回车键确认输入的命令引发操作系统的执行。

上面讲到,若用户按下的键是回车键,且当前命令缓冲区不为空,则EventHandler函数会调用DoCommand函数,处理用户输入的命令。DoCommand函数会对CmdBuffer(全局的命令缓冲区)进行分析,然后根据命令的不同,调用合适的处理函数。系统中维护了一个命令字符串与对应的处理函数之间的映射表,DoCommand函数无非是用命令缓冲区中的字符串,逐个匹配映射表中的项目。若匹配到一个命令,则调用对应的处理函数。在调用处理函数的时候,是以命令缓冲区(CmdBuffer)为参数的。这样命令处理函数可以把用户输入作为参数进行更进一步处理。比如用户输入了字符串“ktview–i 10”后,按下了回车键。这时候DoCommand会使用字符串中的“ktview”来匹配映射表,找到其处理函数KtViewHandler后,把整个字符串传递给这个函数。下面是命令字符串与处理函数之间的映射表:

978-7-111-41444-5-Chapter03-56.jpg

978-7-111-41444-5-Chapter03-57.jpg

其中__CMD_OBJ是预先定义的一个结构体,把一个字符串和一个处理函数进行了关联。在shell成功启动后,用户即可看到[system-view]提示符。这时候输入help命令,即可显示出系统中所有可用的命令(及其帮助信息)。如图3-10所示。

978-7-111-41444-5-Chapter03-58.jpg

图3-10 运行截图

需要注意的是,help的输出结果与上述命令行与处理函数映射表之间不是一一对应的关系,在映射表中的一些命令,并没有显示在help列表中。这些未显示的命令是内部测试命令,不对外呈现。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈