每个进程都有一个主线程。每个线程都包含2个部分:
1、一个内核对象,操作用此来管理线程,里面包含了线程的状态;
2、一个线程堆栈,用来维护所有的函数参数和局部变量。
启动线程,需要提供一个线程入口函数,该函数原形必须为如下形式:
DWORD WINAPI ThreadFunc(PVOID pvParam)
{
DWORD dwRet = 0;
return dwRet;
}
在这个函数里,你的线程执行相关任务,当该函数返回时,线程便停止了运行。线程堆栈也被清除,线程内核对象的引用计数减1。
你可以使用CreateThread函数创建一个线程,该函数返回一个线程内核对象句柄。
结束一个线程有4中方法:
1、线程函数返回
2、线程自己调用ExitThread函数终止自己运行
3、本进程内的其他线程或该线程自己调用TerminateThread函数指定终止一个进程
4、包含该线程的进程终止
应该尽量使用第1种方法,确保线程终止的时候所有资源可以被系统正确地回收。
线程内核对象中维护了一些数据结构,包括一个反应该线程最近运行情况的上下文内容“CONTEXT”,里面有一些“CPU的寄存器信息”,主要包括一个SP和IP,分别保存了线程堆栈中的入口函数地址和NTDLL.dll中的RtlUserThreadStart函数地址,该函数用来执行线程代码,并试图结束线程和处理一些异常。
数据结构中还包括一些属性信息:引用计数,挂起计数,退出代码(在运行的时候为STILL_ACITVE),受信状态(初始为FALSE)。
C/C++运行期函数中提供了2个创建线程的函数,使用这两个函数需要包含头文件“Process.h”,这两个函数是:_beginthread,_beginthreadex,与这两个函数配套使用的结束线程的2个函数是:_endthread,_endthreadex,可以在线程内部使用end函数结束线程,但是不推荐这么做,让线程函数自动返回更好。
_beginthread函数功能比较少,推荐使用_beginthreadex函数,其参数和返回值CreateThread函数本质上是相同的,只是顺序和类型不同,需要强制转换,_beginthreadex函数在内部会调用CreateThread函数,但是比CreateThread安全而且可靠。
另外,尽量使用_beginthreadex函数而不要使用CreateThread函数,貌似后者可能容易引起资源的泄漏而且不是非常可靠(个人理解)。
要取得本进程和本线程对应的句柄,可以使用GetCurrentProcess和GetCurrentThread函数。但是需要注意,这两个函数只返回伪句柄,也就是说这个返回值表明的意思就是“当前句柄”,而不代表“T1的句柄”(假设T1为当前线程)。当把这个伪句柄传递给其他进程或线程的时候,在其他进程和线程中也仅仅把它作为“当前句柄”来处理,假设线程T1调用GetCurrentThread得到一个伪句柄H,把它传给线程T2,T2就认为这个H也是“当前句柄”,也就是T2的线程对象句柄,而不是T1的了。
要将伪句柄转换为真实的句柄,可以使用复制句柄函数——DuplicateHandle函数。该函数在本书第三章有介绍,这里就不再说了。
第六章细节比较多,看过之后只能记个大概,很多就记了一个结论,够用就好吧,呵呵!
来源:https://www.cnblogs.com/wz19860913/archive/2008/07/29/1256016.html