學習的最好方法就是看代碼,所以我們不妨跟著 IPC 的調用路線圖,來學習學習 IPC。
從 x01.Lab.Download 下載代碼后,首先進入 main.c 文件,在 TestA 中,有這么一句:PRint("<Ticks:%x>", GetTicksIPC()); 其中,GetTicksIPC 就是通過 IPC 獲取時間 tick 數。進入 GetTicksIPC,會看到如下代碼:
1 m.type = M_GetTicks;2 _SendReceive(M_Both, T_IPC, &m);3 return m.M_RetValue;
_SendReceive 是對 syscall.s 文件中的 SendReceive 封裝。調用 SendReceive 會產生一個中斷而進入 SysSendReceive(在 proc.c 文件中)。顧名思義,SysSendReceive 根據消息類型,進行相應處理?,F在有個問題,就是消息不止一種,每種又不止一個,處理這么多消息,需要有個生生不息的發動機。這個發動機,就是 IPC 任務,進入 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 中,先接收所有的消息,再根據消息的類型進行處理,處理后的結果由 _SendReceive 發送出去。這同微軟的消息處理機制如出一轍。
TaskIPC 在任務表中,由Schedule 進行調用。而Schedule 則由時鐘中斷周而復始的調用之。生生不息的機制原來在此!
由終端進入工程目錄,make 后 bochs,可看到效果圖如下:
看來,我們的 IPC 機制,已然發揮作用了。
不過,說實話,這套消息機制,看起來優雅,但多了幾次調用,效率是大打折扣的。從設計看優雅,從實際看卻不理想。二者不可兼得,還是要從實際出發。也難怪 linux 要舍棄這套近乎完美的消息處理機制,而采用宏內核了。
新聞熱點
疑難解答