zoukankan      html  css  js  c++  java
  • Mac内核XNU的Mach子系统的一个完整过程的代码跟踪

     

    一个完整的mach子系统

     

     

    mach子系统包括了很多内核功能的实现,比如VM子系统(内存管理)、host子系统(主机硬件信息的处理)、thread子系统(thread相关实现)、exc子系统(异常处理相关);现在拿thread_act为例来跟踪一下代码,希望能够简单地了解vm子系统的概况。

      

    (1)thread_act子系统的实现分为两部分:

     

    thread_actServer.c和thread_actUser.c,分别实现了内核中mach msg消息接收和发送的各个API。

     

    基本逻辑是:调用thread_actUser.c实现的API,接收到消息后thread_actServer.c的对应函数被调用,真正完成一些事情。

     

    说明一下,所有子系统的***Server.c和***User.c代码都是通过MIG由***.defs生成。

     

    (2)mach msg消息发送:

     

    下面是一个“类似系统调用”的函数(或者某个系统调用会间接调用这个函数),用于向thread_act子系统发送mach msg消息请求某个服务(可以当作RPC)。

     

    ------ xnu/osfmk/mach/thread_actUser.c ------

     

    /* Routine act_get_state */
    
    mig_external kern_return_t act_get_state
    
    (
    
             thread_act_t target_act,
    
             int flavor,
    
             thread_state_t old_state,
    
             mach_msg_type_number_t *old_stateCnt
    
    )
    
    {
    
     
    
    #ifdef  __MigPackStructs
    
    #pragma pack(4)
    
    #endif
    
             typedef struct {
    
                      mach_msg_header_t Head;
    
                      NDR_record_t NDR;
    
                      int flavor;
    
                      mach_msg_type_number_t old_stateCnt;
    
             } Request;
    
    #ifdef  __MigPackStructs
    
    #pragma pack()
    
    #endif
    
     
    
    #ifdef  __MigPackStructs
    
    #pragma pack(4)
    
    #endif
    
             typedef struct {
    
                      mach_msg_header_t Head;
    
                      NDR_record_t NDR;
    
                      kern_return_t RetCode;
    
                      mach_msg_type_number_t old_stateCnt;
    
                      natural_t old_state[224];
    
                      mach_msg_trailer_t trailer;
    
             } Reply;
    
    #ifdef  __MigPackStructs
    
    #pragma pack()
    
    #endif
    
     
    
    #ifdef  __MigPackStructs
    
    #pragma pack(4)
    
    #endif
    
             typedef struct {
    
                      mach_msg_header_t Head;
    
                      NDR_record_t NDR;
    
                      kern_return_t RetCode;
    
                      mach_msg_type_number_t old_stateCnt;
    
                      natural_t old_state[224];
    
             } __Reply;
    
    #ifdef  __MigPackStructs
    
    #pragma pack()
    
    #endif
    
             /*
    
              * typedef struct {
    
              *     mach_msg_header_t Head;
    
              *     NDR_record_t NDR;
    
              *     kern_return_t RetCode;
    
              * } mig_reply_error_t;
    
              */
    
     
    
             union {
    
                      Request In;
    
                      Reply Out;
    
             } Mess;
    
     
    
             Request *InP = &Mess.In;
    
             Reply *Out0P = &Mess.Out;
    
     
    
             mach_msg_return_t msg_result;
    
     
    
    #ifdef         __MIG_check__Reply__act_get_state_t__defined
    
             kern_return_t check_result;
    
    #endif        /* __MIG_check__Reply__act_get_state_t__defined */
    
     
    
             __DeclareSendRpc(3601, "act_get_state")
    
     
    
             InP->NDR = NDR_record;
    
     
    
             InP->flavor = flavor;
    
     
    
             if (*old_stateCnt < 224)
    
                      InP->old_stateCnt = *old_stateCnt;
    
             else
    
                      InP->old_stateCnt = 224;
    
     
    
             InP->Head.msgh_bits =
    
                      MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
    
             /* msgh_size passed as argument */
    
             InP->Head.msgh_request_port = target_act;
    
             InP->Head.msgh_reply_port = mig_get_reply_port();
    
             InP->Head.msgh_id = 3601;
    
     
    
             __BeforeSendRpc(3601, "act_get_state")
    
             msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, (mach_msg_size_t)sizeof(Request), (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
    
             __AfterSendRpc(3601, "act_get_state")
    
             if (msg_result != MACH_MSG_SUCCESS) {
    
                      __MachMsgErrorWithoutTimeout(msg_result);
    
                      { return msg_result; }
    
             }

     

    (3)thread_actServer.c中的mach msg消息接收:

     

    ------ xnu/osfmk/mach/thread_actServer.c ------

    /* Description of this subsystem, for use in direct RPC */
    
    const struct thread_act_subsystem {
    
             mig_server_routine_t         server;      /* Server routine */
    
             mach_msg_id_t start; /* Min routine number */
    
             mach_msg_id_t end;  /* Max routine number + 1 */
    
             unsigned int       maxsize;   /* Max msg size */
    
             vm_address_t   reserved;  /* Reserved */
    
             struct routine_descriptor    /*Array of routine descriptors */
    
                      routine[25];
    
    } thread_act_subsystem = {
    
             thread_act_server_routine,
    
             3600,
    
             3625,
    
             (mach_msg_size_t)sizeof(union __ReplyUnion__thread_act_subsystem),
    
             (vm_address_t)0,
    
             {
    
              { (mig_impl_routine_t) 0,
    
              (mig_stub_routine_t) _Xthread_terminate, 1, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__thread_terminate_t)},
    
              { (mig_impl_routine_t) 0,
    
              (mig_stub_routine_t) _Xact_get_state, 4, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__act_get_state_t)},
    
              { (mig_impl_routine_t) 0,
    
              (mig_stub_routine_t) _Xact_set_state, 4, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__act_set_state_t)},
    
              { (mig_impl_routine_t) 0,
    
              (mig_stub_routine_t) _Xthread_get_state, 4, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__thread_get_state_t)},
    
              { (mig_impl_routine_t) 0,
    
              (mig_stub_routine_t) _Xthread_set_state, 4, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__thread_set_state_t)},
    
              { (mig_impl_routine_t) 0,
    
              (mig_stub_routine_t) _Xthre
               ......

     

    解释一下上面的代码,声明并且实现了数据结构thread_act_subsystem,其中第6个成员是一个数组,数组的元素是一个结构 ---routine_descriptor;routine_descriptor声明如下:

     

    ------ xnu/osfmk/mach/mig.h ------

    struct routine_descriptor {
    
             mig_impl_routine_t     impl_routine;      /* Server work func pointer   */
    
             mig_stub_routine_t    stub_routine;     /* Unmarshalling func pointer */
    
             unsigned int                argc;                  /* Number of argument words   */
    
             unsigned int                descr_count;     /* Number complex descriptors */
    
             routine_arg_descriptor_t
    
                                                         arg_descr;                  /* pointer to descriptor array*/
    
             unsigned int                max_reply_msg;        /* Max size for reply msg     */
    
    };
    
    typedef struct routine_descriptor *routine_descriptor_t;
    
     
    
    typedef struct routine_descriptor mig_routine_descriptor;
    
    typedef mig_routine_descriptor *mig_routine_descriptor_t;

      

    (4)跟踪thread_act_subsystem中_Xthread_get_state的实现

     

    ------ xnu/osfmk/mach/thread_actServer.c ------

    /* Routine act_get_state */
    
    mig_internal novalue _Xact_get_state
    
             (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
    
    {
    
     
    
    #ifdef  __MigPackStructs
    
    #pragma pack(4)
    
    #endif
    
             typedef struct {
    
                      mach_msg_header_t Head;
    
                      NDR_record_t NDR;
    
                      int flavor;
    
                      mach_msg_type_number_t old_stateCnt;
    
                      mach_msg_trailer_t trailer;
    
             } Request;
    
    #ifdef  __MigPackStructs
    
    #pragma pack()
    
    #endif
    
             typedef __Request__act_get_state_t __Request;
    
             typedef __Reply__act_get_state_t Reply;
    
     
    
             /*
    
              * typedef struct {
    
              *     mach_msg_header_t Head;
    
              *     NDR_record_t NDR;
    
              *     kern_return_t RetCode;
    
              * } mig_reply_error_t;
    
              */
    
     
    
             Request *In0P = (Request *) InHeadP;
    
             Reply *OutP = (Reply *) OutHeadP;
    
    #ifdef         __MIG_check__Request__act_get_state_t__defined
    
             kern_return_t check_result;
    
    #endif        /* __MIG_check__Request__act_get_state_t__defined */
    
     
    
             __DeclareRcvRpc(3601, "act_get_state")
    
             __BeforeRcvRpc(3601, "act_get_state")
    
     
    
    #if     defined(__MIG_check__Request__act_get_state_t__defined)
    
             check_result = __MIG_check__Request__act_get_state_t((__Request *)In0P);
    
             if (check_result != MACH_MSG_SUCCESS)
    
                      { MIG_RETURN_ERROR(OutP, check_result); }
    
    #endif        /* defined(__MIG_check__Request__act_get_state_t__defined) */
    
     
    
             OutP->old_stateCnt = 224;
    
             if (In0P->old_stateCnt < OutP->old_stateCnt)
    
                      OutP->old_stateCnt = In0P->old_stateCnt;
    
     
    
             OutP->RetCode = act_get_state(In0P->Head.msgh_request_port, In0P->flavor, OutP->old_state, &OutP->old_stateCnt);
    
             if (OutP->RetCode != KERN_SUCCESS) {
    
                      MIG_RETURN_ERROR(OutP, OutP->RetCode);
    
             }
    
     
    
             OutP->NDR = NDR_record;
    
     
    
             OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 896) + (((4 * OutP->old_stateCnt)));
    
     
    
             __AfterRcvRpc(3601, "act_get_state")
    
    }

     

    为什么以thread_act为例呢?因为其他子系统比如vm,其中没有类似调用,感觉走到这里就是死胡同,没下文了。

    麻雀虽小,五脏俱全;thread_act虽然简单,但是结构很完整。注意上面有对函数act_get_state的调用,继续跟踪这个函数。

      

    (5)最终实现在这里

     

    ------ xnu/osfmk/kern/thread_act.c ------

    kern_return_t
    
    act_get_state(
    
             thread_t                               thread,
    
             int                                                 flavor,
    
             thread_state_t                     state,
    
             mach_msg_type_number_t        *count)
    
    {
    
        if (thread == current_thread())
    
                 return (KERN_INVALID_ARGUMENT);
    
     
    
        return (thread_get_state(thread, flavor, state, count));
    
    }
    
     

     

    其中调用的函数thread_get_state也有实现如下,可以函数调用到了最终的那个:

     

    ------ xnu/osfmk/kern/thread_act.c ------

    kern_return_t
    
    thread_get_state(
    
             register thread_t                 thread,
    
             int                                                 flavor,
    
             thread_state_t                     state,                          /* pointer to OUT array */
    
             mach_msg_type_number_t        *state_count)     /*IN/OUT*/
    
    {
    
             kern_return_t             result = KERN_SUCCESS;
    
     
    
             if (thread == THREAD_NULL)
    
                      return (KERN_INVALID_ARGUMENT);
    
     
    
             thread_mtx_lock(thread);
    
     
    
             if (thread->active) {
    
                      if (thread != current_thread()) {
    
                              thread_hold(thread);
    
     
    
                              thread_mtx_unlock(thread);
    
     
    
                              if (thread_stop(thread, FALSE)) {
    
                                       thread_mtx_lock(thread);
    
                                       result = machine_thread_get_state(
    
                                                                                            thread, flavor, state, state_count);
    
                                       thread_unstop(thread);
    
                              }
    
                              else {
    
                                       thread_mtx_lock(thread);
    
                                       result = KERN_ABORTED;
    
                              }
    
     
    
                              thread_release(thread);
    
                      }
    
                      else
    
                              result = machine_thread_get_state(
    
                                                                                   thread, flavor, state, state_count);
    
             }
    
             else
    
                      result = KERN_TERMINATED;
    
     
    
             thread_mtx_unlock(thread);
    
     
    
             return (result);
  • 相关阅读:
    Oracle解除死锁
    观察者模式
    观察者模式
    第一个go程序
    第一个go程序
    Jersey处理表单Post信息
    Jersey处理表单Post信息
    JS获取操作系统及浏览器信息
    JS获取操作系统及浏览器信息
    Linux常用命令
  • 原文地址:https://www.cnblogs.com/andypeker/p/4720572.html
Copyright © 2011-2022 走看看