现代操作系统都是多任务的,操作系统在不同的时间片内把CPU及硬件资源分配给不同的任务,在Windows系统中每一个任务就是一个线程,它是CPU执行调度的最小单元,而进程是线程的容器,为线程提供虚拟地址空间。
多线程环境可以让一个进程即一个应用程序将所要完成的任务进程分配,例如一个浏览器使用一个界面线程来完成与用户的交互,一个线程负责和服务器进行数据的传输,一个线程负责HTML代码的解析,一个线程负责脚本的解析等等。多线程的好处是显而易见的,我们可以的边看电影边聊天等等都是多线程的体现。然而并不是所有的需求都使用多线程来完成是最好的,多线程会带来新的需要处理的问题,例如对全局资源的访问可能造成数据破坏,Windwos的消息机制是基于线程的,因此两个线程创建各自的窗口只能捕获各自窗口的消息,因此需要合理的使用多线程编程,线程同步在多线编程中变得如此的重要。
CreateThread函数
HANDLE CreateThread(
__in SEC_ATTRS SecurityAttributes,
__in ULONG StackSize,
__in SEC_THREAD_START StartFunction, //线程开始地址,通常是一个函数指针
__in PVOID ThreadParameter, //传给新线程的参数
__in ULONG CreationFlags,
__out PULONG ThreadId
);
StackSize 为新线程分配的栈大小,如果为NULL,使用连接器 /stack 选项指定的大小, 应该为栈指定大小 来防止BUG
线程的终止:
1、使用ExitThread ,系统清理线程所使用的资源,释放线程栈空间,但是不会释放线程中申请的堆空间,不会调用对象的析构函数,
2、TerminateThread ,不释放栈空间,不释放堆空间,不调用析构函数,函数返回并不保证线程已终止
当线程终止运行时:
- 线程拥有的用户对象,窗口,钩子被销毁
- 线程的退出代码从STILL_ACTIVE变成传给退出函数的退出码
- 线程内核对象变为触发状态
- 如果线程是进程中的最后一个活动线程,则进程终止
- 线程内核对象引用计数-1
系统创建一个线程的时候,创建一个线程内核对象,系统通过线程内核对象管理线程,该对象开始时引入计数为2,返回线程内核对象句柄,一旦创建线程内核对象就为其分配栈内存,将新线程的参数 线程入口地址 先后放入栈,初始化线程上下文,CONTEXT结构,SP寄存器指向放入栈的线程入口地址,IP 指令指针 放入RtlUserThreadStart的地址,该函数位置NTDLL.DLL中。
在线程被内核调度使用CPU就是从这里开始执行的,栈上已经放好了传过来的参数,然后这个函数会构建一个SEH结构异常,通过栈上的新线程地址和参数 执行新线程的代码,线程完成返回时,返回值传给ExitThread,线程终止,如果线程发生异常没有被线程内的异常处理程序消化掉,那么线程最外层的这个异常处理程序被调用,结束进程。
使用C/C++运行库的 _beginthreadex
如果程序是使用C/C++ 且使用微软的VS平台,那么应该使用_beginthreadex创建线程 使用_endthreadex 退出线程
这里可以参考http://blog.csdn.net/wangpengk7788/article/details/53958387
伪进程线程句柄
GetCurrentProcess();
GetCurrentThread();
这两个函数返回的是伪句柄,不增加内核对象的引用计数,将需要把伪句柄转换为真句柄是 需要使用DuplicateHandle 函数