来源:微信公众号「编程学习基地」
进程线程
Process进程
在windows系统中,进程就是一个正在运行的程序,他拥有自己的虚拟地址空间,拥有自己的代码,数据和其他系统资源,一个进程也包含了一个或多个运行在此进程中的线程
CreateProcess函数
BOOL CreateProcess
(
LPCTSTR lpApplicationName, //可执行文件名称
LPTSTR lpCommandLine, //指定了要传递给执行函数的参数
LPSECURITY_ATTRIBUTES lpProcessAttributes,//NULL
LPSECURITY_ATTRIBUTES lpThreadAttributes, //NULL
BOOL bInheritHandles, //指定是否可以被新进程继承
DWORD dwCreationFlags, //进程优先级
LPVOID lpEnvironment, //新进程使用的环境变量
LPCTSTR lpCurrentDirectory, //新进程当前目录
LPSTARTUPINFO lpStartupInfo, //主窗口的位置,大小和标准句柄
LPPROCESS_INFORMATION lpProcessInformation //返回进程的标志信息
);
进程STARTUPINFO
typedef struct _STARTUPINFO
{
DWORD cb; //包含STARTUPINFO结构中的字节数,将cb初始化为sizeof(STARTUPINFO)
PSTR lpReserved; //保留。必须初始化为NULL
PSTR lpDesktop; //指定桌面名称
PSTR lpTitle; //控制台应用程序标题
DWORD dwX; //用于设定应用程序窗口相对屏幕左上角位置的x 坐标(以像素为单位)。
DWORD dwY; //对于GUI processes用CW_USEDEFAULT作为CreateWindow的x、y参数
DWORD dwXSize; //用于设定应用程序窗口的宽度(以像素为单位)
DWORD dwYSize;
DWORD dwXCountChars;//控制台窗口的行数
DWORD dwYCountChars;
DWORD dwFillAttribute; //用于设定子应用程序的控制台窗口使用的文本和背景颜色
DWORD dwFlags; //请参见下一段和表4-7 的说明
WORD wShowWindow; //窗口的风格
WORD cbReserved2; //保留。必须被初始化为0
PBYTE lpReserved2; //保留。必须被初始化为NULL
HANDLE hStdInput; //用于设定供控制台输入和输出用的缓存的句柄。
HANDLE hStdOutput;
HANDLE hStdError;
} STARTUPINFO, *LPSTARTUPINFO;
获取当前进程的STARTUPINFO结构:GetStartupInfo();
简单使用
#include<Windows.h>
#include<stdio.h>
int main()
{
STARTUPINFO si = {
sizeof(si) };
PROCESS_INFORMATION pi;
CreateProcess("C:\\Program Files\\Notepad++\\notepad++.exe",//需要创建的进程是谁(路径文件名)
nullptr,//命令行参数
nullptr,//是否被子进程所继承
nullptr,//是否被子线程所继承
false,//新创建的进程是否从调用线程处继承了句柄
0,//创建标志
nullptr,//新进程的环境块
nullptr,//子进程的工作路径
&si,
&pi);
printf("新的进程Id:%d\n", pi.dwProcessId);
return 0;
}
程序运行会打开电脑C盘C:\\Program Files\\Notepad++\\notepad++.exe
路径下的NotePad程序
#include<Windows.h>
int main()
{
STARTUPINFO si = {
sizeof(si) };
PROCESS_INFORMATION pi;
char* Command = "notepad";
CreateProcess(NULL, Command, NULL, NULL, FALSE, NULL, NULL, NULL, &si, &pi);
return 0;
}
程序运行创建进程,打开记事本,这是通过参数打开的
结束进程的方法
- 该进程的主线程的入口函数返回(等同于你结束创建的进程)
- 在父进程的某个线程处调用TerminateProcess去结束一个子进程
- 在当前进程的某个位置调用ExitProcess去结束自己
#include<Windows.h>
#include<stdio.h>
int main()
{
STARTUPINFO si = {
sizeof(si) };
PROCESS_INFORMATION pi;
CreateProcess("C:\\Program Files\\Notepad++\\notepad++.exe",//需要创建的进程是谁(路径文件名)
nullptr,//命令行参数
nullptr,//是否被子进程所继承
nullptr,//是否被子线程所继承
false,//新创建的进程是否从调用线程处继承了句柄
0,//创建标志
nullptr,//新进程的环境块
nullptr,//子进程的工作路径
&si,
&pi);
printf("新的进程Id:%d\n", pi.dwProcessId);
HANDLE hinst = pi.hProcess; //获取该进程的示例句柄
Sleep(3000);
//终止当前进程
//第一种方法就是手动关掉notepad
TerminateProcess(hinst, NULL);
//ExitProcess(0);
CloseHandle(hinst);
return 0;
}
Thread线程
CreateThread函数
HANDLE WINAPI CreateThread(
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ SIZE_T dwStackSize,
_In_ LPTHREAD_START_ROUTINE lpStartAddress,
_In_opt_ LPVOID lpParameter,
_In_ DWORD dwCreationFlags,
_Out_opt_ LPDWORD lpThreadId
);
参数说明:
- 第一个参数
lpThreadAttributes
表示线程内核对象的安全属性,一般传入NULL表示使用默认设置。 - 第二个参数
dwStackSize
表示线程栈空间大小。传入0表示使用默认大小(1MB)。 - 第三个参数
lpStartAddress
表示新线程所执行的线程函数地址,多个线程可以使用同一个函数地址。 - 第四个参数
lpParameter
是传给线程函数的参数。 - 第五个参数
dwCreationFlags
指定额外的标志来控制线程的创建,为0表示线程创建之后立即就可以进行调度,如果为CREATE_SUSPENDED则表示线程创建后暂停运行,这样它就无法调度,直到调用ResumeThread()。 - 第六个参数
lpThreadId
将返回线程的ID号,传入NULL表示不需要返回该线程ID号。
返回值
线程创建成功返回新线程的句柄,失败返回NULL
WaitForSingleObject函数
DWORD WINAPI WaitForSingleObject(
_In_ HANDLE hHandle,
_In_ DWORD dwMilliseconds
);
第一个参数 _In_ HANDLE hHandle
是对象的句柄,可以是以下几种:
第二个参数 _In_ DWORD dwMilliseconds
为等待时间,以毫秒为单位。
参数dwMilliseconds有两个具有特殊意义的值:0和INFINITE。
若为0,则该函数立即返回;
若为INFINITE,则线程一直被挂起,直到hHandle所指向的对象变为有信号状态时为止。
#include <stdio.h>
#include <windows.h>
// 线程函数
DWORD WINAPI ThreadProc(LPVOID lpParam)
{
for (int i = 0; i < 10; i++)
{
printf("I am Thread :%d\trun\n", GetCurrentThreadId());
}
return 0;
}
int main(int argc, char* argv[])
{
HANDLE hThread;
DWORD dwThreadId;
// 创建一个线程
hThread = CreateThread(
NULL, // 默认安全属性
NULL, // 默认堆栈大小
ThreadProc, // 线程入口地址(执行线程的函数)
NULL, // 传给函数的参数
0, // 指定线程立即运行
&dwThreadId); // 返回线程的ID号
printf(" Now another thread has been created. ID = %d \n", dwThreadId);
// 等待新线程运行结束
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
return 0;
}