Windows编程之进程与线程

Windows编程之进程

现在的Windows操作系统实行的是抢占式多任务的调度方式,意思是操作系统在执行多任务的时候会按照优先级对任务进行排序,重要的任务先执行,但是并不会一直霸占cpu,而是在执行一段时间后操作系统会收回其运行的权利,把它排到后面,然后让其他的任务进行执行,每次执行的任务的时间其实是特别少的,那么对于任务来说,相当于同时在执行所有的任务。

进程这一部分,我们的代码展示了如果获取系统的进程列表,以及删除进程。

代码之进程

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
#include <stdio.h>
#include <Windows.h>
#include <TlHelp32.h>
#include <string.h>


int main(int argc, char* argv[]) {
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE) {
printf("CreateToolhelp32Snapshot error\n");
return 0;
}
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(pe32);
char buff[1024];
BOOL bProcess = Process32First(hProcessSnap, &pe32);
DWORD sogoupid;
while (bProcess) {
wsprintf(buff, "%40s ------------------- %6d\n", pe32.szExeFile, pe32.th32ProcessID);
if (strcmp(pe32.szExeFile, "SogouCloud.exe") == 0) {
sogoupid = pe32.th32ProcessID;
}
printf(buff);
memset(buff, 0x00, 1024);
bProcess = Process32Next(hProcessSnap, &pe32);
}
CloseHandle(hProcessSnap);
printf("SogouCloud's pid is %d\n", sogoupid);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, sogoupid);
if (hProcess == NULL) {
printf("OpenProcess error\n");
return 0;
}
if (TerminateProcess(hProcess, 0)) {
printf("终止进程成功");
}
CloseHandle(hProcess);
return 0;
}

简单的分析一下这段代码,首先在写获取进程的代码之前要#include <TlHelp32.h>,在main函数中,首先利用CreateToolhelp32Snapshot函数来获取进程快照的句柄,该函数的第一个参数是获取进程的类型,我们选择TH32CS_SNAPPROCESS,来获取进程,第二个参数为0,代表获取系统的所有进程。

之后声明一个PROCESSENTRY32结构变量,该变量用于存取获取的进程的各种信息。

利用Process32First函数来取得第一个进程,之后用while循环配合Process32Next函数来获取所有的进程。我们用到的PROCESSENTRY32结构体中的szExeFile是进程的文件名,th32ProcessID是进程的pid。

在之后我们判断进程名是否是SogouCloud.exe来获取其pid,最后利用OpenProcess打开进程获取句柄,配合TerminateProcess函数结束进程。

Windows编程之多线程

对于多线程,没啥好说的,主要是说一下代码中将要出现的临界区。在多线程中的有一个临界区的概念,意思是同一时间内,只能有一个线程访问临界区的资源,这样能够防止对于一个文件来说,多个线程同时修改的的问题。

代码之线程

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
#include <Windows.h>
#include <stdio.h>

HANDLE hFile;
CRITICAL_SECTION cs;

DWORD WINAPI Thread(LPVOID IpParam) {
int n = (int)IpParam;
DWORD dwWrite;
for (int i = 0; i < 100; i++) {
EnterCriticalSection(&cs);
char Data[256] = "Hello, my friend.\r\n";
WriteFile(hFile, &Data, strlen(Data), &dwWrite, NULL);
LeaveCriticalSection(&cs);
}
printf("第%d号线程结束运行\n", n);
return 0;
}

int main(int argc, char* argv[]) {
hFile = CreateFile("C:\\Users\\pino\\source\\repos\\new\\new\\hack.txt", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
printf("CreateFile error\n");
return 0;
}
HANDLE hThread[5];
DWORD dwThreadId;
InitializeCriticalSection(&cs);
for (int i = 0; i < 5; i++) {
hThread[i] = CreateThread(NULL, 0, Thread, (LPVOID)(i+1), 0, &dwThreadId);
printf("第%d号线程创建成功\n", i + 1);
}
WaitForMultipleObjects(5, hThread, TRUE, INFINITE);
DeleteCriticalSection(&cs);
CloseHandle(hFile);
return 0;
}

代码中的临界区的实现需要先定义一个全局的CRITICAL_SECTION结构变量。然后是InitializeCriticalSection -> EnterCriticalSection -> LeaveCriticalSection -> DeleteCriticalSection。

还有就是在定义线程函数的时候统一的格式DWORD WINAPI 函数名(LPVOID 参数)

本文标题:Windows编程之进程与线程

文章作者:Pino-HD

发布时间:2018年09月28日 - 13:09

最后更新:2018年09月28日 - 14:09

原始链接:https://pino-hd.github.io/2018/09/28/Windows编程之进程与线程/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

坚持原创技术分享,您的支持将鼓励我继续创作!