进程的来龙去脉

原创 2013年12月06日 11:14:34

进程的创建是一件相当复杂的事情,其中要包涵很多工作,我们可以通过反汇编来看看CreateProcess()。为了启动一个进程 可有以下几步:

1.可执行文件必须被以FILE_EXECYTE存取方式打开。

2.可执行映像必须被转载进RAM。

3.必须建立进程执行对象(EPROCESS、KPROCESS和PEB结构)。

4.必须为新建进程分配地址空间。

5.必须建立进程的主线程的线程执行对象(ETHREAD、KTHREAD和TEBstructures)。

6.必须为主线程分配堆栈。

7.必须建立进程的主线程的执行上下文。

8.必须通知Win32子系统有关该进程的创建情况。

下面我们来看一看CreateProcess()函数的一些参数

WINBASEAPI
BOOL
WINAPI
CreateProcessA(
    __in_opt       LPCSTR lpApplicationName, //可执行文件的文件名
    __inout_opt LPSTR lpCommandLine, //命令行参数
    __in_opt       LPSECURITY_ATTRIBUTES lpProcessAttributes, //进程的安全属性
    __in_opt       LPSECURITY_ATTRIBUTES lpThreadAttributes, //线程的安全属性
    __in       BOOL bInheritHandles, // 当前进程内的句柄可不可以被子进程继承
    __in       DWORD dwCreationFlags, //这个一会再说
    __in_opt    LPVOID lpEnvironment,  //  是否使用本进程的环境变量,默认为NULL
    __in_opt    LPCSTR lpCurrentDirectory,  // 是否使用本进程的驱动器和目录,默认为NULL
    __in       LPSTARTUPINFOA lpStartupInfo, // 这里边是一个STARTUPINFO结构体的对象
    __out       LPPROCESS_INFORMATION lpProcessInformation // 这里边是一个PROCESS_INFORMATION结构体的对象
    );

STARTUPINFO结构体的具体内容如下:

typedef struct _STARTUPINFO {

    DWORD   cb; // 是本结构的长度 ,一般情况下设为{ sizeof(STARTUOINFO) },为什么呢?原因是因为不同版本的此结构体他们的成员是不一定的
    LPSTR   lpReserved; //  被保留的字段
    LPSTR   lpDesktop; // 指定桌面的名称
    LPSTR   lpTitle; // 控制台应用程序的使用,指定控制台窗口标题

// 指定新创建窗口的位置坐标 和  大小信息
    DWORD   dwX;
    DWORD   dwY;
    DWORD   dwXSize;
    DWORD   dwYSize;


    DWORD   dwXCountChars; // 控制台程序使用,指定控制台窗口的行数
    DWORD   dwYCountChars; // 
    DWORD   dwFillAttribute; // 控制台程序使用,指定控制台窗口的的背景色
    DWORD   dwFlags; // 标志 它的值决定了STARTUPINFO结构中哪个成员是有效的
    WORD    wShowWindow; // 窗口的显示方式
    WORD    cbReserved2; // 
    LPBYTE  lpReserved2; // 
    HANDLE  hStdInput; // 控制台程序使用,几个标准句柄
    HANDLE  hStdOutput; // 
    HANDLE  hStdError; // 
} STARTUPINFOA, *LPSTARTUPINFOA;

PROCESS_INFORMATION结构体的具体内容如下:

typedef struct _PROCESS_INFORMATION {
    HANDLE  hProcess; // 新建进程的内核句柄
    HANDLE  hThread; // 新建进程中主线程的内核句柄
    DWORD  dwProcessId; // 新建进程的ID
    DWORD  dwThreadId; // 新建进程的主线程ID
} PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION;

下面贴出一段代码来看看创建进程的实例

#include "windows.h"
#include "iostream"
using namespace std;

int main()
{
	char szCommandLine[]="cmd";
	STARTUPINFO si={sizeof(si)};
	PROCESS_INFORMATION pi;
	si.dwFlags=STARTF_USESHOWWINDOW;
	si.wShowWindow=TRUE;

	BOOL bRet=::CreateProcess(	NULL,
					szCommandLine,
					NULL,
					NULL,
					FALSE,
					CREATE_NEW_CONSOLE,
					NULL,
					NULL,
					&si,
					&pi
				);
	if(bRet)
	{
		::CloseHandle(pi.hThread);
		::CloseHandle(pi.hProcess);
		printf("ProcessID %d \n",pi.dwProcessId);
		printf("ThreadID %d \n",pi.dwThreadId);

	}
	return 0;
}

