• 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);
    }
  • 相关阅读:
    Leetcode 647 回文子串
    计算机专业课程——答案搜集
    Centos搭建go环境以及go入门
    android studio实现圆角的button
    关于区块链的认识和看法
    LeetCode 96. 不同的二叉搜索树
    LeetCode 120. Triangle (三角形最小路径和)详解
    LeetCode 64最小路径和
    微信发起摄像头接口请求 上传头像 图片
    Vue解决项目白屏以及(反向代理)
  • 原文地址:https://www.cnblogs.com/iBinary/p/9571577.html
Copyright © 2020-2023  润新知