寫在前面
本筆記是由本人獨自整理出來的,圖片來源於網路。本人非計算機專業,可能對本教程涉及的事物沒有了解的足夠深入,如有錯誤,歡迎批評指正。 如有好的建議,歡迎反饋。碼字不易,如果本篇文章有幫助你的,如有閒錢,可以打賞支援我的創作。如想轉載,請把我的轉載資訊附在文章後面,並宣告我的個人資訊和本人部落格地址即可,但必須事先通知我。
本篇文章主要是讓讀者對
Win32
基本知識和底層有一個簡單的瞭解,並不是詳細介紹WinAPI
的使用,如果有這個想法的請不要繼續閱讀,以免浪費時間。
Win32碎碎念
- 文字編碼:常見的有
ASCII
、GB2312
、Unicode
等。 - Unicode只是一個符號集,它只規定了符號的二進位制程式碼,卻沒有規定這個二進位制程式碼應該如何儲存。Unicode不一定只佔兩個位元組,也可能是一個位元組或者多個位元組。
- TCHAR是一個巨集,它是ASCII編碼還是Unicode編碼取決於專案的設定。
- 每個程序都有一個控制代碼表;多程序共享一個核心物件;控制代碼是否“可以”被繼承。
- 如果控制代碼不通過繼承得到,如果通過呼叫開啟核心物件的API得到的控制代碼,和源建立核心物件得到的控制代碼可能是不同的。
- 模組目錄與工作目錄:當前模組路徑是不變的,檔案放在哪就在哪。工作路徑是父程序通過CreateProcess這個API傳給。
- 把所有引用執行緒物件CloseHandle,並不會真正銷燬該執行緒物件,除非該執行緒執行完畢或被Terminate。
- malloc是假申請記憶體,它的本質的HeapAlloc,都是VirtualAlloc提前申請好的私有記憶體。
- 在區域性變數建立執行緒並給執行緒傳參時,要確保這個區域性變數的生命週期比執行緒長,否則區域性變數所在函式執行完畢堆疊被清空導致錯誤。
- 程序的虛擬記憶體只有使用時才掛上對應的物理頁(實體記憶體按照4KB為一頁管理)
- 一個程式真正擁有低2GB的空間(相對4GB)
- 訊息佇列:每個執行緒只有一個訊息佇列
TranslateMessage
函式的作用是把鍵盤訊息轉化為字元訊息(WM_CHAR)
️ UTF-16
/UTF-8
/UTF-32
是Unicode
的實現方式
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
- Kernel32.dll:最核心的功能模組,比如管理記憶體、程序和執行緒相關的函式等。
- User32.dll:是Windows使用者介面相關應用程式介面,如建立視窗和傳送訊息等。
- GDI32.dll:全稱是Graphical Device Interface(圖形裝置介面),包含用於畫圖和顯示文字的函式。
️ 程序記憶體空間的地址劃分
️ 程序的建立
1️⃣ 任何程序都是別的程序建立的: CreateProcess()
2️⃣ 建立過程
- 對映EXE檔案
- 建立核心物件EPROCESS
- 對映系統DLL(ntdll.dll)
- 建立執行緒核心物件ETHREAD
- 如果是掛起的方式建立的(CREATE_SUSPENDED),就在這停了,等你Resume。
- 系統啟動執行緒:對映DLL(ntdll.LdrlnitializeThunk),執行緒開始執行
️ 什麼是核心物件
像程序、執行緒、檔案、互斥體、事件等在核心都有一個對應的結構體,這些結構體由核心負責管理,這樣的物件叫做核心物件。
️ 如何讓執行緒暫停
讓自己停:Sleep()函式
讓別人停:SuspendThread()函式
執行緒恢復:ResumeThread()函式
【注意:掛起幾次執行緒就必須恢復幾次執行緒,執行緒才能繼續】
️ 等待執行緒結束
- WaitForSingleObject();
- WaitForMultipleObjects();
- 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
);
️ 臨界區實現之執行緒鎖
- 建立全域性變數
CRITICAL_SECTION Cs;
- 初始化全域性變數
lnitializeCriticalSection(&cs);
- 實現臨界區
EnterCriticalSection(&cs);
//使用臨界資源
LeaveCriticalSection(&cs);
️ 使用互斥體示例
HANDLE g__hMlutex =CreateHutex(NULL,FALSE,"XYZ"); //建立互斥體
WaitForSingle0bject(g_hMutex, INF INITE); //獲取令牌
//操作程式碼
ReleaseMutex(g_hMutex); //釋放令牌
️ 互斥體與執行緒鎖的區別
- 執行緒鎖只能用於單個程序間的執行緒控制
- 互斥體可以設定等待超時,但執行緒鎖不能
- 執行緒意外終結時,Mutex可以避免無限等待
- 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 //顯示狀態
)
️ 訊息機制示意圖:
️ 子視窗控制元件:
- WINDOWS提供了幾個預定義的視窗類以方便我們的使用,我們一般就它們叫做子視窗控制元件,簡稱控制元件。
- 控制元件會自己處理訊息,並在自己狀態發生改變時通知父視窗。
- 預定義的控制元件有:按鈕、複選框、編輯框、靜態字串標籤和滾動條等。
️ 虛擬記憶體與實體記憶體的關係
️ 可供使用的實體記憶體:
- MmNumberOfPhysicalPages × 4
- 虛擬記憶體(硬碟)
️ 能夠識別的實體記憶體
32位系統最多可以識別實體記憶體為64GB,但由於作業系統的限制
比如XP,只能識別4GB(Windows 2003伺服器版本可以識別4GB以上)。
️ 物理頁
一個程式對應的物理頁如果不經常使用,將會失去,轉到硬碟的虛擬記憶體。如果失去後,程式又要呼叫,,將走下圖的流程獲取。
️ 申請記憶體的兩種方式:
- 通過VirtualAlloc/VirtualAllocEx申請的: Private Memory(只有該程序使用,別的不能使用)
- 通過CreateFileMapping對映的:Mapped Memory(可以公共使用)
️ 檔案系統
檔案系統是作業系統用於管理磁碟上檔案的方法和資料結構;簡單點說就是在磁碟上如何組織檔案的方法。
1️⃣ EFS加密是指一個使用者在檔案屬性-高階-加密以保護資料選中時,切換到另一個使用者,則該使用者無法訪問該檔案。
2️⃣ 磁碟配額是指Admin賦予給其他使用者的磁碟空間,如果超過則拒絕。
️ 卷(在此電腦開啟看到的驅動器)相關API
- 獲取卷:GetLogicalDrives()
- 獲取一個所卷的碟符的字串:GetLogicalDrives()
- 獲取卷的型別:GetLogicalDrives()
- 獲取卷的型別:GetVolumelnformation()
️ 目錄相關API
- 建立目錄:CreateDirectory()
- 刪除目錄:RemoveDirectory()
- 修改目錄名稱:MoveFile()
- 獲取程式當前目錄:GetCurrentDirectory()
- 設定程式當前目錄:SetCurrentDirectory()
️ 檔案相關API
- 建立檔案:CreateFile()
- 關閉檔案的:CloseHandle()
- 獲取檔案長度:GetFileSize()
- 獲取檔案的屬性和資訊:GetFileAttributes()/GetFileAttributesEx()
- 讀/寫/拷貝/刪除檔案:ReadFile()/WriteFile()/CopyFile()/DeleteFile()
- 查詢檔案:FindFirstFile()/FindNextFile()