學(xué)習(xí)的最好方法就是看代碼,所以我們不妨跟著 IPC 的調(diào)用路線圖,來學(xué)習(xí)學(xué)習(xí) IPC。
從 x01.Lab.Download 下載代碼后,首先進入 main.c 文件,在 TestA 中,有這么一句:PRint("<Ticks:%x>", GetTicksIPC()); 其中,GetTicksIPC 就是通過 IPC 獲取時間 tick 數(shù)。進入 GetTicksIPC,會看到如下代碼:
1 m.type = M_GetTicks;2 _SendReceive(M_Both, T_IPC, &m);3 return m.M_RetValue;
_SendReceive 是對 syscall.s 文件中的 SendReceive 封裝。調(diào)用 SendReceive 會產(chǎn)生一個中斷而進入 SysSendReceive(在 proc.c 文件中)。顧名思義,SysSendReceive 根據(jù)消息類型,進行相應(yīng)處理。現(xiàn)在有個問題,就是消息不止一種,每種又不止一個,處理這么多消息,需要有個生生不息的發(fā)動機。這個發(fā)動機,就是 IPC 任務(wù),進入 ipc.c 文件,可看到如下代碼:
1 #include "kstd.h" 2 3 void TaskIPC() { 4 Message msg; 5 while (1) { 6 _SendReceive(M_Receive, T_Any, &msg); 7 int src = msg.source; 8 switch (msg.type) { 9 case M_GetTicks:10 msg.M_RetValue = g_Ticks;11 _SendReceive(M_Send, src, &msg);12 break;13 default:14 Panic("Unknown message type!");15 break;16 }17 }18 }
這一下就明白了,原來,在 TaskIPC 中,先接收所有的消息,再根據(jù)消息的類型進行處理,處理后的結(jié)果由 _SendReceive 發(fā)送出去。這同微軟的消息處理機制如出一轍。
TaskIPC 在任務(wù)表中,由Schedule 進行調(diào)用。而Schedule 則由時鐘中斷周而復(fù)始的調(diào)用之。生生不息的機制原來在此!
由終端進入工程目錄,make 后 bochs,可看到效果圖如下:
看來,我們的 IPC 機制,已然發(fā)揮作用了。
不過,說實話,這套消息機制,看起來優(yōu)雅,但多了幾次調(diào)用,效率是大打折扣的。從設(shè)計看優(yōu)雅,從實際看卻不理想。二者不可兼得,還是要從實際出發(fā)。也難怪 linux 要舍棄這套近乎完美的消息處理機制,而采用宏內(nèi)核了。
新聞熱點
疑難解答