zoukankan      html  css  js  c++  java
  • 【windows核心编程】 4 进程

    【1】

    windows程序分为GUI程序好CUI程序,即Graphical User Interface和Console User Interface

    在Visual Studio中,GUI程序的链接开关是/SUBSYSTEM:WINDOWS, GUI程序的链接开关是/SUBSYSTEM:CONSOLE

    这是一个控制台程序的设置。

    windows程序的入口有以下两种:

     1 Int WINAPI _tWinMain(
     2 HINSTANCE hInstanceExe,                //进程实例句柄
     3 HINSTANCE , /*hPreInstance*/           //之前的实例,总为NULL
     4 PTSTR,  pszCmdLine,                    //命令行参数,包括exe名称
     5 int nCmdShow
     6 );
     7 
     8 
     9 
    10 int _tmain(
    11 int argc,                //参数个数,包含exe
    12 TCHAR  *argv[],          //每个参数字符串
    13 TCHAR  *envp[]           //进程环境变量指针数组
    14 );

    【2】

    但是在调用上述入口函数之前,系统会调用真正的入口函数来做一些初始化的工作,比如初始化全局变量和静态C++对象的构造,下面说明了每种情况下的真正的入口函数

    ANSI--------_tWinMain(WinMain)------------WinMainCRTStartup

    UNICODE---_tWinMain(wWinMain)-----------wWinMainCRTStartup

    ANSI--------_tmain(Main)--------------------mainCRTStartup

    UNICODE----_tmain(wMain)------------------wmainCRTStartup

     上面四个真正的入口函数的源码在C运行库的crtexe.c文件中。

    【3】

    HINSTANCE和HMODULE相同,可相互替代,只是在16位windows时代有所不同。

    加载到进程地址空间的每个可执行文件和DLL都有一个唯一的实例句柄, HICON LoadIcon(HINSTANCE  hInstance, PCTSTR pszZIcon)函数的作用是从实例句柄为hInstance的文件中加载名为pszIcon的图标资源。

    可执行文件的实例被当作(w)WinMain函数的第一个参数(见上文),即参数 hInstanceExe, 这个参数的实际值是一个内存基地址,希望将可执行文件的映像加载到进程地址空间中的这个位置。

    Visual Studio连接器默认的基地址是0x00400000, 这是在win98下,可执行文件所能加载到的最低的地址。使用MS的连接器/BASE:address开关可以更改基地址。

    那么怎么样获得一个可执行文件或DLL被加载到进程地址空间的什么位置呢? 可用下函数:

    HMODULE  GetModuleHandle(PCTSTR  pszModule)

    加入A进程调用了一个可执行文件B和一个DLL名为C, 那么可以用这个函数来把B 或 C的名字作为pszModule参数传给它取得B或C在当前进程地址空间中的位置, 如果找到了该参数标明的可执行文件或DLL,那么将返回他们在进程地址空间中的位置,否则返回NULL。

    如果给pszModule参数传NULL, 那么将返回调用此函数的进程即A进程的可执行文件的基地址。

     1 #include "stdafx.h"
     2 #include <iostream>
     3 #include "windows.h"
     4 
     5 int _tmain(int argc, _TCHAR* argv[])
     6 {
     7 
     8     HMODULE hModue = GetModuleHandle(NULL);
     9 
    10     printf("当前进程地址为:0x%08x\n", hModue); 
    11 
    12     PWSTR lpParams = GetCommandLineW();               //取得命令行参数,包括exe
    13 
    14     int count = 0;
    15 
    16     PWSTR *pRet = CommandLineToArgvW(lpParams, &count); //命令行参数和参数个数,包括exe; 该函数内部分配内存, 返回指针数组(指针的指针)
    17 
    18     for (int i = 0; i < count; ++ i)
    19     {
    20         std::wcout<<pRet[i]<<std::endl;
    21     }
    22 
    23  
    24     return 0;
    25 }

    输出如下:

    需要注意的是:上面函数CommandLineToArgvW在函数内部分配内存,且不释放,一般情况下是可以接收的,但是如果想要手动释放那部分内存也是可以的

    HeapFree函数可以用来释放那部分内存:

    HeapFree(GetProcessHeap(), 0, pRet);   //pRet为上面CommandLineToArgvW函数的返回值。

     1  PTSTR pszValue = NULL;
     2 
     3     DWORD dwResult = GetEnvironmentVariable(_T("path"), pszValue, 0);
     4 
     5     if (0 != dwResult)
     6     {         
     7         pszValue = (PTSTR)malloc(size);
     8         GetEnvironmentVariable(_T("path"), pszValue, size);
     9         wcout<<pszValue<<endl;
    10 
    11         free(pszValue);
    12     }

  • 相关阅读:
    JS模拟出 getElementsByClassName 功能
    如何为PDF文件添加书签
    Linux内核模块学习
    Linux字符设备驱动学习
    第53篇编译线程的初始化
    第51篇SharedRuntime::generate_native_wrapper()生成编译入口
    第50篇调用约定(2)
    第52篇即时编译器
    2021 阿里云容器服务年度盘点:企业级容器应用变化和技术趋势观察
    如何在零停机的情况下迁移 Kubernetes 集群
  • 原文地址:https://www.cnblogs.com/cuish/p/2882159.html
Copyright © 2011-2022 走看看