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);
原文地址:https://www.cnblogs.com/andypeker/p/4720572.html