1. 程式人生 > 其它 >羽夏筆記——Win32(非WinAPI)

羽夏筆記——Win32(非WinAPI)

比較翔實的聊一聊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;
  1. 初始化全域性變數
lnitializeCriticalSection(&cs);
  1. 實現臨界區
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()

☀️ 記憶體對映檔案

☀️ 記憶體對映檔案之共享

☀️ 寫拷貝

本文來自部落格園,作者:寂靜的羽夏,一個熱愛計算機技術的菜鳥,轉載請註明原文連結:https://www.cnblogs.com/wingsummer/p/15250378.html