羽夏筆記——Win32(非WinAPI)


寫在前面

  本筆記是由本人獨自整理出來的,圖片來源於網絡。本人非計算機專業,可能對本教程涉及的事物沒有了解的足夠深入,如有錯誤,歡迎批評指正。 如有好的建議,歡迎反饋。碼字不易,如果本篇文章有幫助你的,如有閑錢,可以打賞支持我的創作。如想轉載,請把我的轉載信息附在文章后面,並聲明我的個人信息和本人博客地址即可,但必須事先通知我

本篇文章主要是讓讀者對Win32基本知識和底層有一個簡單的了解,並不是詳細介紹WinAPI的使用,如果有這個想法的請不要繼續閱讀,以免浪費時間。

Win32碎碎念

  1. 文字編碼:常見的有ASCIIGB2312Unicode等。
  2. Unicode只是一個符號集,它只規定了符號的二進制代碼,卻沒有規定這個二進制代碼應該如何存儲。Unicode不一定只占兩個字節,也可能是一個字節或者多個字節。
  3. TCHAR是一個宏,它是ASCII編碼還是Unicode編碼取決於項目的設置。
  4. 每個進程都有一個句柄表;多進程共享一個內核對象;句柄是否“可以”被繼承。
  5. 如果句柄不通過繼承得到,如果通過調用打開內核對象的API得到的句柄,和源創建內核對象得到的句柄可能是不同的。
  6. 模塊目錄與工作目錄:當前模塊路徑是不變的,文件放在哪就在哪。工作路徑是父進程通過CreateProcess這個API傳給。
  7. 把所有引用線程對象CloseHandle,並不會真正銷毀該線程對象,除非該線程執行完畢或被Terminate。
  8. malloc是假申請內存,它的本質的HeapAlloc,都是VirtualAlloc提前申請好的私有內存。
  9. 在局部變量創建線程並給線程傳參時,要確保這個局部變量的生命周期比線程長,否則局部變量所在函數執行完畢堆棧被清空導致錯誤。
  10. 進程的虛擬內存只有使用時才掛上對應的物理頁(物理內存按照4KB為一頁管理)
  11. 一個程序真正擁有低2GB的空間(相對4GB)
  12. 消息隊列:每個線程只有一個消息隊列
  13. TranslateMessage函數的作用是把鍵盤消息轉化為字符消息(WM_CHAR)

☀️ UTF-16/UTF-8/UTF-32Unicode的實現方式

1️⃣ UTF-16
  UTF-16編碼以16位無符號整數為單位,注意是16位為一個單位,不
表示一個字符就只有16位。這個要看字符的Unicode編碼處於什么范圍而定,有可能是2個字節,也可能是4個字節。現在機器上的Unicode編碼一般指的就是UTF-16
2️⃣ UTF-8編碼規則(網絡傳輸中含有較多字母時建議使用)

Unicode編碼(16進制) UTF-8字節流(二進制)
000000 - 00007F 0xXXXXXX
000080 - 0007FF 110xxxxx 10xxxxxx
000800-00FFFF 1110xxxx 10xxxxxx 10xxxxxx
010000- 10FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

3️⃣ UTF-32:以4個字節為單位,類比UTF-16

☀️ BOM(Byte Order Mark)

LE:小端存儲;BE:大端存儲

BOM
UTF-8 EF BB BF
UTF-16LE FF FE
UTF-16BE FE FF

☀️ C語言的寬字符

char(多字節字符類型) wchar_t(寬字符類型)
printf wprintf
strlen wcslen
strcpy wcscpy

☀️ Win系統中幾個重要的DLL

  1. Kernel32.dll:最核心的功能模塊,比如管理內存、進程和線程相關的函數等。
  2. User32.dll:是Windows用戶界面相關應用程序接口,如創建窗口和發送消息等。
  3. GDI32.dll:全稱是Graphical Device Interface(圖形設備接口),包含用於畫圖和顯示文本的函數。

☀️ 進程內存空間的地址划分

☀️ 進程的創建

1️⃣ 任何進程都是別的進程創建的: CreateProcess()
2️⃣ 創建過程

  1. 映射EXE文件
  2. 創建內核對象EPROCESS
  3. 映射系統DLL(ntdll.dll)
  4. 創建線程內核對象ETHREAD
  5. 如果是掛起的方式創建的(CREATE_SUSPENDED),就在這停了,等你Resume。
  6. 系統啟動線程:映射DLL(ntdll.LdrlnitializeThunk),線程開始執行

☀️ 什么是內核對象

  像進程、線程、文件、互斥體、事件等在內核都有一個對應的結構體,這些結構體由內核負責管理,這樣的對象叫做內核對象。

☀️ 如何讓線程暫停

讓自己停:Sleep()函數
讓別人停:SuspendThread()函數
線程恢復:ResumeThread()函數
【注意:掛起幾次線程就必須恢復幾次線程,線程才能繼續】

☀️ 等待線程結束

  1. WaitForSingleObject();
  2. WaitForMultipleObjects();
  3. GetExitCodeThread();

☀️ 設置、獲取線程上下文

BOOL GetThreadContext(
    HANDLE hThread,        // handle to thread with context
    LPCONTEXT lpContext    // context structure
    );

BOOL SetThreadContext(
    HANDLE hThread,             // handle to thread
    CONST CONTEXT*lpContext     // context structure
    );

