orange's学习--第八章:实现IPC--增加系统调用

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

实现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( )处理。 
 

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值