1、课程目标
- 理解进程和线程的基本概念
- 掌握进程创建和管理API
- 学会多线程编程
- 掌握进程枚举和信息获取
2、名词解释
| 术语 |
英文 |
说明 |
| 进程 |
Process |
程序的运行实例 |
| 线程 |
Thread |
进程中的执行单元 |
| PID |
Process ID |
进程标识符 |
| TID |
Thread ID |
线程标识符 |
| 线程池 |
Thread Pool |
线程的共享池 |
3、使用工具
| 工具 |
用途 |
| Process Explorer |
查看进程详情 |
| Task Manager |
任务管理 |
4、技术原理
4.1、进程 vs 线程
| 特性 |
进程 |
线程 |
| 地址空间 |
独立 |
共享 |
| 资源 |
独立 |
共享 |
| 创建开销 |
大 |
小 |
| 通信 |
IPC |
直接共享内存 |
5、代码实现
5.1、示例1:创建进程
#include <windows.h>
#include <stdio.h>
void CreateNewProcess() {
STARTUPINFO si = {sizeof(si)};
PROCESS_INFORMATION pi = {0};
TCHAR cmdLine[] = TEXT("notepad.exe");
BOOL success = CreateProcess(
NULL, // 应用程序名
cmdLine, // 命令行
NULL, NULL, // 进程/线程安全属性
FALSE, // 不继承句柄
0, // 创建标志
NULL, // 环境变量
NULL, // 当前目录
&si, &pi
);
if (success) {
printf("Process ID: %d\n", pi.dwProcessId);
printf("Thread ID: %d\n", pi.dwThreadId);
// 等待进程结束
WaitForSingleObject(pi.hProcess, INFINITE);
// 获取退出码
DWORD exitCode;
GetExitCodeProcess(pi.hProcess, &exitCode);
printf("Exit code: %d\n", exitCode);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
}
5.2、示例2:创建线程
#include <windows.h>
#include <stdio.h>
typedef struct {
int id;
int count;
} THREAD_PARAM;
DWORD WINAPI ThreadFunc(LPVOID lpParam) {
THREAD_PARAM* param = (THREAD_PARAM*)lpParam;
for (int i = 0; i < param->count; i++) {
printf("Thread %d: %d\n", param->id, i);
Sleep(100);
}
return param->id;
}
void CreateThreadDemo() {
HANDLE threads[3];
THREAD_PARAM params[3];
for (int i = 0; i < 3; i++) {
params[i].id = i;
params[i].count = 5;
threads[i] = CreateThread(
NULL, // 安全属性
0, // 默认栈大小
ThreadFunc, // 线程函数
¶ms[i], // 参数
0, // 立即运行
NULL // 线程ID
);
}
// 等待所有线程完成
WaitForMultipleObjects(3, threads, TRUE, INFINITE);
// 获取线程退出码
for (int i = 0; i < 3; i++) {
DWORD exitCode;
GetExitCodeThread(threads[i], &exitCode);
printf("Thread %d returned: %d\n", i, exitCode);
CloseHandle(threads[i]);
}
}
5.3、示例3:进程枚举
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>
void EnumerateProcesses() {
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE) return;
PROCESSENTRY32 pe = {sizeof(pe)};
if (Process32First(hSnapshot, &pe)) {
do {
printf("PID: %5d Name: %ls\n",
pe.th32ProcessID, pe.szExeFile);
} while (Process32Next(hSnapshot, &pe));
}
CloseHandle(hSnapshot);
}
// 根据名称查找进程
DWORD FindProcessByName(const TCHAR* name) {
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe = {sizeof(pe)};
DWORD pid = 0;
if (Process32First(hSnapshot, &pe)) {
do {
if (_tcsicmp(pe.szExeFile, name) == 0) {
pid = pe.th32ProcessID;
break;
}
} while (Process32Next(hSnapshot, &pe));
}
CloseHandle(hSnapshot);
return pid;
}
5.4、示例4:线程枚举
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>
void EnumerateThreads(DWORD pid) {
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
THREADENTRY32 te = {sizeof(te)};
if (Thread32First(hSnapshot, &te)) {
do {
if (te.th32OwnerProcessID == pid) {
printf(" TID: %d, Priority: %d\n",
te.th32ThreadID, te.tpBasePri);
}
} while (Thread32Next(hSnapshot, &te));
}
CloseHandle(hSnapshot);
}
5.5、示例5:进程信息获取
#include <windows.h>
#include <psapi.h>
#include <stdio.h>
#pragma comment(lib, "psapi.lib")
void GetProcessInfo(DWORD pid) {
HANDLE hProcess = OpenProcess(
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE, pid
);
if (!hProcess) return;
// 获取进程路径
TCHAR path[MAX_PATH];
GetModuleFileNameEx(hProcess, NULL, path, MAX_PATH);
printf("Path: %ls\n", path);
// 获取内存信息
PROCESS_MEMORY_COUNTERS pmc;
GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc));
printf("Working Set: %lld KB\n", pmc.WorkingSetSize / 1024);
CloseHandle(hProcess);
}
6、课后作业
- 基础练习:创建多线程程序计算数学运算
- 进程枚举:实现类似任务管理器的进程列表
- 进程控制:实现进程启动/终止/挂起功能
- 线程池:使用Windows线程池API