最近面試遇到的Windows相關的題目
上週準備在公司內部轉崗,面了3個部門windows客戶端相關的工作,最終拿到3個Offer,主要涉及C++和Windows兩大塊內容,C++的題目基本都答上了,Windows一直都是我的弱項,在這裡記錄一下Windows相關的題目。有些答不上的問題就沒列出來,還有些問題忘了,下面的答案有些大部分是我自己的理解,有些是直接從網上copy的,有問題大家可以討論。
1:GetMessage和PeekMessage的區別?
GetMessage:獲取訊息佇列中的一個訊息,存入MSG中,並從訊息佇列中移除,如果訊息佇列中沒有訊息就會阻塞;
PeekMessage:檢視訊息,有訊息,就將資料存入MSG結構中,沒有訊息就返回FALSE,不會阻塞,但如果沒有更新區,可以移除WM_PAINT訊息,還可以通過最後一個引數來決定是否從佇列中移除檢視的訊息;
2:SendMessage和PostMessage的區別?怎麼跨執行緒發訊息?怎麼跨程序發訊息?SendMessage在程序間發訊息要注意什麼?SendMessage能將訊息傳送到訊息佇列嗎?PostMessage可以在程序間發訊息嗎?兩個執行緒互相SendMessage會出問題嗎?
SendMessage:將一個訊息傳送到指定視窗的視窗過程中,等視窗過程執行完了再返回;
PostMessage:將訊息傳送到指定視窗所線上程的訊息佇列中,直接返回,訊息是否被處理完全不知道;
SendMessage直接呼叫視窗過程,那它是否可以將訊息傳送到傳送到執行緒的訊息佇列中呢?
可以啊,比如傳送一個WM_PAINT訊息,這是一個佇列訊息,只有存在無效區域的情況下,才會處理WM_PAINT訊息;
執行緒間SendMessage,由於它基本就是呼叫指定視窗的視窗過程,當跨執行緒發訊息的時候,無法呼叫指定視窗的視窗過程,在跨執行緒傳送;
訊息的時候,傳送執行緒會先掛起,由系統執行緒將訊息傳送到接收執行緒的另一個佇列中,並設定QS_SENDMESSAGE標誌,當系統檢測到這個標誌後,就會處理這個佇列的訊息,當這個訊息被處理之後,呼叫SendMessage的執行緒就會被喚醒,就繼續執行。
SendMessage是可以跨程序發訊息的,通過FindWindow找到對方程序的視窗控制代碼,發一個訊息過去就行了,由於兩個程序間的記憶體是完全獨立的,不能髮指針,如果要發資料,就用WM_COPYDATA。
PostMessage可以在程序間發訊息,但不能結合WM_COPYDATA使用,WM_COPYDATA通過記憶體對映在程序間傳遞資料,PostMessage後對映檔案的控制代碼就無效了。
兩個執行緒互相SendMessage可能會導致死鎖,A執行緒鎖住一個資源,向B執行緒發一個訊息,A執行緒掛起,這時如果B執行緒在處理A執行緒的訊息需要A執行緒鎖住的資源,A由於發給B的訊息還沒有處理完就一直不能返回,鎖也沒有開啟,B執行緒又用不了,訊息也就處理不完,結果就死鎖了。
3:Windows是怎麼實現視窗重新整理的?怎麼實現視窗的立即重新整理?
Update Region不為空時,系統就會自動產生WM_PAINT訊息,通過InvalidateRect和InvalidateRgn可把指定的區域加到視窗的Update Region中,通過處理WM_PAINT訊息來實現視窗的重新整理。 系統為什麼不在呼叫Invalidate時傳送WM_PAINT訊息呢?又為什麼非要等應用訊息佇列為空時才傳送WM_PAINT訊息呢?這是因為系統把在視窗中的繪製操作當作一種低優先順序的操作,於是儘可能地推後做。不過這樣也有利於提高繪製的效率:兩個WM_PAINT訊息之間通過InvalidateRect和InvaliateRgn使之失效的區域就會被累加起來,然後在一個WM_PAINT訊息中一次得到更新,不僅能避免多次重複地更新同一區域,也優化了應用的更新操作。
如果視窗更新的區域不為空,UpdateWindow函式通過傳送一個WM_PAINT訊息來更新指定視窗的客戶區。函式繞過應用程式的訊息佇列,直接傳送WM_PAINT訊息給指定視窗的視窗過程,如果更新區域為空,則不傳送訊息。
WM_PAINT一般在訊息佇列中沒有訊息的時候才處理,有時候我們需要立即重新整理視窗,那麼就需要UpdateWindow函數了,直接繞過訊息迴圈,只要更新區域不為空,將WM_PAINT訊息直接傳送到指定視窗過程即可。
Invalidate(hwnd); //將視窗設為不可用,導致更新區域不為空
UpdateWindow(hwnd); //立即重新整理視窗
4:Windows訊息迴圈有哪幾個函式,各自的作用是什麼?訊息迴圈是怎麼退出的?
while(GetMessage(&msg, NULL, 0, 0)) //獲取一個訊息,成功後會放在msg中。
{
TranslateMessage(&msg); //訊息進行必要的處理轉換。
DispatchMessage(&msg); //呼叫WinProc,將msg的各項資訊傳遞給WinProc
}
當GetMessage獲取到的訊息是WM_QUIT,返回的就是FALSE,while迴圈就退出了,訊息迴圈也就終止了。
5:控制代碼是什麼?
控制代碼就是一個整數,Windows為每一個控制元件指定了一個唯一的整數,通過這個整數和相關函式操作控制元件。
6:Windows實現執行緒間同步有哪些方法?實現程序間同步又有哪些方法?讀寫鎖的實現原理是什麼?
1:volatile
2:關鍵段
3:旋轉鎖
4:讀寫鎖
5:事件物件
6:訊號量
7:互斥量
只要是核心物件,就能用於程序間的同步,核心物件不屬於任何程序,由系統管理。
讀寫鎖實際是一種特殊的自旋鎖,它把對共享資源的訪問者劃分成讀者和寫者,讀者只對共享資源進行讀訪問,寫者則需要對共享資源進行寫操作。這種鎖相對於自旋鎖而言,能提高併發性,因為在多處理器系統中,它允許同時有多個讀者來訪問共享資源,最大可能的讀者數為實際的邏輯CPU數。寫者是排他性的,一個讀寫鎖同時只能有一個寫者或多個讀者 (與CPU數相關),但不能同時既有讀者又有寫者。我覺得他其實就是對關鍵段和核心事件物件的封裝。寫的時候獨佔,讀的時候共享。
7:模態視窗的實現原理?模態視窗會導致崩潰嗎?
模態視窗其實就是在當前視窗呼叫系統的訊息迴圈,響應使用者的操作,將相關的訊息傳送到對應的視窗。將父視窗設為不可用,即不能響應使用者的操作,在關閉當前視窗的時候,將父視窗設為可用,並退出訊息迴圈。
可能導致視窗崩潰,模態視窗顯示的時候,除了父視窗不可用之外,其他的視窗都是可用的,如果需要的一個資源在別的地方被釋放了,而在模態視窗中使用的時候,沒有判斷可能就會導致崩潰。
8:你瞭解沙箱,UAC相關的知識嗎?
不瞭解
9:怎麼實現執行緒間發訊息?執行緒的訊息佇列預設會建立嗎?
SendMessage可以再執行緒間發訊息,PostThreadMessage通過執行緒ID可以線上程間發訊息,將訊息傳送到指定執行緒的訊息佇列中。執行緒的訊息佇列預設是不會建立的,因為執行緒的訊息佇列並不是必須的。通過ResumeThread(threadHwnd);可以建立執行緒的訊息佇列。
10:說說Windows的記憶體管理,怎麼實現記憶體共享?
FileMapping用於將存在於磁碟的檔案放進一個程序的虛擬地址空間,並在該程序的虛擬地址空間中產生一個區域用於“存放”該檔案,這個空間就叫做 File View,系統並同時產生一個File Mapping Object(存放於物理記憶體中)用於維持這種對映關係,這樣當多個程序需要讀寫那個檔案的資料時,它們的File View其實對應的都是同一個File Mapping Object,這樣做可節省記憶體和保持資料的同步性,並達到資料共享的目的。
第四輪面試官:如果加班嚴重你來嗎?
阿漢:不來
第四輪面試官:你確定嗎?
阿漢:確定
第四輪面試官:我沒有問題了,你還有什麼要問的嗎?
接下來是第五輪面試……我只是內部轉崗啊,面了五輪整整四個小時,最後哥還是從了這個部門。