一個完整的mach子系統數組
mach子系統包括了不少內核功能的實現,好比VM子系統(內存管理)、host子系統(主機硬件信息的處理)、thread子系統(thread相關實現)、exc子系統(異常處理相關);如今拿thread_act爲例來跟蹤一下代碼,但願可以簡單地瞭解vm子系統的概況。數據結構
thread_actServer.c和thread_actUser.c,分別實現了內核中mach msg消息接收和發送的各個API。函數
基本邏輯是:調用thread_actUser.c實現的API,接收到消息後thread_actServer.c的對應函數被調用,真正完成一些事情。this
說明一下,全部子系統的***Server.c和***User.c代碼都是經過MIG由***.defs生成。spa
下面是一個「相似系統調用」的函數(或者某個系統調用會間接調用這個函數),用於向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; }
}
------ 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;
------ 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的調用,繼續跟蹤這個函數。
------ 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);