最近在学习的时候 需要创建多线程的应用程序来访问设备 但是不知道为什么始终进不了线程的执行函数里边 经过一番百度 知道了原因 写下以下总结
在学习线程的时候书上有这么一段话“线程对象也可以提前释放,对于大部分的句柄来说,使用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关闭线程句柄时 要确认是否后边还要用到它 是否查询进程的句柄表