从CreateProcess()函数的最后两个参数的样子可以看出,&对象,一定是CreateProcess()把一些东西写进对象相应的结构中去了。

下面再来看一小段程序,它主要是用用来枚举系统中正在运行的进程的一些相关的信息

	#include "windows.h"
	#include "tlhelp32.h"
	
	int main()
	{
		
		HANDLE hProcessSnap = NULL;
		PROCESSENTRY32 pe32 = {0};
		//获得句柄
		hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
		if(hProcessSnap == (HANDLE)-1)
		{
			printf("\nCreateToolhelp32Snapshot()failed:%d",GetLastError());
			return;
		}
		pe32.dwSize = sizeof(PROCESSENTRY32);
		
		//列举所有进程名称
		if (Process32First(hProcessSnap, &pe32))
		{
			do
			{
				printf("进程名称 %s 进程ID %u \n",pe32.szExeFile,pe32.th32ProcessID);
			}
			while (Process32Next(hProcessSnap, &pe32));//直到列举完毕
		}
		else
		{
			printf("\nProcess32Firstt() failed:%d",GetLastError());
		}
		//关闭句柄
		CloseHandle (hProcessSnap); 
		return 0;
	}

从倒数第12行可以看出,我们是从pe32对象的th32ProcessID成员中获得到当前系统正在运行的进程的一些信息的。当然了在整个的遍历的过程中,是通过

BOOL WINAPI Process32Next(
__in     HANDLE hSnapshot,
__out    LPPROCESSENTRY32 lppe
);
函数来进行遍历的,当然了他遍历的是系统的快照,其中第一个参数便是一个系统快照的句柄,所以程序的最初是要创建系统快照,目的就是把当前系统内正在运行的进程通过快照捕获下来一份。

我们不得不看看PROCESSENTRY32是一个什么东东,他的内部都有哪些成员,这些成员都存储了什么东西。

typedef struct tagPROCESSENTRY32
{
    DWORD   dwSize; // 结构的长度,不需预先设置
    DWORD   cntUsage; // 进程的引用计数
    DWORD   th32ProcessID;          // this process
    ULONG_PTR th32DefaultHeapID; //进程默认堆的ID
    DWORD   th32ModuleID;           // associated exe进程模块的ID
    DWORD   cntThreads; // 进程创建的线程数
    DWORD   th32ParentProcessID;    // this process's parent process 进程的父线程ID
    LONG    pcPriClassBase;         // Base priority of process's threads 进程创建的线程的基本优先级
    DWORD   dwFlags; // 内部使用
    CHAR    szExeFile[MAX_PATH];    // Path 进程对应的可执行文件名
} PROCESSENTRY32;




未完待续。。。。

版权声明:开放

相关文章推荐

MFC来龙去脉

  • 2012年10月13日 13:20
  • 25KB
  • 下载

X86指令编码的来龙去脉

  • 2012年01月17日 15:25
  • 325KB
  • 下载

ARM异常向量表中LDR指令、LDR伪指令的来龙去脉

1、问题引出 在ARM开发中,异常向量表(或者称为中断向量表)处在一个关键的位置,因为它控制了ARM芯片复位时的跳转地址,也即是调到哪里去执行启动代码。一般来说,异常向量表的形式如下 Vector: ...

MFC源码剖析之--MFC来龙去脉

  • 2009年02月20日 18:32
  • 220KB
  • 下载

原始需求的来龙去脉和核心要求

在软件工程术语中,“原始需求”并不是个常见的说法。 这个“原始需求”的提法是本博主自己提出来的。它的起源与CMM有关,CMM中,有“客户需求”的说法。 当时没有直接采用“客户需求”而采用“原始...

IEEE802_的来龙去脉

  • 2011年04月11日 09:28
  • 51KB
  • 下载

QQ产品经理解读QQ圈子的来龙去脉

  • 2013年09月18日 16:21
  • 641KB
  • 下载

回车 换行 0x0D 0x0A CR LF \r \n的来龙去脉

原文地址:http://www.crifan.com/detailed_carriage_return_0x0d_0x0a_cr_lf__r__n_the_context/ ...

html5的来龙去脉

  • 2013年03月27日 12:52
  • 431KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:进程的来龙去脉
举报原因:
原因补充:

(最多只允许输入30个字)