线程的CloseHandle和WaitForSingleObject

来源:互联网 发布:json python 文件 编辑:程序博客网 时间:2024/05/29 17:39

最近在学习的时候 需要创建多线程的应用程序来访问设备 但是不知道为什么始终进不了线程的执行函数里边 经过一番百度 知道了原因 写下以下总结

在学习线程的时候书上有这么一段话“线程对象也可以提前释放,对于大部分的句柄来说,使用CloseHandle函数关闭句柄意味着整个对象被释放,但对于线程句柄来说,关闭它仅释放线程的统计信息,并不会终止线程的执行,如果不在需要使用线程句柄的话,在调用CreateThread后马上就可以将它关闭掉,线程的执行并不会受影响”

以下是一段测试代码:

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .386
                .model        flat,stdcall
                option        casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include            windows.inc
include            kernel32.inc
includelib        kernel32.lib
include            user32.inc
includelib        user32.lib

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>        
                .data?
hStdOut                dd        ?
hThread                dd        ?

                .const

szShow                db        '进入了线程执行函数',0dh,0ah,0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>        
_Thread         proc        uses ebx esi edi,_lParam
                
                invoke      lstrlen,offset szShow
                push        ecx
                invoke      WriteConsole,hStdOut,offset szShow,eax,esp,NULL
                pop          ecx
                ret

_Thread         endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
                invoke     GetStdHandle,STD_OUTPUT_HANDLE        
                mov         hStdOut,eax
                push       ecx
                invoke     CreateThread,NULL,0,offset _Thread,NULL,0,esp
                pop         ecx
                mov         hThread,eax
                invoke     CloseHandle,hThread
                invoke     WaitForSingleObject,hThread,INFINITE;

                invoke     ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                end        start


在上面的代码中,创建完线程以后,就把线程句柄关闭了 但是并没有像预期的那样打印出“进入了线程执行函数” 是没有进入_Thread吗? 还是其他什么原因了

用OllyDBG跟入发现

第一 在_Thread中设置了断点 但是没有断下来就结束了  

第二 WaitForSingleObject函数返回失败


百度以后发现一下内容

1. 对于内核对象,系统会维护一个引用计数,
2. 对于每个进程,进程本身维护了一个句柄表,记录它可以操作的内核对象在本进程内的映射值(就是句柄)
3. CloseHandle会删除内核对象的一个引用计数,同时会删除进程句柄表中的一项(如果该句柄在进程内再无引用)
4. WaitForSingleObject对传进来的句柄首先执行的动作就是查进程的句柄表,如果不存在这一项,返回无效句柄错误


WaitForSingleObject在CloseHandle前调用,这个使用hThread还在进程句柄表里
CloseHandle先一步把进程句柄表里的hThread这一项删掉了,再去WaitForSingleObject当然找不到句柄了

修改上边的程序 把WaitForSingleObject放在CloseHandle前执行

......

invoke     WaitForSingleObject,hThread,INFINITE;

invoke     CloseHandle,hThread

......

程序打印出了 期待的“进入了线程执行函数”

由此可以总结 以后在使用CloseHandle关闭线程句柄时 要确认是否后边还要用到它 是否查询进程的句柄表