天天看點

[筆記]Windows核心程式設計《三》程序程序獲得系統總結

文章目錄

  • 程序
    • 程序必須有一個線程
    • 程序銷毀
      • 主線程的入口點函數傳回(推薦)
      • 調用ExitProcess 強制退出(不推薦)
      • 在另一個程序調用TerminalProcess(不推薦)
    • 連結器子系統開關
      • /Subsystem:console 控制台程式 入口
      • /Subsystem:Windows GUI程式 入口
    • main函數運作生命周期
      • C運作時庫函數
      • main函數運作生命周期
    • exit(0),ExitProcess,和TerminateProcess
  • 獲得系統
  • 總結

程序

程序必須有一個線程

PrimaryThread 主線程

程序銷毀

主線程的入口點函數傳回(推薦)

程序的所有線程自然死亡(幾乎不出現)

要麼程序所有線程都調用ExitThread

調用ExitProcess 強制退出(不推薦)

在程序的一個子線程中調用ExitProcess,

缺陷:

ExitProcess 後的代碼會無法執行,會有資源沒有釋放,因為c/c++運作庫也許不能執行正确的清理工作,包括全局對象的析構和本地對象的析構。

在另一個程序調用TerminalProcess(不推薦)

在另一個程序的任意線程中調用TerminalProcess,傳入被終止的程序handle。

缺陷:

被終止程序得不到終止的通知,程序得不到正确清理,也不能阻止它被強行終止,但是作業系統會在終止後徹底清理的,確定不會洩露任何作業系統資源(程序的 記憶體,檔案,核心對象計數,使用者對象,GDI對象都會被銷毀)。

連結器子系統開關

将子系統的正确類型嵌入最終生成的可執行檔案。

visitual studio中設定子系統方式:屬性-》連結器-》子系統

/Subsystem:console 控制台程式 入口

_tmain(Main):處理ascii字元和字元串的CUI程式(控制台程式)

對應嵌入可執行檔案的啟動函數 mainCRTStartup

_tmain(wMain):處理Unicode字元和字元串的CUI程式(控制台程式)

對應嵌入可執行檔案的啟動函數 wMainCRTStartup

/Subsystem:Windows GUI程式 入口

_tWinMain(WinMain):處理ascii字元和字元串的GUI程式(圖形化程式)

對應嵌入可執行檔案的啟動函數 WinMainCRTStartup

_tWinMain(wWinMain):處理Unicode字元和字元串的GUI程式(圖形化程式)

對應嵌入可執行檔案的啟動函數 wWinMainCRTStartup

main函數運作生命周期

C運作時庫函數

這些C運作時庫函數,主要完成以下任務:

  1. 擷取程序指令行指針;
  2. 擷取程序環境變量指針;
  3. 初始化C/C++運作時庫的全局變量,如果你包含了頭Stdlib.h,那麼你就可以通路這些變量!//errno這就是一個全局變量。_enrion這是環境變量指針
  4. 初始化malloc函數的記憶體堆;
  5. 為C++全局類,調用構造函數。

malloc 函數,不要輕易使用,因為這個函數一般來說,最終會調用windows API函數,我們直接調用virtualAlloc windowsAPI函數,效率會高!

main函數運作生命周期

Kenerl 調用XXXCRTStartup函數;

XXXCRTStartup函數調用main函數;

main函數退出;

exit函數被調用(真正調用的是crt0dat.c中的)

static void __cdecl doexit (
        int code,
        int quick,
        int retcaller
        )
           

這個函數主要做以下事情:

1.調用_onexit函數注冊的所有函數;

2.調用C++銷毀函數銷毀所有的全局和靜态類對象;

3.如果_CRTDBG_LEAK_CHECK_DF标志被設定,那麼調用CrtDumpMemoryLeaks函數,列出洩露記憶體。

4.調用ExitProcess函數,系統殺死目前程序!

exit(0),ExitProcess,和TerminateProcess

獲得系統

GetVersion() 獲得版本号

#include <windows.h>
#include <stdio.h>

#include <VersionHelpers.h> 

void main()
{
    DWORD dwVersion = 0; 
    DWORD dwMajorVersion = 0;
    DWORD dwMinorVersion = 0; 
    DWORD dwBuild = 0;
    LPOSVERSIONINFOW lpVersionInformation;
    dwVersion = GetVersion();//GetVersionEx(lpVersionInformation);

    if (IsWindowsXPOrGreater()) {
        printf("Yes\n");
    };
	printf("%0x\n",dwVersion);
 
    // Get the Windows version.
	//一個子就是WORD;
	WORD Version=LOWORD(dwVersion);
	//dwVersion中,其地位字,
    dwMajorVersion = (DWORD)(LOBYTE(Version));
	//Version字的低位元組代表大版本号
    dwMinorVersion = (DWORD)(HIBYTE(Version));
	//Version字的高位元組代表小版本号

    // Get the build number.

    if (dwVersion < 0x80000000)              
        dwBuild = (DWORD)(HIWORD(dwVersion));
	//dwVersion的高位字,表示build号。

    printf("Version is %d.%d (%d)\n", 
                dwMajorVersion,
                dwMinorVersion,
                dwBuild);

	getchar();
}
           

總結

1.使用

C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\Tools

有一些工具 包括GuidGen.exe

繼續閱讀