//1. 线程组成部分: (A):一个是线程的内核对象,操作系统用他管理线程,存放线程统计信息 (B):一个线程栈,用于维护线程执行时所需的所有函数参数和局部变量 //2. (A):线程函数(实际包括所有函数)应该尽可能使用函数参数与局部变量。使用静态变量和全局变量时,多个线程同时访问时,很可能破坏变量中保存的内容 (B):系统从进程的地址空间中分配内存给线程栈使用。线程可以访问进程的内核对象的所有句柄、进程中所有内存以及同一个进程中其他所有线程的栈 //3. HANDLE WINAPI CreateThread( __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, //安全性 __in SIZE_T dwStackSize, //栈分配大小 __in LPTHREAD_START_ROUTINE lpStartAddress, //线程函数入口 __in_opt __deref __drv_aliasesMem LPVOID lpParameter, //传递给线程函数的参数 __in DWORD dwCreationFlags, //0表示立刻运行 CREATE_SUSPENDED表示挂起 __out_opt LPDWORD lpThreadId //用于获取线程ID ); CreateThread 函数是用于创建线程的Windows函数,不过如果写的是C/C++代码,就绝对不要使用 CreateThread ,相反要使用C++运行库中的 _beginthreadex _beginthreadex 会在内部调用 CreateThread ,并分配和初始化C/C++运行库相关资源 //4. 终止运行线程: (A):线程函数返回(强烈推荐) 让线程函数返回,可以确保以下正确的应用程序清理工作得到执行 (a):线程函数中创建的所有C++对象通过析构函数正确销毁 (b):操作系统正确释放线程栈使用的内存 (c):操作系统把线程的退出代码(线程内核对象中维护)设为线程函数的返回值 (d):系统递减线程的内核对象使用计数 (B):通过调用 ExitThread 杀死自己(避免使用) (a):ExitThread 该函数会导致操作系统清理该线程使用的所有操作系统资源。但是C/C++资源(如C++对象)不会被销毁 (b):若编写的是C/C++代码,则不要使用 ExitThread ,而要使用 _endthreadex (C):同一个进程或另一个进程中的线程使用 TerminateThread 函数(避免使用) (a):TerminateThread 是异步调用的 (b):调用 ExitThread 系统会释放对应线程的堆栈,而调用 TerminateThread 系统不会释放对应线程的堆栈,除非拥有此线程的进程终止 (D):包含线程的进程终止(避免使用) (a):正确的应用程序清理工作不会执行,比如C++对象的析构函数无法被调用 //5. 线程终止运行时,会发生如下事情: (A):线程拥有的所有用户对象句柄会被释放,在Windows中大多数对象都是由创建线程的进程所拥有,但是线程有两个用户对象:窗口(windows)、挂钩(hook) 一个线程终止运行时,系统会自动销毁由该线程创建或安装的任何窗口,并卸载由该线程创建和安装的任何挂钩。其他对象只有在进程终止时才被销毁 (B):线程的退出代码由 STILL_ACTIVE 变为传给 ExitThread 或 TerminateThread 的代码 (C):线程内核对象变为以触发状态 (D):如果线程是进程的最后一个活动线程,系统认为进程也终止了 (E):递减内核对象的使用计数 GetExitCodeThread 用于获取线程退出代码 //6. 每个线程都有其自己的一组CPU寄存器,称为线程的上下文。上下文反映了当线程上一次执行时,线程的CPU寄存器的状态。 线程的CPU寄存器全部保存在 CONTEXT 结构中。 CONTEXT 本身保存在线程内核对象中 //7. GetCurrentProcess GetCurrentThread 可以方便的获取主调进程或主调线程的内核对象句柄,返回的都是伪句柄,不会影响相关内核对象的使用计数 对于上述伪句柄,对其调用 CloseHandle ,则 CloseHandle 会忽略此次调用并返回 FALSE GetCurrentProcessId GetCurrentThreadId 可以获取唯一的系统级别的ID 若想将伪句柄转为真句柄,可以使用 DuplicateHandle