1. 程式人生 > >win32之進程概念

win32之進程概念

分享圖片 memory 重要 api def 版本 ppr 環境 模塊

          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之進程概念