进程相关API
1.PID 与 句柄
上节课,我们知道.
每一个进程 都有自己的 私有的一张 句柄表.
然而我们的操作系统(Windows)也有一张句柄表 , 叫做全局句柄表 这张表 包含了所有的进程 线程 事件 等
接下来分析 我们创建子进程返回来的Process_Information
typedef struct _PROCESS_INFORMATION {
HANDLE hProcess; //本身进程的句柄表编号
HANDLE hThread;
DWORD dwProcessId; //操作系统全局句柄表的编号 PID
DWORD dwThreadId;
} PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION;
//也就意味着
//hProcess是局部的,仅仅针对这个进程有效
//dwProcessId ,dwThreadId 是全局的,是通过操作系统管理的,是唯一的 .不可能出现相同的PID TID
//但唯一不代表不变,0这编号的进程没了, 那么这0编号会被回收且分给新的进程
论证 PID 是操作系统的全局句柄 和 ProcessHandle 是进程本身局部的句柄
打开一个进程,该进程的PID 和 ProcessHandle 并且保持进程运行
bool CreateChildProcess(TCHAR* szChildProcessName,TCHAR* szCommandline){
SECURITY_ATTRIBUTES sa;
STARTUPINFO si;//IN 给你的子进程赋属性 一般全为空
PROCESS_INFORMATION pi;//OUT 创建进程成功后,返回的子进程标识
//#define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length))
ZeroMemory(&si,sizeof(si));
ZeroMemory(&pi,sizeof(pi));
if (!CreateProcess(
szChildProcessName, //对象名称
szCommandline, //命令行参数
NULL, //不继承进程句柄
NULL, //不继承线程句柄
FALSE, //不继承句柄
0, //没有创建标志
NULL, //使用父进程环境变量
NULL, //使用父进程目录作为当前目录,可以自己设置目录
&si, //caller 填写的信息
&pi //out 创建的子进程的信息
))
{
printf("Last error:%d \n",GetLastError());
}
//打印子进程的相关信息
printf("进程句柄:%d ,线程句柄:%x 进程ID:%x,线程ID:%x",pi.hProcess,pi.hThread,pi.dwProcessId,pi.dwThreadId);
//通过子进程句柄对子进程控制
//SuspendThread(pi.hThread);//线程假死(僵尸状态?)
//ResumeThread(pi.hThread);//复活线程
//释放子进程句柄
CloseHandle(pi.hProcess); //对于线程的CloseHandle,不仅线程内核对象的计数器 == 0 ,并且关闭线程(线程关了进程才能关)才能真正
CloseHandle(pi.hThread); //消除线程内核对象
return TRUE;
//CreateProcess()
}
int _tmain(int argc, _TCHAR* argv[])
{
TCHAR szApplicationName[] = TEXT("c://program files//internet explorer//iexplore.exe");
TCHAR szCommand[] = TEXT("http://www.bing.cn/");
CreateChildProcess(szApplicationName,szCommand);
getchar();
return 0;
}
通过另外一个进程,打开这个进程,并通过代码分别使用PID 和 ProcessHandle terminate这个进程
#include "stdafx.h"
#include <windows.h>
//PID = 0x871C
//ProcessHandle = 204 = 0xCC
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hProcess;
DWORD dwProcessID = 0xCC;
hProcess