? 關于一些進程的概念就不說了。。。
?
一創建進程GreateProcess
(1).當一個進程被創建時:
①.系統為進程創建一個內核對象,并將這個對象的計數設置為1,進程對象只是一個比較小的數據結構,可以通過進程句柄來引用
②.系統為進程創建一個虛擬地址空間,并將可執行文件裝載到這個地址空間中,系統同時處理可執行文件的導入表,將導入表中所有dll文件裝入.
每個dll被裝入的時候,dll入口函數被執行,如果入口函數返回初始化失敗信息的話 ,進程的初始化失敗.
可執行文件的每個dll都被看作單獨的模塊,都被分配了一個實例句柄(實例句柄在數值上等于模塊裝入到地址空間中的線性地址)
③.系統為進程建立一個主線程,主線程將從可執行文件的的入口地址開始執行
④.對于進程來說,每一個進程對應一個進程句柄和一個進程ID
?
(2).和創建進程有關的一些結構
①STARTUPINFO
typedef struct _STARTUPINFO {
? DWORD cb;????????????????????????????????????? ;結構的長度
? LPTSTR lpReserved;?????????????????????????? ;保留字段
? LPTSTR lpDesktop;??????????????????????????? ;NT下使用,指定桌面名稱
? LPTSTR lpTitle;????????????????????????????????? ;控制臺使用指定控制臺窗口標題
? DWORD dwX;?????????????????????????????????? ;當新進程使用CW_USEDEFAULT參數創建
? DWORD dwY;?????????????????????????????????? ;窗口的時候將使用這些位置和大小屬性
? WORD dwXSize;???????????????????????????????
? ORD dwYSize;
? DWORD dwXCountChars;?????????????????;控制臺程序使用,指定控制臺窗口行數
? DWORD dwYCountChars;?????????????????;
? DWORD dwFillAttribute;???????????????????;控制臺程序使用,指定控制臺窗口背景色
? DWORD dwFlags;?????????????????????????????;標志
? WORD wShowWindow;????????????????????;窗口的顯示方式
? WORD cbReserved2;
? LPBYTE lpReserved2;
? HANDLE hStdInput;??????????????????????? ;控制臺程序使用:幾個標準句柄
? ANDLE hStdOutput;
? HANDLE hStdError;
} STARTUPINFO,
?*LPSTARTUPINFO;
在需要指定新進程的窗口時,才需要手動填寫STARTUPINFO結構(比如需要控制臺程序的輸入輸出重定位時候,可以改寫hStdInput和hStdOutput字段)
在大多數情況下,并不需要新進程的窗口有什么特殊之處,這時只需要使用GetStartupInfo獲取當前進程的STARTUPINFO結構并使用他就可以了
invoke GetStartupInfo,addr stStartupInfo
?
②.PROCESS_INFOMATION
typedef struct _PROCESS_INFORMATION
?{?
HANDLE hProcess;?
HANDLE hThread;?
DWORD dwProcessId;
DWORD dwThreadId;??? 主線程句柄
PROCESS_INFORMATION,?
*LPPROCESS_INFORMATION;
?
(3).CreateProcess
BOOL WINAPI CreateProcess(
? __in_opt??????? LPCTSTR? lpApplicationName,
? __inout_opt? LPTSTR? lpCommandLine,
? __in_opt??????? LPSECURITY_ATTRIBUTES lpProcessAttributes,
? __in_opt??????? LPSECURITY_ATTRIBUTES lpThreadAttributes,
? __in??????????????? BOOL bInheritHandles,
? __in??????????????? DWORD dwCreationFlags,
? __in_opt?????? LPVOID lpEnvironment,
? __in_opt??????? LPCTSTR lpCurrentDirectory,
? __in??????????????? LPSTARTUPINFO lpStartupInfo,
? __out???????????? LPPROCESS_INFORMATION lpProcessInformation
);
①lpApplicationName
指向一個以0結尾的字符串,指明可執行文件名,如果這個參數為NULL,那么文件名可以在老婆CommandLine參數指定的命令行參數中包含
②lpCommandLine
用來指定命令行參數,如果 lpApplicationName為NULL,那么命令行參數的第一個組成部分用來指定可執行文件名;
如果2個參數都為空,那么lpApplicationName為文件名,lpCommandLine作為命令行參數
③lpProcessAtrributes
指向一個SECURITY_ATTRIBUTES結構,用來指定新進程的安全屬性,如果進程句柄不需要被其他子進程繼承,可以在這里使用NULL
④lpThreadAtrributes
指向一個SECURITY_ATTRIBUTES結構,用來指定新進程的安全屬性,如果進程句柄不需要被其他線程繼承,可以在這里使用NULL
⑤bInheritHandles
指定當前進程句柄是否可以被新進程繼承,如果指定為TRUE,那么可以繼承,一般在這里使用FALSE
⑥dwCreationFlags
創建標志,指定新進程的優先級以及其他標志,這個參數類似于CreateThread函數中的同名參數它可以是一些標志的組合,下面列舉一些常用的標志
CREATE_NEW_CONSOLE 如果新進程是控制臺程序,那么為他新建一個控制臺窗口,而不是使用父進程的窗口
CREATE_SUSPENED? 新建進程的主線程一開始處于掛起狀態需要以后用ResumeThread函數來恢復它的執行
DEBUG_PROCESS?????????????????????? ;調試有關
DEBUG_ONLY_THIS_PROCESS
HIGH_PRIORITY_CLASS?????????????? ;指定新進程的優先級
NORMAL_PRIORITY_CLASS
REALTIME_PRIORIY_CLASS
⑦lpEnvironment
指向新進程的環境變量塊,如果這個參數指定為NULL,表示讓Windows拷貝當前進程的環境塊當做子進程的環境塊,如果程序需要將修改過的環境塊傳給子進程,可以設置這個參數
⑧lpCurrentDirectory
指向一個字符路徑,用來指定子進程的當前驅動器和當前目錄,如果指定為NULL,子進程將引用父進程的當前路徑
⑨后面2個參數分別指向前面介紹的2個結構體
---------------------------------------------------------------------------------------------------------------------------------------------------
二.結束進程
(1)ExitProcess? dwExitCode
ExitProcess只能用來結束當前進程,不能用來結束其他進程,包括當前進程創建的子進程
?
(2)TerminateProcess hProcess,dwExitCode
這個函數不推薦使用,一般僅在很極端的條件下使用,(如任務管理器用來結束響應的進程)
因為目標進程無條件結束,沒有機會進行掃尾工作,同時目標進程使用的dll文件也不會收到結束通知,所以極有可能 造成數據丟失
?
當前進程被結束時,系統將做如下工作
①進程創建或打開的所有對象句柄被關閉
②進程的所有線程被終止
③進程和進程中所有的線程狀態被改為置位狀態,以便讓WaitForSingleObject函數正常的檢測
④進程對象中的退出碼字段從STILL_ACTIVE被改為指定的退出碼
?
(3)要檢測一個進程的退出碼可以使用
GetExitCodeProcess hProcess,lpExitCode
如果函數執行成功返回退出碼到lpExitCode
如果失敗返回STILL_ACTIVE到lpExitCode
通過檢測一個子進程的退出碼是否為STILL_ACTIVE,就可以得知子進程是否已經結束,但如果需要在父進程中等待子進程結束時,就沒有必要不停的檢測退出碼
可以使用WaitForSingleObject hProcess,dwMilliseconds
dwMilliseconds指定為INFINITE就可以了,表示子進程結束前函數不會返回
?
當一個進程被結束時,并不影響它所創建的子進程,進程對象也不會馬上從內存中刪除,因為可能其他進程還需要通過進程句柄檢測進程狀態,直到使用CloseHandle函數將進程句柄關閉以后,
進程對象才是真正的被刪除了,所以當不在使用進程句柄的時候,不要忘記關閉PROCESS_INFORMATION中的進程句柄 和主線程句柄
?
?