win32之進程概念
win32之進程
一丶簡介
學習WindowsAPI. 之前.我們必須理解什麽是進程. 在windows環境下.進程就是一個運行起來的exe程序
進程提供了數據以及資源. 但是怎麽使用不管.而是由線程去管.
進程可以抽象為一棟房子. 而房子裏面提供了日用品. 怎麽使用它是不管的.
進程由很多DLL組成.我們可以拖動exe文件到win32dbg中查看. 快捷鍵 ALT + E 鍵.查看模塊.
進程使用的內存空間是用戶模式的內存空間.
什麽是用戶模式空間?
在windows中.進程的空間都是虛擬空間. 低2G空間是用戶使用的. 高2G則是內核中使用. 而且是所有進程共享的.只有ring 3也就是用戶模式的exe空間是獨立的.
而高2G空間中.又分為高低64k空間. 這段內存是不能使用的.
例如下圖:
我們使用快捷鍵ALT + M鍵可以看到.進程的資源.以及地址起始位置.
二丶探究原理跟本質.進程是如何創建的.
1.雙擊原理
我們一個進程可以使用鼠標雙擊來創建.但是並不是你鼠標創建的.而是由桌面管理器來創建的. 在windows任務管理器中 (ctrl + alt + del / ctrl + shift + esc 調出)
如下圖:
而它創建的時候.是通過API CreateProcess 進行創建的.
2.原理.CreateProcess做了什麽事情.
1.映射exe內存. 當調用CreateProcess的時候. 此時會把我們的exe映射到用戶模式的虛擬內存中.
2.創建內核對象 EPROCESS 關於這點.熟悉內核驅動的應該知道.內核中EPROCESS是進程. ETHREAD是線程.不過如果不懂了解即可.
3.映射系統DLL 映射NTDLL. ntdll是系統dll每個進程都必須有這個ntdll.
4.創建ETHREAD 線程來執行代碼. 我們知道進程只是提供資源數據代碼而已. 但是怎麽執行.是由線程來執行的. 通常我們會說主線程.
5.系統啟動
5.1映射DLL 為什麽還要映射.因為你程序需要的dll加載了.可是dll可能還是使用其他的dll.所以為了程序的執行.也一並加載進來.
5.2線程開始執行.這個時候就是開始執行我們代碼了.
三丶進程創建CreateProcess解析
通過上面的原理我們知道了系統會調用CreateProcess進行創建進程.
PS: 在windows系統中.我們使用API的時候其實是 A版本跟W版本. 例如CreateProcessA 但是為了兼容性.windows直接封裝了宏. CreateProcess.表示A 版下調用的就是CreateProcessA. W版本則是W版本.
BOOL CreateProcessA( LPCSTR lpApplicationName, //要創建的進程名稱 完整路徑+exe LPSTR lpCommandLine, //命令行參數. LPSECURITY_ATTRIBUTES lpProcessAttributes, //是否進行繼承進程句柄 LPSECURITY_ATTRIBUTES lpThreadAttributes, //是否進行繼承線程句柄 BOOL bInheritHandles, //是否進行繼承句柄 DWORD dwCreationFlags, //程序創建的標誌. LPVOID lpEnvironment, //父進程環境變量 LPCSTR lpCurrentDirectory, //父進程當前目錄.自己可以設置 LPSTARTUPINFOA lpStartupInfo, //啟動信息結構體. LPPROCESS_INFORMATION lpProcessInformation//進程信息結構體 );
在這裏主要參數是1 2 9 10參數
1.LpApplicationName 這個就是我們要創建的進程的路徑.
2.lpCommandLine 這個就是命令行參數.如果我們要啟動的程序帶有命令行啟動.那麽這裏填寫參數即可.
9. lpStartupInfo 啟動信息結構體. 這個結構體裏面存儲了要創建進程的一些信息.傳入參數.我們可以指定.但是一般進程都有自己啟動信息所以一般不設置.其中有一個成員比較重要.
10 lpProcessInfomation 進程信息結構體. 傳出參數. 當我們創建進程完畢後.會得到進程的句柄.線程句柄. 進程id,線程id. 這個是個傳出參數.表示返回值.
啟動信息結構體解析.
typedef struct _STARTUPINFOA { DWORD cb; 表示當前結構體的大小 重要成員 LPSTR lpReserved; LPSTR lpDesktop; LPSTR lpTitle; DWORD dwX; 創建進程的x位置.y位置大小... DWORD dwY; DWORD dwXSize; DWORD dwYSize; DWORD dwXCountChars; DWORD dwYCountChars; DWORD dwFillAttribute; DWORD dwFlags; WORD wShowWindow; WORD cbReserved2; LPBYTE lpReserved2; HANDLE hStdInput; HANDLE hStdOutput; HANDLE hStdError; } STARTUPINFOA, *LPSTARTUPINFOA;
關於這個結構.我們只需要知道第一個成員. 因為第一個成員必須我們給定.(其他也可以.但不是必須) 給定的是使用的當前結構體的大小.因為在windows程序中.很有可能擴展.為了擴展性.所以給一個成員指定一下.等以後結構體修改了.那麽我們成員多大.windows就知道使用多大的結構體了.
進程信息結構體
typedef struct _PROCESS_INFORMATION { HANDLE hProcess; 返回的進程句柄 HANDLE hThread; 返回的線程句柄 DWORD dwProcessId; 返回的進程ID DWORD dwThreadId; 返回的線程ID } PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION;
其中重要了就這些成員了.
介紹幾個常用的API函數.
ZeroMemory(清零的地址,清零地址的大小) ; 這個API是使內存進行清零. 我們創建啟動信息結構體的時候需要進行初始化使用.
CloseHandle(句柄) 關閉句柄. 當CreateProcess創建進程完畢後會返回進程信息結構體. 裏面的句柄如果不適用我們需要使用CloseHandle進行關閉.
四丶詳細代碼.
#include <Windows.h> int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { TCHAR wszStartUpFileName[] = TEXT("D:\\calc.exe"); //要啟動的程序路徑 TCHAR wszStartUpFileCommandLine[] = TEXT(""); //命令行參數 STARTUPINFO si; //啟動信息結構體 PROCESS_INFORMATION pi; //進程信息結構體 ZeroMemory(&si, sizeof(si)); //清零 ZeroMemory(&pi, sizeof(pi)); si.cb = sizeof(si); //啟動信息結構體賦值為當前結構體大小 CreateProcess( //創建進程 wszStartUpFileName, wszStartUpFileCommandLine, NULL, NULL, NULL, NULL, NULL, NULL, &si, &pi ); CloseHandle(pi.hProcess); //不使用的句柄關閉 CloseHandle(pi.hThread); }
win32之進程概念