MFC学习第二天心得!(关于系统队列、任务队列、消息队列)

来源:互联网 发布:软件项目质量计划 编辑:程序博客网 时间:2024/05/17 03:27
 MFC学习第二天

 今天主要是弄懂什么是系统队列,任务队列(程序队列)和消息队列!全是本菜鸟一字一字打出来的,里面有错的,请大家指点,请不要随便骂人,谢谢!真的很累!如果对大家有帮助,非常容幸!

 

While(int bRet=BOOL GetMessage(LPMSG lpMsg,HWND hWnd,UINT wMsgFilterMin,UINT wMsgFilterMax)

          {

             If(bRet==-1)

                {

                 Return false;

                }

             Else

                {

               TranslateMessage(&msg);

               DispatchMessage(&msg);

}  

}

本菜鸟刚开始看的时候,被什么系统队列、任务队列(程序队列)、线程消息队列搞得头都是大的,实在不知道该怎么区分他们,后面搞得我烦了!直接上反汇编加上在网上找了很多资料!略有心得,不一定正确,大家看看就行!

 

1.先看看他们的运行模式和区别!

Windows一启动的时候,就会初始化kernel,再接着加载user.exe,加载完后,马上会用createSystemQueue()去创建系统队列(所以windows只有一个系统队列).

 

创建任务后,由启动代码调用user的InitApp()模块,再通过CreateTaskqueue()来创建任务队列(或称程序队列).所以一个程序一个任务队列。

 

通过反汇编可以略得知里面的几个关键内容:(下面不是连续的,我只是分别写了几个关键的代码段,另外的中间或许省去)

 

//创建系统队列(只接受windows硬件的输入(键盘和鼠标等))

createSystemQueue()

mov    ax,[00f2]  //把系统队列中的消息个数保存到ax中,默认是78H

mov    ax,000E   //系统队列里每条消息的长度,默认00Eh

CALL CreateQueue(5aE0)   //这句话关键啦,这就创建了系统队列。Createqueue()

                         其实就是创建系统的消息队列.

Mov [0000],ax      //在user的一个固定段中填入句柄队列的选择符。[0000]这是类似于模块链表,任务链表,保存的是系统队列的选择符,通过选择符可以找到系统队列的句柄。而偏移E6H处保存的是任务队列的链表头.

//创建任务队列(程序队列)

CreateTaskqueue()

Push word ptr[bp+6]  //任务队列中的消息个数。默认为8

Mov ax,0016         //任务队列中每条消息的长度,默认为11fh字节

CALL CreateQueue(5ae0)  //关键点了吧,和系统队列一样创建程序的消息队列。现在看到了吧,其实系统队列和任务队列里的消息队列底层实现是差不多的.  

 

 

//看看消息队列是怎么创建的吧。太TMD的复杂了

CreateQueue()

CALL KERNEL GETCURRENTTASK   //在ax中获得当前任务的TDB句柄

Push ax    

Mov ax,[bp+06]                 //消息队列中的消息个数到ax

Mov cx,[bp+04]                 //每条消息的长度到cx

Mul cx                        //消息队列中保存消息的区域长度
call kerne!globalalloc            //分配消息队列所需的内存块

Mov es,ax                     //es指向消息队列

Or ax,ax                      //判断内存分配是否成功

Jz 5be6                      //失败,退出createqueue()

Xchg ax,bx                    //当前任务的TDB句柄到ax,当前任务的消息队列选择符到bx

Mov DI,0002                  //消息处偏移02处

Stows                        //把拥有这条消息队列的任务句柄填入消息队列中

Mov ax,[bp+04]               //每条消息的长度到ax

Stows                       //填入消息队列偏移04处

··· ··· ···//消息链表的创建,这个大同小异,就没写了

Cmp word ptr es:[00e6],+00      //判断windows是否创建了消息队列(PROGMAN的消息队列,并不是系统队列)

Jnz 5b6e                      //已经创建,则转

Mov es:[00e8],ax               //没有,则在固定段中保存progman的消息队列选择符[es:00e8]

Cmp word ptr es:[0000],+00     //判断是否创建了系统队列

Jz 5b6e                       //没有,则转

Mov bx,es:[0000]              //系统队列选择符到bx

Or bx,bx

Jz 5b6e                     //不存在系统队列。则转

Mov es,bx                    //es指向系统队列

Cmp word ptr es:[0006],+00     //检测系统队列中设置的消息个数

Mov es,ax                    //es指向progman的消息队列

Jz 5b6e                      //系统队列中保存消息的空闲个数为0,则转

Or word ptr es:[0044],+07      //在progman的消息队列中设置键盘消息和鼠标消息的类型标记:qs_key+qs_mouse

··· ··· ···

这个就是创建消息队列的过程。真TMD的打得烦,如果微软肯提供源代码的话,其实是很简单的东西!

大家从上面应该就能知道系统队列和任务队列究竟怎么来的!他们各自的消息队列又是如何创建的!TNND,花了我一天的时间才弄懂!

顺便提醒一句,硬件消息进入系统消息队列后,是不进入到任务队列的,而是直接getmessage到一个msg结构(例如键盘输入),然后转换成wm_char消息放入到任务队列中,下次getmessage到这个wm_char消息后,再通过dispatchmessage放到窗口响应,鼠标消息也是,他们的消息不进入到任务队列中,直接发送到窗口响应!当然这里面有自己的一套过程,明天我再写一篇关于系统队列和任务队列是如何发送消息和接收消息(任务队列),和getmessage的底层实现!

 

因为本人是菜鸟,不对的地方请大家指点,请不要骂我,谢谢!里面的很多知识,有我一步一步调试的,也有很多来源于很多大N们的文章,是在网上找的,谢谢各位!

原创粉丝点击