十七
十七
Published on 2025-07-31 / 21 Visits
0
0

windows进程与线程

1. 进程相关API

线程定义

  • 线程是进程中的执行单元

  • 每个进程至少有一个线程(主线程)

  • 线程共享进程的资源,但拥有独立的执行上下文

GetVersionEx

函数介绍

GetVersionEx 是一个用于获取操作系统版本信息的函数。它填充一个结构体,其中包含有关当前操作系统版本的信息。

函数原型

BOOL GetVersionEx(
  LPOSVERSIONINFO lpVersionInfo
);

参数介绍

  • lpVersionInfo

    • 类型:LPOSVERSIONINFO

    • 指向一个 OSVERSIONINFOOSVERSIONINFOEX 结构的指针,用于接收操作系统版本信息。

返回值

  • 成功:返回值为非零值。

  • 失败:返回值为零。可以通过调用 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);  // 等待工作项完成
}


Comment