线程

函数原型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
HANDLE CreateThread(
//安全描述符
LPSECURITY_ATTRIBUTES lpThreadAttributes,
//堆栈大小
SIZE_T dwStackSize,
//A pointer to the application-defined function to be executed by the thread
LPTHREAD_START_ROUTINE lpStartAddress,
// *void类型的函数参数
__drv_aliasesMem LPVOID lpParameter,
//The flags that control the creation of the thread.
DWORD dwCreationFlags,
//传递线程id
LPDWORD lpThreadId
);

使用C语言创建线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

#include<stdio.h>
#include<Windows.h>
#include<stdlib.h>

DWORD WINAPI myThreadFunc(_In_ LPVOID lpParameter) {

//获取参数
int c = *(int *)lpParameter;

for (int i = 0; i < c; i++) {
printf("%d\n*******\n", i);
Sleep(500);
}
return 0;
}

int main() {

//main函数执行完毕后指针可能会失效,要避免这种情况可以使用全局变量
int count = 10;
DWORD dwResult;

HANDLE hThread = CreateThread(0, NULL, myThreadFunc, (LPVOID)&count, 0, NULL);

for (int i = 0; i < 10; i++) {
printf("%d\n-------\n", i);
Sleep(500);
}

WaitForSingleObject(hThread, INFINITE);
GetExitCodeThread(hThread, &dwResult);
printf("%u", dwResult);

/*
获取线程上下文*/

//SuspendThread(hThread);

//CONTEXT context;
//context.ContextFlags = CONTEXT_INTEGER;
//GetThreadContext(hThread, &context);

//printf("%x,%x", context.Eax, context.Ebx);

//ResumeThread(hThread);

/******************************/
CloseHandle(hThread);

system("pause");
}



线程控制相关API

挂起线程

1
2
3
DWORD SuspendThread(
HANDLE hThread
);

继续执行线程

1
2
3
DWORD ResumeThread(
HANDLE hThread
);

等待单个线程执行

1
2
3
4
5
6
7
8
//Waits until the specified object is in the signaled state or the time-out interval elapses.

//To enter an alertable wait state, use the WaitForSingleObjectEx function. To wait for multiple objects, use WaitForMultipleObjects.

DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);

等待多个线程执行

1
2
3
4
5
6
7
8
9
DWORD WaitForMultipleObjects(
//The number of object handles in the array pointed to by lpHandles
DWORD nCount,
//An array of object handles.
const HANDLE *lpHandles,
BOOL bWaitAll,
DWORD dwMilliseconds
);

获取返回值

返回值只能判断函数是否执行成功,如果线程还在执行则lpExitCode的值为STILL_ACTIVE (259),如果执行完毕则返回线程函数的返回值

1
2
3
4
BOOL GetExitCodeThread(
HANDLE hThread,
LPDWORD lpExitCode
);

获取线程上下文

线程切换时会将寄存器的值保存在CONTEXT结构体中,获取上下文时必须先挂起线程,也可以修改寄存器的值,在调用函数前必须设置CONTEXT结构体中ContextFlags的值

  1. CONTEXT_DEBUG_REGISTERS,查询调式寄存器

  2. CONTEXT_FLOATING_POINT,查询浮点寄存器

  3. CONTEXT_SEGMENTS,查询段寄存器

  4. CONTEXT_INTEGER,查询通用数据寄存器

  5. CONTEXT_CONTROL,查询控制寄存器组

  6. CONTEXT_EXTENDED_REGISTERS,扩展寄存器组

示例片段

1
2
3
4
5
6
7
8
9
10
11
12
SuspendThread(hThread);

CONTEXT context;
context.ContextFlags = CONTEXT_INTEGER;
GetThreadContext(hThread, &context);

/*
如果要修改寄存器可以使用SetThreadContext()*/
printf("%x,%x", context.Eax, context.Ebx);

ResumeThread(hThread);
CloseHandle(hThread);

修改线程上下文

CONTEXT变更后使用此函数修改寄存器。

1
2
3
4
BOOL SetThreadContext(
HANDLE hThread,
const CONTEXT *lpContext
);