Mac內核XNU的Mach子系統的一個完整過程的代碼跟蹤



 

一個完整的mach系統數組

 

 

mach子系統包括了不少內核功能的實現,好比VM子系統(內存管理)、host子系統(主機硬件信息的處理)、thread子系統(thread相關實現)、exc子系統(異常處理相關);如今拿thread_act爲例來跟蹤一下代碼,但願可以簡單地瞭解vm子系統的概況。數據結構

 

 

 

1thread_act子系統的實現分爲兩部分

 

thread_actServer.c和thread_actUser.c,分別實現了內核中mach msg消息接收和發送的各個API。函數

 

基本邏輯是:調用thread_actUser.c實現的API,接收到消息後thread_actServer.c的對應函數被調用,真正完成一些事情。this

 

說明一下,全部子系統的***Server.c***User.c代碼都是經過MIG***.defs生成。spa

 

 

2mach msg消息發送

 

下面是一個「相似系統調用」的函數(或者某個系統調用會間接調用這個函數),用於向thread_act子系統發送mach msg消息請求某個服務(能夠看成RPC)。code

 

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

/* Routine act_get_state */ip

mig_external kern_return_t act_get_state內存

(get

         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; }

         }

 

 

3thread_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_descriptorroutine_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);

相關文章
相關標籤/搜索