一.什么为进程
进程实体的执行过程叫做进程,通俗的话来讲就是在磁盘上的程序被双击运行起来后,就称为进程。
每个进程中都含有一个主线程,用来真正执行程序。进程是空间的概念,线程是时间的概念。
二.进程的创建过程
打开系统--->双击要运行的程序--->EXE开始执行
步骤一:
当系统启动后,创建一个进程:Explorer.exe也就是桌面进程
步骤二:
当用户双击某个EXE时,Explorer.exe使用CreateProcess()API为该EXE创建进程,即在桌面上双击创建的进程,他们的父进程都是Explorer.exe
- 创建内核对象
用户层 内核层(高2G的内存,每个进程有2^32=4GB的内存空间,低2G由ring3使用,高2G由ring0使用)
CreateProcess NtCreateProcess
句柄表,刚创建的时候为空
如果这个刚刚被创建的进程,里面的线程用创建了其他的内核对象
内核对象的句柄表,为了安全,不会给客户端返回真正的地址,而是一个编号
- 分配4GB的虚拟空间(windows 32位)
- 创建进程的主线程
当进程的空间创建完毕,EXE与导入表中的DLL都正确加载完毕后,会创建一个线程
当线程得到CPU的时候,程序就正开始指向了,EIP的初始值设定为:ImageBase+OEP
当进程创建成功后,会将进程句柄、主线程句柄、进程ID以及主线程ID存储在
typedef struct _PROCESS_INFORMATION { HANDLE hProcess; //进程句柄 HANDLE hThread; //主线程句柄 DWORD dwProcessId; //进程ID DWORD dwThreadId; //线程ID } PROCESS_INFORMATION;
也就是,CreateProcess的最后一个 OUT 参数。到此,整个进程创建结束了
三.CreateProcess()API
BOOL CreateProcess( LPCTSTR lpApplicationName, // name of executable module LPTSTR lpCommandLine, // command line string LPSECURITY_ATTRIBUTES lpProcessAttributes, // SD LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD BOOL bInheritHandles, // handle inheritance option DWORD dwCreationFlags, // creation flags LPVOID lpEnvironment, // new environment block LPCTSTR lpCurrentDirectory, // current directory name LPSTARTUPINFO lpStartupInfo, // startup information LPPROCESS_INFORMATION lpProcessInformation // process information
四.创建进程的几种方式
VOID TestCreateProcessByAPPName() { STARTUPINFO si = {0}; PROCESS_INFORMATION pi; si.cb = sizeof(si); TCHAR szApplicationName[] =TEXT("c://program files//internet explorer//iexplore.exe"); BOOL res = CreateProcess( szApplicationName, NULL, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi); }
VOID TestCreateProcessByCmdline() { STARTUPINFO si = {0}; PROCESS_INFORMATION pi; si.cb = sizeof(si); TCHAR szCmdline[] =TEXT("c://program files//internet explorer//iexplore.exe http://www.ifeng.com"); BOOL res = CreateProcess( NULL, szCmdline, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi); }
VOID TestCreateProcess() { STARTUPINFO si = {0}; PROCESS_INFORMATION pi; si.cb = sizeof(si); TCHAR szCmdline[] =TEXT(" http://www.ifeng.com"); BOOL res = CreateProcess( TEXT("c://program files//internet explorer//iexplore.exe"), szCmdline, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi); }
typedef struct _STARTUPINFO { DWORD cb; PSTR lpReserved; PSTR lpDesktop; PSTR lpTitle; DWORD dwX; DWORD dwY; DWORD dwXSize; DWORD dwYSize; DWORD dwXCountChars; DWORD dwYCountChars; DWORD dwFillAttribute; DWORD dwFlags; WORD wShowWindow; WORD cbReserved2; PBYTE lpReserved2; HANDLE hStdInput; HANDLE hStdOutput; HANDLE hStdError; } STARTUPINFO, *LPSTARTUPINFO; 用来设定要创建的应用程序的属性,比如可以指定新创建的控制台程序的标题等待。 一般情况,只要为第一个成员赋值就可以了. si.cb = sizeof(si);
typedef struct _PROCESS_INFORMATION { HANDLE hProcess; //进程句柄 HANDLE hThread; //主线程句柄 DWORD dwProcessId; //进程ID DWORD dwThreadId; //线程ID } PROCESS_INFORMATION;
五.关于句柄和ID
1、都是系统分配的一个编号,句柄是客户程序使用 ID主要是系统调度时使用.
2、调用CloseHandle关闭进程或者线程句柄的时候,只是让内核计数器(GetTickCount)减少一个,并不是终止进程或者线程.
进程或线程将继续运行,直到它自己终止运行。
3、进程ID与线程ID 是不可能相同。但不要通过进程或者线程的ID来操作进程或者线程,因为,这个编号是会
重复使用的,也就是说,当你通过ID=100这个编号去访问一个进程的时候,它已经结束了,而且系统将这个编号
赋给了另外一个进程或者线程.
六.终止进程的三种方式
1、VOID ExitProcess(UINT fuExitCode) //进程自己调用
2、BOOL TerminateProcess(HANDLE hProcess, UINT fuExitCode); //终止其他进程
3、ExitThread //终止进程中的所有线程,进程也会终止
获取进程的退出码:
BOOL GetExitCodeProcess(HANDLE hProcess,PDWORD pdwExitCode);
进程终止时相关操作:
1、进程中剩余的所有线程全部终止运行
2、进程指定的所有用户对象均被释放,所有 内核对象均被关闭
3、进程内核对象的状态变成收到通知的状态
4、进程内核对象的使用计数递减1