zoukankan      html  css  js  c++  java
  • Windows程序设计_18_程序加载过程

      今天看Windows Program Via c/c++;突然想看一下Windows加载EXE文件或者可执行文件的过程。于是就建立了一个

    项目进行测试:

      代码很简单,就是建立一个窗口。

    /*
        windows program via c/c++
    exp:
        chapter  1
    */
    
    #include <windows.h>
    
    LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam);
    
    int WINAPI WinMain(HINSTANCE hInstance,
                       HINSTANCE hPrevInstance,
                       LPSTR lpCmdLine,
                       int nShowCmd
                       )
    {
        TCHAR szAppName[]=TEXT("ErrorWin");
    
        HWND hwnd; //窗口句柄
        WNDCLASS wndclass;  //窗口类
        MSG message;
    
        wndclass.cbClsExtra=0;
        wndclass.cbWndExtra=0;
        wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
        wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
        wndclass.hbrBackground =(HBRUSH)GetStockObject(WHITE_BRUSH);
        wndclass.hInstance =hInstance;
        wndclass.lpfnWndProc=WndProc;
        wndclass.lpszClassName=szAppName;
        wndclass.lpszMenuName=NULL;
        wndclass.style = CS_HREDRAW | CS_VREDRAW;
    
        if(!RegisterClass(&wndclass))
        {
            MessageBox(NULL,
                       TEXT("You need Windows NT to run this program"),
                       TEXT("ErrorWin"),
                       MB_ICONERROR);
            return 0;
        }
    
        hwnd=CreateWindow(szAppName,  //窗口类名
                          TEXT("ErrorWin"),  //窗口标题
                          WS_OVERLAPPEDWINDOW,  //窗口层叠类型
                          CW_USEDEFAULT,//x
                          CW_USEDEFAULT, //y
                          480, //hight
                          240, //width
                          NULL,  //父窗口句柄
                          NULL,  //菜单句柄
                          hInstance,  //实例句柄
                          NULL  //附加参数
                          );
    
        ShowWindow(hwnd,nShowCmd);
        UpdateWindow(hwnd);
    
        while(GetMessage(&message,hwnd,0,0))
        {
            TranslateMessage(&message);
            DispatchMessage(&message);
        }
    
        return message.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
    {
        switch(message)
        {
        case WM_CLOSE:
        case WM_DESTROY:
             PostQuitMessage(0);
             return 0;    
        }
        
        return DefWindowProc(hwnd,message,wParam,lParam);
    }

      下面是程序执行过程VS 2008 Output窗口显示的调试信息:

    'chapter1_01.exe': Loaded 'G:\13_Windows_Program_Via_C\chapter1_01\Debug\chapter1_01.exe', Symbols loaded.
    'chapter1_01.exe': Loaded 'C:\Windows\System32\ntdll.dll'
    'chapter1_01.exe': Loaded 'C:\Windows\System32\kernel32.dll'
    'chapter1_01.exe': Loaded 'C:\Windows\System32\KernelBase.dll'
    'chapter1_01.exe': Loaded 'C:\Windows\System32\user32.dll'
    'chapter1_01.exe': Loaded 'C:\Windows\System32\gdi32.dll'
    'chapter1_01.exe': Loaded 'C:\Windows\System32\lpk.dll'
    'chapter1_01.exe': Loaded 'C:\Windows\System32\usp10.dll'
    'chapter1_01.exe': Loaded 'C:\Windows\System32\msvcrt.dll'
    'chapter1_01.exe': Loaded 'C:\Windows\winsxs\x86_microsoft.vc90.debugcrt_1fc8b3b9a1e18e3b_9.0.21022.8_none_96748342450f6aa2\msvcr90d.dll', Symbols loaded.
    'chapter1_01.exe': Loaded 'C:\Windows\System32\imm32.dll'
    'chapter1_01.exe': Loaded 'C:\Windows\System32\msctf.dll'
    'chapter1_01.exe': Loaded 'C:\Windows\System32\uxtheme.dll'
    'chapter1_01.exe': Loaded 'C:\Windows\System32\apphelp.dll'
    'chapter1_01.exe': Loaded 'C:\Windows\System32\baiducn.ime'
    'chapter1_01.exe': Loaded 'C:\Windows\System32\oleacc.dll'
    'chapter1_01.exe': Loaded 'C:\Windows\System32\ole32.dll'
    'chapter1_01.exe': Loaded 'C:\Windows\System32\rpcrt4.dll'
    'chapter1_01.exe': Loaded 'C:\Windows\System32\advapi32.dll'
    'chapter1_01.exe': Loaded 'C:\Windows\System32\sechost.dll'
    'chapter1_01.exe': Loaded 'C:\Windows\System32\shell32.dll'
    'chapter1_01.exe': Loaded 'C:\Windows\System32\shlwapi.dll'
    'chapter1_01.exe': Loaded 'C:\Windows\System32\oleaut32.dll'
    'chapter1_01.exe': Loaded 'C:\Windows\winsxs\x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82.7601.17514_none_ec83dffa859149af\comctl32.dll'
    'chapter1_01.exe': Loaded 'C:\Windows\System32\version.dll'
    'chapter1_01.exe': Loaded 'C:\Windows\System32\profapi.dll'
    'chapter1_01.exe': Loaded 'C:\Windows\System32\dwmapi.dll'
    'chapter1_01.exe': Loaded 'C:\Windows\System32\cryptbase.dll'
    'chapter1_01.exe': Loaded 'C:\Program Files\Baidu\BaiduPinyin\2.4.2.281\uipfull.dll'
    'chapter1_01.exe': Loaded 'C:\Windows\System32\winmm.dll'
    'chapter1_01.exe': Loaded 'C:\Windows\System32\msimg32.dll'
    'chapter1_01.exe': Loaded 'C:\Windows\winsxs\x86_microsoft.windows.gdiplus_6595b64144ccf1df_1.1.7601.17514_none_72d18a4386696c80\GdiPlus.dll'
    'chapter1_01.exe': Loaded 'C:\Program Files\Baidu\BaiduPinyin\2.4.2.281\imefreetype.dll', Binary was not built with debug information.
    'chapter1_01.exe': Loaded 'C:\Program Files\Baidu\BaiduPinyin\2.4.2.281\imepng.dll', Binary was not built with debug information.
    'chapter1_01.exe': Loaded 'C:\Program Files\Baidu\BaiduPinyin\2.4.2.281\imezlib.dll', Binary was not built with debug information.
    'chapter1_01.exe': Loaded 'C:\Windows\System32\sspicli.dll'
    The thread 'Win32 Thread' (0x7fc) has exited with code 0 (0x0).
    The thread 'Win32 Thread' (0xb74) has exited with code 0 (0x0).
    The thread 'Win32 Thread' (0x210) has exited with code 0 (0x0).
    The thread 'Win32 Thread' (0xd34) has exited with code 0 (0x0).
    The program '[3940] chapter1_01.exe: Native' has exited with code 0 (0x0).

      我们可以看各行的信息:

    【1】

     Loaded 'G:\13_Windows_Program_Via_C\chapter1_01\Debug\chapter1_01.exe', Symbols loaded.

      这一行的内容:  显示加载可执行文件到内存,并且加载程序的符号,毫无疑问,第一步必须将文件从硬盘加载到内存,才有可能执行。

    【2】

    'chapter1_01.exe': Loaded 'C:\Windows\System32\ntdll.dll'

      加载ntdll.dll中的内容,这个动态链接库文件,应该是一直常驻内存的;这个地方既然不是加载,那么就必然是调用函数,那么这个时候调用的会

    是那个API函数呢?

      我们可以通过查看ntdll.dll文件的导出符号表,发现里面有一个NtCreateProcess函数,如下图所示:

      虽然我们在Windows API中有CreateProcess函数可以使用;但是函数CreateProcess最终都会调用NtCreateProcess函数来创建进程;这个函数

    的作用就是创建内核进程对象,具体是:

    所谓创建内核中的进程对象,实际上就是创建以EPROCESS为核心、为基础的相关数据结构,这就是系统调用NtCreateProcess()要做的事情,主要包括:
        ● 分配并设置EPROCESS数据结构。
        ● 其他相关的数据结构的设置,例如“打开对象表”。
        ● 为目标进程创建初始的地址空间。
        ● 对目标进程的“内核进程块”KPROCESS进行初始化。
        ● 将系统DLL的映像映射到目标进程的(用户)地址空间。
        ● 将目标进程的映像映射到其自身的用户空间。
        ● 设置好目标进程的“进程环境块”PEB。
        ● 映射其他需要映射到用户空间的数据结构,例如与“当地语言支持”、即NLS有关的数据结构。
        ● 完成EPROCESS创建,将其挂入进程队列(注意受调度的是线程队列而不是进程队列)。

      当然这个过程也会进行一次线程的创建,如果是单线程的话,那么这个线程就是进程的主线程。

      但是这个函数并没有进行真正的进程创建工作,真正的工作是PspCreateProcess完成的。但是我找了好久的资料都没发现这个PspCreateProcess函数

    存在于那个动态链接库文件中。

    【3】

    'chapter1_01.exe': Loaded 'C:\Windows\System32\kernel32.dll'

      这一行,表示进程执行过程中,调用了Kernel32.dll文件,在《Windows程序设计》里面,作者将kernel32.dll作为一个子系统来作用,这里我们可以看一下

    这个动态链接库文件与其他链接库文件的依存关系:

                 

      通过上面的图可以看出:kernel32.dll 调用了ntdll.dll中提供的函数;而在整个dll链中ntdll.dll,我们没有发现其有依存关系(迷惑中....ing)。

    而在kernel32.dll中,我们可以看到CreateProcess函数

            

    创建进程后,需要初始化内核对象。

    【4】

    'chapter1_01.exe': Loaded 'C:\Windows\System32\user32.dll'

      当进程内核对象创建完成,并完成初始化。

      进程内核对象初始化完成后,就需要进行一些界面上处理工作了,这个时候就需要注册窗口类了,

      RegisteClass函数是user32.dll提供的系统API函数。注册完就是创建窗口。

      这就是CreateWindow这些函数的事情了,在dll中可以查看

    其函数有

      

      这就是我们的CreateWindows函数,创建窗口,很显然这个属于用户界面的范畴。

      创建完窗口,就是显示和更新窗口,这个也是属于用户界面的范畴。

      最终进入消息循环队列,这个还是属于user32.dll动态链接库的范畴,由用户子系统来处理消息。

      大体就是这么一个过程,可以发现执行一个Windows程序,系统需要做的工作非常之多。

    凌晨0点了,累了,有机会再说吧。

  • 相关阅读:
    css常见小问题(个人的积累总结)
    YQBlogs1.2的解读与使用VS2012&LocalDB版本(跟进贴)
    asp.net mvc 用自定义的RazorViewEngine实现主题的自由切换遇到的问题!
    求解?命令行下操作LocalDb的诸多问题
    CentOS7下docker安装
    IIS 应用程序池设置,避免IIS假死
    .NET 将数据输出到WORD、EXCEL、TXT、HTM
    iframe高度动态自适应
    .net利用SQLBulkCopy进行数据库之间的大批量数据传递
    Datatable.Select()用法简介
  • 原文地址:https://www.cnblogs.com/volcanol/p/3072285.html
Copyright © 2011-2022 走看看