分享

minix3内核代码注释

 orion360doc 2014-02-11

分类:

IPC是在内核最底层实现的,它的重要性不言而喻,下面试着分析minix3的ipc实现。
在include/minix/ipc.h中可以看到message结构体的定义

typedef struct {
  int m_source;            /* 消息的发送源*/
  int m_type;            /* 消息的类型*/
  union {           
    mess_1 m_m1;
    mess_2 m_m2;
    mess_3 m_m3;
    mess_4 m_m4;
    mess_5 m_m5;
    mess_7 m_m7;
    mess_8 m_m8;
  } m_u;          /* 这个联合为消息的内容 消息的格式由消息类型决定*/
} message;

七种不同的消息内容格式如下:(在386平台下,int为32位 short为16位 long为32位 指针为32位)

 

typedef struct {int m1i1, m1i2, m1i3; char *m1p1, *m1p2, *m1p3;} mess_1; /* 类型1 3整形3指针 24个字节*/
typedef struct {int m2i1, m2i2, m2i3; long m2l1, m2l2; char *m2p1;} mess_2;/* 类型2 3整形1长整形2指针 24个字节*/
typedef struct {int m3i1, m3i2; char *m3p1; char m3ca1[M3_STRING];} mess_3;/* 类型3 2整形1指针14个字符 26个字节*/
typedef struct {long m4l1, m4l2, m4l3, m4l4, m4l5;} mess_4;
/* 类型4 5长整形 20个字节*/
typedef struct {short m5c1, m5c2; int m5i1, m5i2; long m5l1, m5l2, m5l3;}mess_5;/* 类型5 2短整形2整形3长整形 24个字节*/
typedef struct {int m7i1, m7i2, m7i3, m7i4; char *m7p1, *m7p2;} mess_7;/* 类型7 4整形2指针 24个字节*/
typedef struct {int m8i1, m8i2; char *m8p1, *m8p2, *m8p3, *m8p4;} mess_8;/* 类型8 2整形4指针 24个字节*/

在include/minix/ipc.h中可以看到函数的声明

 

/*==========================================================================*
 * Minix run-time system (IPC).                      *
 *==========================================================================*/

#define echo        _echo 
#define notify        _notify
#define sendrec        _sendrec
#define receive        _receive
#define send        _send

_PROTOTYPE( int echo, (message *m_ptr)                    );
_PROTOTYPE( int notify, (int dest)                    );
_PROTOTYPE( int sendrec, (int src_dest, message *m_ptr)            );
_PROTOTYPE( int receive, (int src, message *m_ptr)            );
_PROTOTYPE( int send, (int dest, message *m_ptr)            );
//一组API
#define ipc_request    _ipc_request
#define ipc_reply    _ipc_reply
#define ipc_notify    _ipc_notify
#define ipc_select    _ipc_select

_PROTOTYPE( int ipc_request, (int dst, message *m_ptr)            );
_PROTOTYPE( int ipc_reply, (int dst, message *m_ptr)            );
_PROTOTYPE( int ipc_notify, (int dst, long event_set)            );
_PROTOTYPE( int ipc_receive, (int src, long events, message *m_ptr)    );
//另外一组API 没有发现实现的代码

#endif /* _IPC_H */

以上IPC API函数的实现均是通过int指令trap调用系统调用

_send的代码为例,其余都大体类似

 

__send:
    push    ebp
    mov    ebp, esp
    push    ebx
    mov    eax, SRC_DST(ebp)    ! eax 目标地址
    mov    ebx, MESSAGE(ebp)    ! ebx 放消息指针
    mov    ecx, SEND        ! SEND标识
    int    SYSVEC            ! trap调度mpx386.s中的_s_call

    pop    ebx
    pop    ebp
    ret

以上IPC函数都是通过int SYSVEC 实现 不过对应的ecx值是不同的

mpx386.s中的_s_call代码如下

 

    .align    16
_s_call:
_p_s_call:
    cld            ! set direction flag to a known value
    sub    esp, 6*4    ! skip RETADR, eax, ecx, edx, ebx, est
    push    ebp        ! stack already points into proc table
    push    esi
    push    edi
    o16    push    ds
    o16    push    es
    o16    push    fs
    o16    push    gs
    mov    si, ss        ! ss is kernel data segment
    mov    ds, si        ! load rest of kernel segments
    mov    es, si        ! kernel does not use fs, gs
    incb    (_k_reenter)    ! increment kernel entry count
    mov    esi, esp    ! assumes P_STACKBASE == 0
    mov    esp, k_stktop
    xor    ebp, ebp    ! for stacktrace
                ! end of inline save
                ! now set up parameters for sys_call()
    push    edx        ! event set or flags bit map
    push    ebx        ! pointer to user message
    push    eax        ! source / destination
    push    ecx        ! call number (ipc primitive to use)
    call    _sys_call    ! 调用sys_call(call_nr, src_dst, m_ptr, bit_map)
                ! caller is now explicitly in proc_ptr
    mov    AXREG(esi), eax    ! sys_call MUST PRESERVE si

sys_call()的核心部分如下:

 

switch(function) {//判断要执行的任务
  case SENDREC:

//send和sendrec的区别在于sendrec发送信息后要挂起等待接收回复信息

      caller_ptr->p_misc_flags |= REPLY_PENDING;
  case SEND:            
      result = mini_send(caller_ptr, src_dst_e, m_ptr, flags);
      if (function == SEND || result != OK) {    
          break;                /* 若是SEND 就可以返回了*/
      }                        /* 若是SENDREC 将继续执行以下部分*/
  case RECEIVE:            
      if (function == RECEIVE)
          caller_ptr->p_misc_flags &= ~REPLY_PENDING;

//清除等待回复位
      result = mini_receive(caller_ptr, src_dst_e, m_ptr, flags);

//接收消息
      break;
  case NOTIFY:   //仅仅发送一个notification
      result = mini_notify(caller_ptr, src_dst);
      break;
  case ECHO:    //仅仅将消息原地复制一遍
      CopyMess(caller_ptr->p_nr, caller_ptr, m_ptr, caller_ptr, m_ptr);
      result = OK;
      break;
  default:
      result = EBADCALL;            /* 非法系统调用*/
  }

以上看出在minix3内核中,系统调用实现的仅仅是IPC功能,

且通过sys_call()函数可以看出ipc_系列的API都没有实现。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多