• Windows创建的基本含义和进程的进程的内核


    过程

    1 这意味着过程:

    1.1   一个是在操作系统的内核对象管理处理。

    的统计信息的地方。

    1.2   还有一个是地址空间。它包括全部可运行模块或DL L 模块的代码和数据。它还包括动态内存分配的空间。如线程堆栈和堆分配空间。

    2 操作系统启动应用程序的步骤

    2.1 调用C/c++执行时的启动函数

             启动函数总共4种,WinMainCRTStartup,wWinMainCRTStartup,mainCRTStartup,wmainCRTStartup。

             启动函数完毕例如以下任务:

    <1>检索指向新进程的完整命令行的指针

    <2>检索指向新进程的环境变量的指针

    <3>对C/ C + +执行期的全局变量进行初始化。

    假设包括了S t d L i b . h 文件。代码就能訪问这些变量

    <4>对C执行期内存单元分配函数(m a l l o c 和c a l l o c )和其它低层输入/输出例程使用的内存栈进行初始化。

    <5>为全部全局和静态C+ +类对象调用构造函数。

    <6>调用入口点函数

    如:int nMainRetVal = wmain(__argc, __wargv, _wenviron); 

    <7>当进入点函数返回时,启动函数便调用C 执行期的ex i t 函数,将返回值(nMainRetVal )传递给它。

    <8>调用由_onexit函数的调用而注冊的不论什么函数

    <9>为全部全局的和静态的C++类对象调用析构函数

    <10>调用操作系统的ExitProcess函数。将nMainRetVal传递给它。

    这使得该操作系统可以撤消进程并设置它的e x i t 代码

    3 进程的实例句柄

    3.1 进程的当前实例句柄

             载入到进程地址空间的每一个exe或者dll文件都会被赋予一个独一无二的句柄。

    获取载入的模块(exe,dll)的方法:

    GetModuleFileName(HMOUDLEhModule,LPTSTR lpFileName,DWROD nSize);

    当hModule的值为NULL 的时候。会返回当前调用模块的所有路径名字。

    3.2 进程的前一个实例句柄

             C++代码总是将NULL赋值给WinMain函数的第二个參数HINSTANCEhPreInstance,这种原因是在16位的程序中对这个參数有保留使用,那么保留它就方便转用16位程序。

    4 进程的命令行

    LPTSTR GetCommandLine();获取命令行字符串

    5  进程的环境变量

             每一个进程都有一个与它相关的环境变量块,环境块是进程的地址空间中分配的一个内存块。每一个环境块都包括一组字符串,形式例如以下所看到的:

    VarName1=VarValue1

    VarName2=VarValue2

    VarName3=VarValue3

             当中要注意变脸等号前有没有空格。有空格和没空格代表的是全然不同的环境变量,如:

    XYZ=xxx;和XYZ =xxx;这就是两个全然不同的环境变量了。

             操作华景变量相关的 函数

    <1>

    LPVOIDGetEnvironmentStrings(VOID);

    <2>

    BOOL SetEnvironmentVariable(
     LPCTSTR lpName,  // environment variable name
     LPCTSTR lpValue  // new value for variable);

    <3>

    DWORD GetEnvironmentVariable(  LPCTSTR lpName,  // environment variable name
     LPTSTR lpBuffer, // buffer for variable value
     DWORD nSize      // size ofbuffer);

    <4>

    BOOL FreeEnvironmentStrings(LPTSTRlpszEnvironmentBlock  // environmentstrings);

    6 进程的当前文件夹

             程序的当前文件夹是能够进行改变的。当前文件夹和进程的启动文件夹是不同的,启动文件夹就是exe或者dll被调用的文件夹,我们能够通过GetModuleFineName函数进行处理。

    <1>

    DWORD GetCurrentDirectory(
     DWORD nBufferLength,    //size of directory buffer
     LPTSTR lpBuffer            //directory buffer);

    <2>

    BOOL SetCurrentDirectory(  LPCTSTR lpPathName   // new directory name);

    7 系统的版本号信息获得

    GetVersion()

    可是这个函数有bug,就是程序猿把主版本。次版本放错了高低字节。

    BOOL GetVersionEx(  LPOSVERSIONINFO lpVersionInfo // versioninformation);

    这个是新的修正过来的。

    8 创建进程

    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
    );


    參数解释:

    <1> lpApplicationName

             被载入模块的名字,必须制定模块的格式。比方exe,由于系统不会默觉得exe,模块的名字能够是部门名字,那么系统就会在当前文件夹去寻找该模块。

             通常将其设置为NULL。由于lpCommandLine具有比它更加强大的功能来完毕模块的调用。

    <2> lpCommandLine

             系统寻找可运行文件exe的顺序是:

    应用程序载入的文件夹。

    父进程的当前文件夹;

    Windows System 文件夹;

    Windows文件夹。

    环境变量列出的文件夹;

    注意:当字符集是Unicode时候,參数类型不能是const类型的,若是就会报错。

    <3> lpProcessAttributes 

           指向 SECURITY_ATTRIBUTES的指针,决定进程创建函数返回的的新进程对象的句柄能否被子进程继承。

             当为NULL的时候,获取的是默认安全描写叙述符

    <4> lpThreadAttributes

           指向SECURITY_ATTRIBUTES 的指针,决定进程创建函数范湖的新线程对象的句柄能否被子进程继承。

             当为NULL的时候。获取的是默认安全描写叙述符。

    <5> bInheritHandles 

           假设为True。那么不论什么能够被继承的句柄都会别新创建的进程所继承。假设为FALSE。那么则不会被新进程继承。

    <6>dwCreationFlags 

           新创建的进程的创建标志位设置,决定是父子进程调试信息的反馈,子进程窗体的产生等行为。

    <7> lpEnvironment 

    新进程中指向的环境块。假设该值为NULL。那么就表示新进程继承了父进程的环境块。

    <8>lpCurrentDirectory 

    指向新进程的当前文件夹的指针。假设为NULL。那么则就和调用进程(父进程)具有同样的当前文件夹。

    <9> lpStartupInfo

           指向 STARTUPINFO or STARTUPINFOEX的指针。

    主要指定窗体的状态。外观,标准句柄。

    当Wi n d o w s 创建新进程时。它将使用该结构的有关成员。大多数应用程序将要求生成的应用程序只使用默认值。至少应该将该结构中的全部成员初始化为零,然后将cb 成员设置为该结构的大小。

           当里面创建的句柄不在是用的使用,要通过CloseHandle来关闭。

    <10> lpProcessInformation 

    指向PROCESS_INFORMATION结构体的指针。

    typedef struct _PROCESS_INFORMATION {
      HANDLE hProcess;
      HANDLE hThread;
      DWORD  dwProcessId;
      DWORD  dwThreadId;
    } PROCESS_INFORMATION, *LPPROCESS_INFORMATION;


    里面是用的句柄不在使用的时候。要通过CloseHandle函数来关闭。

           当进程内核对象创建后,系统赋予该对象一个独一无二的标识号。系统中的其它不论什么进程内核对象都不能使用这个同样的ID号。线程内核对象的情况也一样。当一个线程内核对象创建时,该对象被赋予一个独一无二的、系统范围的ID号。进程ID和线程ID共享同样的号码池。

    这意味着进程和线程不可能拥有同样的ID 。


    9 创建进程的实例:

    #include <Windows.h>
    #include <iostream>
    using namespace std;
    
    void main()
    {
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
    
        ZeroMemory( &si, sizeof(si) );
        si.cb = sizeof(si);
        ZeroMemory( &pi, sizeof(pi) );
    
        // Start the child process. 
        if( !CreateProcess( NULL, // No module name (use command line). 
            TEXT("Notepad++"),	// Command line. 
            NULL,             // Process handle not inheritable. 
            NULL,             // Thread handle not inheritable. 
            FALSE,            // Set handle inheritance to FALSE. 
            0,                // No creation flags. 
            NULL,             // Use parent's environment block. 
            NULL,             // Use parent's starting directory. 
            &si,              // Pointer to STARTUPINFO structure.
            &pi )             // Pointer to PROCESS_INFORMATION structure.
        ) 
        {
            cout<<TEXT("CreateProcess failed.");
        }
    
        // Wait until child process exits.
        WaitForSingleObject( pi.hProcess, INFINITE );
    
        // Close process and thread handles. 
        CloseHandle( pi.hProcess );
        CloseHandle( pi.hThread );
    }
    



    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    【Flutter学习】之绘画实例(二)
    【Flutter学习】之绘画实例(一)
    【Flutter学习】之动画实现原理浅析(三)
    【Flutter学习】之动画实现原理浅析(二)
    NopCommerce支持多种类型的数据库
    NopCommerce 多数据库方案
    开发程序需要注意的点
    基于SVN的项目管理——集中与分散
    JS代码优化小技巧
    开发日记:中控PUSH协议
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4643359.html
Copyright © 2020-2023  润新知