实现IPC--的核心乃在于 “int SYSVEC”这个软中断以及与之对应的sys_call()这个函数。其实就是增加系统调用。
中断号为INT_VECTOR_SYS_CALL的系统调用函数就是sys_call
init_idt_desc(INT_VECTOR_SYS_CALL, DA_386IGate, sys_call, PRIVILEGE_USER);
系统调用函数sys_call通过sys_call_table数组表格以及eax为数组下标执行真正处理的函数
; =============================================================================
; sys_call
; =============================================================================
sys_call:
call save
sti
push esi
push dword [p_proc_ready]
push edx
push ecx
push ebx
call [sys_call_table + eax * 4]
add esp, 4 * 4
pop esi
mov [esi + EAXREG - P_STACKBASE], eax
cli
ret
PUBLIC system_call sys_call_table[NR_SYS_CALL] = {sys_printx, sys_sendrec};
INT_VECTOR_SYS_CALL equ 0x90
_NR_printx equ 0
_NR_sendrec equ 1
; ====================================================================================
; sendrec(int function, int src_dest, MESSAGE* msg);
; ====================================================================================
; Never call sendrec() directly, call send_recv() instead.
sendrec:
mov eax, _NR_sendrec
mov ebx, [esp + 4] ; function
mov ecx, [esp + 8] ; src_dest
mov edx, [esp + 12] ; p_msg
int INT_VECTOR_SYS_CALL
ret
sendrec()系统调用函数通过 int INT_VECTOR_SYS_CALL以及 mov eax, _NR_sendrec就会从sys_call_table查询到执行sys_sendrec函数。
/*****************************************************************************
* sys_sendrec
*****************************************************************************/
/**
* <Ring 0> The core routine of system call `sendrec()'.
*
* @param function SEND or RECEIVE
* @param src_dest To/From whom the message is transferred.
* @param m Ptr to the MESSAGE body.
* @param p The caller proc.
*
* @return Zero if success.
*****************************************************************************/
PUBLIC int sys_sendrec(int function, int src_dest, MESSAGE* m, struct proc* p)
{
assert(k_reenter == 0); /* make sure we are not in ring0 */
assert((src_dest >= 0 && src_dest < NR_TASKS + NR_PROCS) ||
src_dest == ANY ||
src_dest == INTERRUPT);
int ret = 0;
int caller = proc2pid(p);
MESSAGE* mla = (MESSAGE*)va2la(caller, m);
mla->source = caller;
assert(mla->source != src_dest);
/**
* Actually we have the third message type: BOTH. However, it is not
* allowed to be passed to the kernel directly. Kernel doesn't know
* it at all. It is transformed into a SEND followed by a RECEIVE
* by `send_recv()'.
*/
if (function == SEND) {
ret = msg_send(p, src_dest, m);
if (ret != 0)
return ret;
}
else if (function == RECEIVE) {
ret = msg_receive(p, src_dest, m);
if (ret != 0)
return ret;
}
else {
panic("{sys_sendrec} invalid function: "
"%d (SEND:%d, RECEIVE:%d).", function, SEND, RECEIVE);
}
return 0;
}
sys_sendrec( )这个函数被设计得相当简单,它可以描述为:把SEND消息交给msg_send( )处理,把RECEIVE消息交给msg_receive( )处理。

本文深入探讨了实现进程间通信(IPC)的核心机制,重点讲解了通过软中断和sys_call函数增加系统调用的过程。详细解析了sys_call_table数组如何使用eax作为下标来执行特定函数,以及sendrec()系统调用如何通过int指令和sys_sendrec函数进行消息发送与接收。
1万+

被折叠的 条评论
为什么被折叠?