☀️ 臨界區實現之線程鎖

  1. 創建全局變量

    CRITICAL_SECTION Cs;
    
  2. 初始化全局變量

    lnitializeCriticalSection(&cs);
    
  3. 實現臨界區

    EnterCriticalSection(&cs);
    //使用臨界資源
    LeaveCriticalSection(&cs);
    

☀️ 使用互斥體示例


HANDLE g__hMlutex =CreateHutex(NULL,FALSE,"XYZ");   //創建互斥體

WaitForSingle0bject(g_hMutex, INF INITE);   //獲取令牌

//操作代碼

ReleaseMutex(g_hMutex); //釋放令牌

☀️ 互斥體與線程鎖的區別

  1. 線程鎖只能用於單個進程間的線程控制
  2. 互斥體可以設定等待超時,但線程鎖不能
  3. 線程意外終結時,Mutex可以避免無限等待
  4. Mutex效率沒有線程鎖高

☀️ 線程互斥

 線程互斥是指對於共享的進程系統資源,在各單個線程訪問時的排它性。當有若干個線程都要使用某一共享資源時,任何時刻最多只允許一個線程去使用,其它要使用該資源的線程必須等待,直到占用資源者釋放該資源。

☀️ 線程同步(CreateEvent可以實現)

 線程同步是指線程之間所具有的一種制約關系,一個線程的執行依賴另一個線程的消息,當它沒有得到另一個線程的消息時應等待,直到消息到達時才被喚醒。

☀️ 窗體的本質

圖上的dll僅為編程提供接口,真正的實現在右邊的exe和sys文件

內核句柄:HANDLE;窗體句柄:HWND

☀️ GDI圖形設備接口(Graphics Device Interface)

☀️ 窗體是畫圖畫出來的

【注】如果不進行關聯的話,將使用默認的畫筆

HWND hwnd;
HDC hdc;
HPEN hpen;
//1. 設備對象畫在哪
hwnd = (HWND) /*HWND句柄值,為NULL則是桌面*/;

//2. 獲取設備對象上下文
hdc = GetDc(hwnd);

//3.創建畫筆設置線條的屬性
hpen = CreatePen(PS_soLID,5 ,RGB(0XFF,00,00));

//4. 關聯
Selectobject(hdc,hpen);

//5. 開始畫
MoueToEx(hdc,8,400,NULL);
LineTo(hdc,400,400) ;   // gdi32.d11

//6. 釋放資源
DeleteObject(hpen);
Re1easeDC(hwnd,hdc);

☀️ Win32工程入口函數

int APIENTRY WinMain(
    HINSTANCE hInstance,    //當前模塊的內存地址
    HINSTANCE hPrevInstance,    //NULL
    LPSTR lpCmdLine,    //命令行
    int nCmdShow    //顯示狀態
    )

☀️ 消息機制示意圖

☀️ 子窗口控件

  1. WINDOWS提供了幾個預定義的窗口類以方便我們的使用,我們一般就它們叫做子窗口控件,簡稱控件。
  2. 控件會自己處理消息,並在自己狀態發生改變時通知父窗口。
  3. 預定義的控件有:按鈕、復選框、編輯框、靜態字符串標簽和滾動條等。

☀️ 虛擬內存與物理內存的關系

☀️ 可供使用的物理內存

  1. MmNumberOfPhysicalPages × 4
  2. 虛擬內存(硬盤)

☀️ 能夠識別的物理內存

  32位系統最多可以識別物理內存為64GB,但由於操作系統的限制
比如XP,只能識別4GB(Windows 2003服務器版本可以識別4GB以上)。

☀️ 物理頁

一個程序對應的物理頁如果不經常使用,將會失去,轉到硬盤的虛擬內存。如果失去后,程序又要調用,,將走下圖的流程獲取。

☀️ 申請內存的兩種方式

  1. 通過VirtualAlloc/VirtualAllocEx申請的: Private Memory(只有該進程使用,別的不能使用)
  2. 通過CreateFileMapping映射的:Mapped Memory(可以公共使用)

☀️ 文件系統

 文件系統是操作系統用於管理磁盤上文件的方法和數據結構;簡單點說就是在磁盤上如何組織文件的方法。

1️⃣ EFS加密是指一個用戶在文件屬性-高級-加密以保護數據選中時,切換到另一個用戶,則該用戶無法訪問該文件。
2️⃣ 磁盤配額是指Admin賦予給其他用戶的磁盤空間,如果超過則拒絕。

☀️ 卷(在此電腦打開看到的驅動器)相關API

  1. 獲取卷:GetLogicalDrives()
  2. 獲取一個所卷的盤符的字符串:GetLogicalDrives()
  3. 獲取卷的類型:GetLogicalDrives()
  4. 獲取卷的類型:GetVolumelnformation()

☀️ 目錄相關API

  1. 創建目錄:CreateDirectory()
  2. 刪除目錄:RemoveDirectory()
  3. 修改目錄名稱:MoveFile()
  4. 獲取程序當前目錄:GetCurrentDirectory()
  5. 設置程序當前目錄:SetCurrentDirectory()

☀️ 文件相關API

  1. 創建文件:CreateFile()
  2. 關閉文件的:CloseHandle()
  3. 獲取文件長度:GetFileSize()
  4. 獲取文件的屬性和信息:GetFileAttributes()/GetFileAttributesEx()
  5. 讀/寫/拷貝/刪除文件:ReadFile()/WriteFile()/CopyFile()/DeleteFile()
  6. 查找文件:FindFirstFile()/FindNextFile()

☀️ 內存映射文件

☀️ 內存映射文件之共享

☀️ 寫拷貝


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM