Windows 核心编程之6 线程内核对象
2013-08-13 17:28
423 查看
线程内核对象每个进程里,都有一个线程,操作系统用线程内核对象来管理线程。线程有2部分组成:1 线程内核对象。 操作系统来管理线程 2 线程栈, 来存在函数和局部变量的地址空间。什么情况下使用多线程? 当各个任务彼此独立时,可以使用多线程,如:开一个后台线程来检测语法。什么情况下不要使用多线程? 任务联系紧密。如 扫描一个目录的文件,就不适合开多个线程处理,这样处理起来复杂度很高!实现CreateThread 来创建一个线程.如果是C、C++代码的话,使用_beginThreadEx来创建线程为什么? 因为有些C函数里面使用了静态变量,那么多个线程执行的话,会有冲突,但是_beginThreadex做了线程局部处理,它内部就调用了CreateThread函数。WINBASEAPI 表示是winbase.h的API__out_opt 表示是输出HANDLEWINAPICreateThread( __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, 安全属性,一般为NULL表示默认 __in SIZE_T dwStackSize, 线程栈的空间,一般使用0来表示默认值 __in LPTHREAD_START_ROUTINE lpStartAddress, 线程函数地址 __in_opt LPVOID lpParameter, 线程函数参数 __in DWORD dwCreationFlags, 创建线程时,指定啥标志 0 表示立即开始执行,CREATE_SUSPENDED 表示暂停 __out_opt LPDWORD lpThreadId 返回线程ID,不需要时,可以传递NULL,表示不关心 );终止运行线程的4种方式:1 线程函数返回(推荐)可以清理C++对象资源,会调用C++的析构函数清理线程栈2 自己调用ExitThread(避免使用)不会调用C++的析构函数清理线程栈如果使用的是C++代码,那么调用_endThreadEx() 来替换ExitThread3 其它线程调用TerminateThread() 避免使用不会调用C++析构函数,也不会清理线程栈ExitThread来结束的线程,会清理堆栈,但是调用terminateThread()函数 不会清理堆栈信息,除非线程所在进程终止。4 线程所在的进程终止 避免使用C++析构函数不会调用,线程被强行杀死,正常的清理工作没有执行。线程终止时,会发生以下事情:1 线程拥有的所有对象句柄被释放一个线程有2个用户对象: 窗口和挂钩2 退出码有STILL_ACTIVE 变成 ExitThread 或者TerminateThread 返回的退出码3 线程内核对象变成触发状态4 如果线程是最后一个活动线程,那么进程也终止。5 线程内核对象的引用计数减一C和C++库标准的C和C++库,最开始不是为了多线程设计的,在多线程环境下有些函数会出问题:errno,_doserrno, strtok, _wcstok, strerror, _strerror, tmpnam, tmpfile,asctime,gmtime,等所以要不要调用系统的CreateThread,而要调用C,C++运行库 _beginthreadex_beginthreadex 分配和初始化 初始化数据块,并将它与新的线程关联起来_endthreadex 函数 在线程终止运行的 释放分配的数据块不要使用C和C++运行库的这一对函数_beginthread ,_endthread了解自己的身份返回当前进程的句柄 和 IDHANDLE GetCurrentProcess();DWORD GetCurentProceddID();返回当前线程的句柄 和 IDHANDLE GetCurrentThread();DWORD GetCureentThreadID();注意: 上面这2个函数返回的都是伪句柄伪句柄:表示当前线程的句柄,即调用线程的句柄。下面举一个示例来分析
#include <iostream> #include <vector> #include <map> #include <Windows.h> #include <tchar.h> #include <process.h> #include <Strsafe.h> HANDLE ghthreadCurrent = NULL; unsigned int WINAPI ThreadFunc2(LPVOID lp); unsigned int WINAPI ThreadFunc1(LPVOID lp) { HANDLE hThread = GetCurrentThread(); ghthreadCurrent =(HANDLE) _beginthreadex(NULL, 0, ThreadFunc2, hThread, 0, NULL); while(1) { printf("111\n"); Sleep(1000); } return 0; } unsigned int WINAPI ThreadFunc2(LPVOID lp) { HANDLE hThread = (HANDLE)lp; TerminateThread(hThread,0); return 0; } int main() { HANDLE hThread1 =(HANDLE) _beginthreadex(NULL, 0, ThreadFunc1, NULL, 0, NULL ); WaitForSingleObject(hThread1,INFINITE); return 0; }线程2 的线程函数 TerminateThread 会把自己杀死,不会杀死线程1使用一个复制句柄的函数 DuplicateHandle() 来复制句柄
#include <iostream>#include <vector>#include <map>#include <Windows.h>#include <tchar.h>#include <process.h>#include <Strsafe.h>unsigned int WINAPI ThreadFunc2(LPVOID lp);unsigned int WINAPI ThreadFunc1(LPVOID lp){HANDLE hThread = GetCurrentThread();HANDLE hTagrealThread = NULL;BOOL bOk = DuplicateHandle(GetCurrentProcess(),hThread,GetCurrentProcess(),&hTagrealThread,0,FALSE,DUPLICATE_SAME_ACCESS);(HANDLE) _beginthreadex(NULL, 0, ThreadFunc2, hTagrealThread, 0, NULL);while(1){printf("111\n");Sleep(1000);}return 0;}unsigned int WINAPI ThreadFunc2(LPVOID lp){HANDLE hThread = (HANDLE)lp;Sleep(5000);TerminateThread(hThread,0);//必须要关闭句柄CloseHandle(hThread);return 0;}int main(){HANDLE hThread1 =(HANDLE) _beginthreadex(NULL, 0, ThreadFunc1, NULL, 0, NULL );WaitForSingleObject(hThread1,INFINITE);CloseHandle(hThread1);printf("main exit\n");system("pause");return 0;}线程2函数,杀死的是线程1 最后要关闭线程1的线程内核对象复制一个句柄后,线程内核对象引用计数会加1
相关文章推荐
- windows核心编程---用内核对象进行线程同步
- Windows 核心编程内核对象同步之-Waitable timer
- Windows编程那些事----线程与内核对象同步之【信标对象】
- Windows编程--线程和内核对象的同步-事件内核对象
- windows核心编程--内核对象
- Windows核心编程_3.内核对象
- Windows核心编程学习八:事件内核对象
- windows核心编程-事件内核对象
- Windows编程--线程和内核对象的同步-等待定时器内核对象
- windows核心编程心解--内核对象
- Windows编程-- 线程和内核对象的同步 - 互斥对象内核对象
- Windows编程--线程和内核对象的同步-信标(信号量)内核对象
- Windows核心编程--用内核对象进行线程同步(一)
- WINDOWS核心编程学习1------内核对象
- Windows核心编程学习九:利用内核对象进行线程同步
- windows 核心编程之9 内核对象用于线程同步
- 【Windows 核心编程】Windows 核心编程 -- 内核对象
- 读Windows核心编程-3-内核对象
- Windows-核心编程-09-如何用内核对象进行线程同步-事件内核对象
- Windows-核心编程-09-如何用内核对象进行线程同步-信号内核对象