CloseHandle疑惑
来源:互联网 发布:如何购买淘宝网店 编辑:程序博客网 时间:2024/06/10 00:40
句柄实际上是指向内核对象内存块的指针、访问掩码、标志.(其实微软为了隐藏里面的结构体,故意以void*来表示)
对于Windows的线(进)程而言,系统总是维护一个与当前进程(线)相关的一张句柄表.当我们创建一个进程(线)时,句柄使用计数就会加1,因为继承关系(继承父进程的句柄)而产生后的句柄,使用计数同样加1.但是CloseHandle的实质是告诉进程(线程),当前句柄使用计数减1,如果句柄使用计数减为0,那么内核对象会被销毁,同样线程也会结束.(前提是线程还没有运行),也就是说,当系统要运行的时候,它就会检查句柄使用计数是否为0,如果是0,则退出进(线)程,否则执行进(线)程.
说了一大堆,还是看代码吧!
代码一:
DWORD WINAPI ThreadProc1( PVOID pvParam ){cout<<"thread one running..."<<endl;for( int i = 0;i< 10000;++ i ){cout<<"i = :"<<i<<endl;}return 0;}void main(){DWORD dwThread1ID;HANDLE hThread = CreateThread( NULL,0,ThreadProc1,NULL,0/*CREATE_SUPPEND*/,&dwThread1ID );CloseHandle( hThread );getchar();return;}
使用CloseHandle时,线程已经结束(可以通过Process Explorer来查看)但是输出依然在继续.
这个地方不是很理解.开始以为是10000不够大,cpu实际上已经处理完成,后来加大数字,而且把cout<<"thread one running..."<<endl;移至循环内,经过发现线程还是闪一下就退出了,但是输出并没有结束.这就奇怪了.
代码二:
DWORD WINAPI ThreadProc1( PVOID pvParam ){cout<<"thread one running..."<<endl;for( int i = 0;i< 10000;++ i ){cout<<"i = :"<<i<<endl;}return 0;}void main(){DWORD dwThread1ID;HANDLE hThread;hThread = CreateThread( NULL,0,ThreadProc1,NULL,0,&dwThread1ID );Sleep(100);SuspendThread( hThread );CloseHandle( hThread );ResumeThread( hThread );//hThread已经无效,但当线程暂停,当前线程无法操作之前的线程.getchar();return;}
这个程序开始确实想错了,本来是想测试线程暂停和执行时,内核使用计数对其的影响,后来发现证明我的想法是错的.原因见注释.
这里关于CloseHandle,再回过头看msdn,里面就线程问题专门进行了说明:
Closing a thread handle does not terminate the associated thread. To remove a thread object, you must terminate the thread, then close all handles to the thread.
意思大概是要想终止线程,必须关闭所有的句柄并且终止线程.单独关闭句柄并不能使线程结束.
纠结了很久,再次查看核心编程,它上面是这样说的,调用CloseHandle,如果句柄有效,系统将根据内核对象的地址找到使用计数,然后递减,如果计数为0,内核对象将被销毁,并从内存中除去.那它的意思是创建一个线程的时候,使用计数不是1而是2?如果是1的话,那肯定内核对象将被销毁了.也就不会出现上述代码出现的问题.
那么可以有两种解释:一种是内核对象和线程是两个并不相关的东西.二中解释就是之前所说的计数为2.
前一种解释是不通的:首先内核对象是系统为管理线程而创建的.如果内核对象都销毁了,线程就变成了游离态,这岂不是一个天大的bug.我估计微软也不可能做这么愚蠢的事情.
后一种解释的话,好像不是怎么好理解.实际上核心编程针对CreateProcess有了对内核对象的引用计数的说明.书中指出创建进程内核对象和线程(主)对象的时候,系统会每个对象指定一个初始化引用计数1.然后在CreateProcess返回之前,它使用完全的权限来打开进程进程对象和线程对象.并保存在PROCESS_INFORMATION结构中.这是因为是再一次打开(可以理解成引用),对应的使用技术自然是+1(也就是2).
很悲剧的一件事情,弄了半天居然就这么简单.当初在看的时候也没有太留意.导致出现这么大的错误.后来在网上发现原来已经有人发表过类似的博客了.这更加让人悲剧.
- CloseHandle疑惑
- 对closehandle()的疑惑终于弄明白了
- closehandle
- CloseHandle()
- CloseHandle
- CloseHandle
- CloseHandle()
- closehandle();
- CloseHandle
- CloseHandle
- CloseHandle
- CloseHandle()
- CloseHandle
- 疑惑
- 疑惑
- 疑惑
- 疑惑
- 疑惑
- UIView 绘画
- phpmyadmin中乱码很通俗的解释和解决方法
- Java调用SQL存储过程详解.
- 树形结构的处理——组合模式(四)
- 【java】Java开源建站工具
- CloseHandle疑惑
- C++简单程序典型案例
- 序列化与反序列化概述
- 主备切换和心跳机制的一点考虑
- 红黑树
- 【排序算法】鸡尾酒排序的实现与分析
- Unity 3D网页游戏 Demo 展示
- 红黑树
- Android ApiDemos示例解析(160):Views->Layouts->TableLayout->05. Spanning and Stretchable