标签:
一个完整的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://www.cnblogs.com/andypeker/p/4720572.html