创建线程
HANDLE hThread1 = ::CreateThread(NULL, 0, ThreadProc1, &a, 0, NULL);
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, // 安全属性 通常为NULL
SIZE_T dwStackSize, // 参数用于设定线程可以将多少地址空间用于它自己的堆栈
// 每个线程拥有它自己的堆栈
LPTHREAD_START_ROUTINE lpStartAddress, // 参数用于指明想要新线程执行的线程函数的地址
LPVOID lpParameter, // 线程函数的参数
// 在线程启动执行时将该参数传递给线程函数
// 既可以是数字,也可以是指向包含其他信息的一个数据结构的指针
DWORD dwCreationFlags, // 0 创建完毕立即调度 CREATE_SUSPENDED创建后挂起
LPDWORD lpThreadId // 线程ID
);
1. 返回值:线程句柄,是void *类型
2. 线程句柄与线程ID的区别:
线程是由Windows内核负责创建与管理的,句柄相当于一个令牌,有了这个令牌就可以使用线程对象。
线程ID是身份证,唯一的,系统进行线程调度的时候要使用的。
线程操作函数:
1. 挂起线程:
::SuspendThread(hThread);
2. 恢复线程
::ResumeThread(hThread);
3. 终止线程:
方式一:
::ExitThread(DWORD dwExitCode); //同步的,之后的代码就不会执行了。
方式二:
线程函数返回
方式三:
::TerminateThread(hThread,2); //异步的,会使用一个新的线程。
::WaitForSingleObject(hThread,INFINITE); //正因为是异步的,所以之后的代码也有可能会执行,所以要进行阻塞。
线程结束后堆栈不会被清理,因为其他线程可能会使用到。
4. 判断线程是否结束
BOOL GetExitCodeThread(HANDLE hThread, LPDWORD lpExitCode);
_CONTEXT结构体
在时间片切换时将寄存器中的值保存到_CONTEXT结构体中。
typedef struct _CONTEXT {
//
// The flags values within this flag control the contents of
// a CONTEXT record.
//
// If the context record is used as an input parameter, then
// for each portion of the context record controlled by a flag
// whose value is set, it is assumed that that portion of the
// context record contains valid context. If the context record
// is being used to modify a threads context, then only that
// portion of the threads context will be modified.
//
// If the context record is used as an IN OUT parameter to capture
// the context of a thread, then only those portions of the thread's
// context corresponding to set flags will be returned.
//
// The context record is never used as an OUT only parameter.
//
DWORD ContextFlags;
//
// This section is specified/returned if CONTEXT_DEBUG_REGISTERS is
// set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT
// included in CONTEXT_FULL.
//
DWORD Dr0;
DWORD Dr1;
DWORD Dr2;
DWORD Dr3;
DWORD Dr6;
DWORD Dr7;
//
// This section is specified/returned if the
// ContextFlags word contians the flag CONTEXT_FLOATING_POINT.
//
FLOATING_SAVE_AREA FloatSave;
//
// This section is specified/returned if the
// ContextFlags word contians the flag CONTEXT_SEGMENTS.
//
DWORD SegGs;
DWORD SegFs;
DWORD SegEs;
DWORD SegDs;
//
// This section is specified/returned if the
// ContextFlags word contians the flag CONTEXT_INTEGER.
//
DWORD Edi;
DWORD Esi;
DWORD Ebx;
DWORD Edx;
DWORD Ecx;
DWORD Eax;
//
// This section is specified/returned if the
// ContextFlags word contians the flag CONTEXT_CONTROL.
//
DWORD Ebp;
DWORD Eip;
DWORD SegCs; // MUST BE SANITIZED
DWORD EFlags; // MUST BE SANITIZED
DWORD Esp;
DWORD SegSs;
//
// This section is specified/returned if the ContextFlags word
// contains the flag CONTEXT_EXTENDED_REGISTERS.
// The format and contexts are processor specific
//
BYTE ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];
} CONTEXT;
//1. 挂起线程
SuspendThread(线程句柄); //这样获取的CONTEXT 才有意义。
CONTEXT context
//2. 设置要获取的类型
context.ContextFlags = CONTEXT_CONTROL; //CONTEXT_FULL是获取除Debug寄存器外所有的,其他单独或取的在文档中每类寄存器前都有介绍。如果需要全部获取 CONTEXT_FULL | Debug寄存器的标志 即可。
//3. 获取
BOOL ok = ::GetThreadContext(hThread,&context);
//4. 设置
context.Eip = 0x401000;
SetThreadContext(hThread,&context);

本文介绍了Windows系统中创建线程的过程,强调线程句柄与线程ID的区别。详细阐述了线程的挂起、恢复、终止以及判断线程是否结束的方法,并讨论了使用_CONTEXT结构体在时间片切换时保存寄存器值的重要性。
327

被折叠的 条评论
为什么被折叠?



