1. 进程相关API
线程定义:
线程是进程中的执行单元
每个进程至少有一个线程(主线程)
线程共享进程的资源,但拥有独立的执行上下文
GetVersionEx
函数介绍
GetVersionEx 是一个用于获取操作系统版本信息的函数。它填充一个结构体,其中包含有关当前操作系统版本的信息。
函数原型
BOOL GetVersionEx(
LPOSVERSIONINFO lpVersionInfo
);参数介绍
lpVersionInfo类型:
LPOSVERSIONINFO指向一个
OSVERSIONINFO或OSVERSIONINFOEX结构的指针,用于接收操作系统版本信息。
返回值
成功:返回值为非零值。
失败:返回值为零。可以通过调用
GetLastError获取错误代码。
示例代码
#include <windows.h>
#include <stdio.h>
int main() {
OSVERSIONINFO osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx(&osvi)) {
printf("Major Version: %d\n", osvi.dwMajorVersion);
printf("Minor Version: %d\n", osvi.dwMinorVersion);
printf("Build Number: %d\n", osvi.dwBuildNumber);
printf("Platform ID: %d\n", osvi.dwPlatformId);
printf("Service Pack: %s\n", osvi.szCSDVersion);
} else {
printf("Failed to get version information. Error: %d\n", GetLastError());
}
return 0;
}CreateProcess
函数介绍
CreateProcess 用于创建一个新的进程及其主线程。它可以启动一个程序或命令,并指定程序的运行方式。
函数原型
BOOL CreateProcess(
LPCSTR lpApplicationName,
LPSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
);参数介绍
lpApplicationName:指向要运行的模块的名称。lpCommandLine:指向命令行字符串。lpProcessAttributes:指向进程安全属性。lpThreadAttributes:指向线程安全属性。bInheritHandles:是否继承句柄。dwCreationFlags:创建标志。lpEnvironment:指向新环境块。lpCurrentDirectory:指向当前目录。lpStartupInfo:指向启动信息。lpProcessInformation:指向返回的进程和线程信息。
返回值
成功:返回值为非零值。
失败:返回值为零。可以通过调用
GetLastError获取错误代码。
示例代码
#include <windows.h>
#include <stdio.h>
int main() {
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
if (!CreateProcess(
NULL, // 指向可执行文件的名称
"notepad.exe", // 指向命令行字符串
NULL, // 指向进程安全属性
NULL, // 指向线程安全属性
FALSE, // 是否继承句柄
0, // 创建标志
NULL, // 指向新环境块
NULL, // 指向当前目录
&si, // 指向启动信息
&pi // 指向返回的进程和线程信息
)) {
printf("CreateProcess failed. Error: %d\n", GetLastError());
return 1;
}
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 0;
}ShellExecuteEx
函数介绍
ShellExecuteEx 是一个功能强大的函数,用于执行各种与文件或文件夹相关的操作,例如启动程序、打开文件、打印文件、浏览文件夹等。
函数原型
BOOL ShellExecuteEx(
LPSHELLEXECUTEINFO lpExecInfo
);参数介绍
lpExecInfo:指向一个SHELLEXECUTEINFO结构的指针,包含执行操作所需的所有信息。
返回值
成功:返回值为非零值。
失败:返回值为零。可以通过调用
GetLastError获取错误代码。
示例代码
#include <windows.h>
#include <shellapi.h>
#include <stdio.h>
int main() {
SHELLEXECUTEINFO sei = {0};
sei.cbSize = sizeof(SHELLEXECUTEINFO);
sei.fMask = SEE_MASK_NOCLOSEPROCESS;
sei.lpVerb = "open";
sei.lpFile = "notepad.exe";
sei.lpParameters = NULL;
sei.lpDirectory = NULL;
sei.nShow = SW_SHOWNORMAL;
if (!ShellExecuteEx(&sei)) {
printf("ShellExecuteEx failed. Error: %d\n", GetLastError());
return 1;
}
WaitForSingleObject(sei.hProcess, INFINITE);
CloseHandle(sei.hProcess);
return 0;
}GetProcessElevation
函数介绍
GetProcessElevation 用于检测当前进程的权限提升状态,判断进程是否以管理员权限运行以及其令牌的提升类型。
函数原型
BOOL GetProcessElevation(TOKEN_ELEVATION_TYPE* pElevationType, BOOL* pIsAdmin);参数介绍
pElevationType:指向TOKEN_ELEVATION_TYPE枚举类型的指针,用于接收当前进程的令牌提升类型。pIsAdmin:指向布尔值的指针,用于接收当前进程是否以管理员身份运行。
返回值
成功:返回值为非零值。
失败:返回值为零。
示例代码
#include <windows.h>
#include <stdio.h>
BOOL GetProcessElevation(TOKEN_ELEVATION_TYPE* pElevationType, BOOL* pIsAdmin) {
HANDLE hToken = NULL;
DWORD dwSize;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
return FALSE;
}
BOOL bResult = FALSE;
if (GetTokenInformation(hToken, TokenElevationType, pElevationType, sizeof(TOKEN_ELEVATION_TYPE), &dwSize)) {
*pIsAdmin = IsUserAnAdmin();
bResult = TRUE;
}
CloseHandle(hToken);
return bResult;
}
int main() {
TOKEN_ELEVATION_TYPE Type;
BOOL IsAdmin;
if (GetProcessElevation(&Type, &IsAdmin)) {
printf("Elevation Type: %d\n", Type);
if (IsAdmin) {
printf("Running as Admin\n");
} else {
printf("Running as Normal User\n");
}
} else {
printf("Failed to get elevation information\n");
}
return 0;
}CreateThread
函数介绍
CreateThread 用于创建一个新线程。它可以启动一个线程来执行指定的函数,通常用于多线程编程。
函数原型
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);参数介绍
lpThreadAttributes:指向线程安全属性。dwStackSize:初始堆栈大小。lpStartAddress:指向线程函数的指针。lpParameter:传递给线程函数的参数。dwCreationFlags:创建标志。lpThreadId:指向线程标识符的指针。
返回值
成功:返回新线程的句柄。
失败:返回
NULL。可以通过调用GetLastError获取错误代码。
示例代码
#include <windows.h>
#include <stdio.h>
DWORD WINAPI ThreadFunc(LPVOID lpParam) {
int count = (int)lpParam;
for (int i = 0; i < count; i++) {
printf("Thread: %d\n", i);
}
return 0;
}
int main() {
HANDLE hThread;
DWORD dwThreadId;
int threadCount = 5;
hThread = CreateThread(
NULL, // 安全属性
0, // 堆栈大小
ThreadFunc, // 线程函数
(LPVOID)threadCount, // 传递给线程函数的参数
0, // 创建标志
&dwThreadId // 线程标识符
);
if (hThread == NULL) {
printf("CreateThread failed. Error: %d\n", GetLastError());
return 1;
}
printf("Thread created with ID: %d\n", dwThreadId);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
return 0;
}2. 线程同步API
互斥量 (Mutex)
// 创建互斥量
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes,
BOOL bInitialOwner, // 初始拥有者
LPCTSTR lpName // 名称
);
HANDLE OpenMutex(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCTSTR lpName
);
// 示例
HANDLE g_hMutex;
void MutexExample() {
g_hMutex = CreateMutex(NULL, FALSE, NULL);
HANDLE threads[2];
for (int i = 0; i < 2; i++) {
threads[i] = CreateThread(NULL, 0, ThreadWithMutex, (LPVOID)i, 0, NULL);
}
WaitForMultipleObjects(2, threads, TRUE, INFINITE);
CloseHandle(g_hMutex);
}
DWORD WINAPI ThreadWithMutex(LPVOID lpParam) {
int id = (int)lpParam;
WaitForSingleObject(g_hMutex, INFINITE); // 等待互斥量
// 临界区代码
printf("线程 %d 进入临界区\n", id);
Sleep(1000);
printf("线程 %d 离开临界区\n", id);
ReleaseMutex(g_hMutex); // 释放互斥量
return 0;
}事件 (Event)
// 创建事件
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset, // 手动重置/自动重置
BOOL bInitialState, // 初始状态
LPCTSTR lpName
);
// 设置事件为有信号状态
BOOL SetEvent(HANDLE hEvent);
// 重置事件为无信号状态
BOOL ResetEvent(HANDLE hEvent);
// 示例
HANDLE g_hEvent;
void EventExample() {
g_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); // 手动重置,初始无信号
HANDLE hThread = CreateThread(NULL, 0, WaitingThread, NULL, 0, NULL);
Sleep(2000);
printf("主线程设置事件\n");
SetEvent(g_hEvent); // 触发事件
WaitForSingleObject(hThread, INFINITE);
CloseHandle(g_hEvent);
CloseHandle(hThread);
}
DWORD WINAPI WaitingThread(LPVOID lpParam) {
printf("等待线程等待事件...\n");
WaitForSingleObject(g_hEvent, INFINITE);
printf("等待线程收到事件信号\n");
return 0;
}信号量 (Semaphore)
// 创建信号量
HANDLE CreateSemaphore(
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
LONG lInitialCount, // 初始计数
LONG lMaximumCount, // 最大计数
LPCTSTR lpName
);
// 释放信号量
BOOL ReleaseSemaphore(
HANDLE hSemaphore,
LONG lReleaseCount, // 释放数量
LPLONG lpPreviousCount // 先前计数
);
// 示例
HANDLE g_hSemaphore;
void SemaphoreExample() {
g_hSemaphore = CreateSemaphore(NULL, 3, 3, NULL); // 最多3个线程同时访问
HANDLE threads[5];
for (int i = 0; i < 5; i++) {
threads[i] = CreateThread(NULL, 0, ThreadWithSemaphore, (LPVOID)i, 0, NULL);
}
WaitForMultipleObjects(5, threads, TRUE, INFINITE);
CloseHandle(g_hSemaphore);
}
DWORD WINAPI ThreadWithSemaphore(LPVOID lpParam) {
int id = (int)lpParam;
WaitForSingleObject(g_hSemaphore, INFINITE);
printf("线程 %d 获得信号量\n", id);
Sleep(2000);
printf("线程 %d 释放信号量\n", id);
ReleaseSemaphore(g_hSemaphore, 1, NULL);
return 0;
}临界区 (Critical Section)
// 临界区操作
CRITICAL_SECTION g_cs;
void CriticalSectionExample() {
InitializeCriticalSection(&g_cs);
HANDLE threads[3];
for (int i = 0; i < 3; i++) {
threads[i] = CreateThread(NULL, 0, ThreadWithCS, (LPVOID)i, 0, NULL);
}
WaitForMultipleObjects(3, threads, TRUE, INFINITE);
DeleteCriticalSection(&g_cs);
}
DWORD WINAPI ThreadWithCS(LPVOID lpParam) {
int id = (int)lpParam;
EnterCriticalSection(&g_cs);
// 临界区代码
printf("线程 %d 进入临界区\n", id);
Sleep(1000);
printf("线程 %d 离开临界区\n", id);
LeaveCriticalSection(&g_cs);
return 0;
}3. 线程等待函数
单对象等待
DWORD WaitForSingleObject(
HANDLE hHandle, // 对象句柄
DWORD dwMilliseconds // 超时时间
);
// 返回值:
// WAIT_OBJECT_0 - 对象有信号
// WAIT_TIMEOUT - 超时
// WAIT_ABANDONED - 互斥量被放弃
// WAIT_FAILED - 失败多对象等待
DWORD WaitForMultipleObjects(
DWORD nCount, // 对象数量
const HANDLE* lpHandles, // 对象句柄数组
BOOL bWaitAll, // 等待所有/任一
DWORD dwMilliseconds // 超时时间
);可警告等待
DWORD WaitForSingleObjectEx(
HANDLE hHandle,
DWORD dwMilliseconds,
BOOL bAlertable
);
DWORD WaitForMultipleObjectsEx(
DWORD nCount,
const HANDLE* lpHandles,
BOOL bWaitAll,
DWORD dwMilliseconds,
BOOL bAlertable
);4. 线程信息与控制
获取和设置线程信息
// 获取当前线程句柄
HANDLE GetCurrentThread(); // 伪句柄
// 获取当前线程ID
DWORD GetCurrentThreadId();
// 设置线程优先级
BOOL SetThreadPriority(
HANDLE hThread,
int nPriority
);
// 获取线程优先级
int GetThreadPriority(HANDLE hThread);
// 设置线程I/O优先级
BOOL SetThreadPriority(
HANDLE hThread,
DWORD dwPriorityClass
);
// 设置线程处理器亲和性
DWORD_PTR SetThreadAffinityMask(
HANDLE hThread,
DWORD_PTR dwThreadAffinityMask
);线程退出与终止
// 正常退出线程
VOID ExitThread(DWORD dwExitCode);
// 强制终止线程(不推荐)
BOOL TerminateThread(
HANDLE hThread,
DWORD dwExitCode
);
// 获取线程退出代码
BOOL GetExitCodeThread(
HANDLE hThread,
LPDWORD lpExitCode
);5. 线程本地存储 (TLS)
// 动态TLS
DWORD TlsAlloc(); // 分配TLS索引
BOOL TlsSetValue(DWORD dwTlsIndex, LPVOID lpTlsValue);
LPVOID TlsGetValue(DWORD dwTlsIndex);
BOOL TlsFree(DWORD dwTlsIndex);
// 示例
DWORD g_tlsIndex;
void TLSExample() {
g_tlsIndex = TlsAlloc();
HANDLE hThread = CreateThread(NULL, 0, ThreadWithTLS, NULL, 0, NULL);
WaitForSingleObject(hThread, INFINITE);
TlsFree(g_tlsIndex);
CloseHandle(hThread);
}
DWORD WINAPI ThreadWithTLS(LPVOID lpParam) {
int* data = new int(123);
TlsSetValue(g_tlsIndex, data);
int* retrieved = (int*)TlsGetValue(g_tlsIndex);
printf("TLS值: %d\n", *retrieved);
delete data;
return 0;
}6. 线程池API (Vista+)
// 提交工作项到线程池
BOOL TrySubmitThreadpoolCallback(
PTP_SIMPLE_CALLBACK pfnCallback,
PVOID pvContext,
PTP_CALLBACK_ENVIRON pcbe
);
// 等待线程池工作项
VOID WaitForThreadpoolWorkCallbacks(
PTP_WORK pWork,
BOOL bCancelPending
);
// 示例
VOID CALLBACK SimpleCallback(
PTP_CALLBACK_INSTANCE Instance,
PVOID Context
) {
int* data = (int*)Context;
printf("线程池工作项执行: %d\n", *data);
}
void ThreadPoolExample() {
int data = 42;
// 简单线程池使用
TrySubmitThreadpoolCallback(SimpleCallback, &data, NULL);
Sleep(1000); // 等待工作项完成
}