标签:
一个完整的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的对应函数被调用,真正完成一些事情。
说明一下,所有子系统的***Server.c和***User.c代码都是通过MIG由***.defs生成。
下面是一个“类似系统调用”的函数(或者某个系统调用会间接调用这个函数),用于向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; }
}
------ 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);
标签:
原文地址:http://my.oschina.net/u/614221/blog/490641