- 论坛徽章:
- 0
|
本帖最后由 71v5 于 2014-06-25 21:00 编辑
个人觉的freebsd内核子系统的初始化过程比linux更清晰,这主要归功于SYSINIT框架。SYSINIT的基本原理就是构造一个数据结构,将该数据结构的地址放到
一个统一的数据节中,这样当内核初始化时,就会处理该数据节中的数据。有两种时刻需要使用SYSINIT:系统启动或内核模块加载时, 系统析构或
内核模块卸载时。
SYSINIT的标准形式如下:- SYSINIT(uniquifier, subsystem, order, func, ident)
复制代码 SYSINIT宏建立了一种让系统能够够按顺序启动的两级结构,参数subsystem这第一级,每个子系统都有一个特殊的数字常量,这个数字常量确定了在第一级
里的启动顺序;第二级参数数据哦order,如果第一级相同,那么order确定了在第一级相同时的加载顺序。
uniquifier:标识符
subsystem:第一级参数
order:第二级参数
func:初始化函数
ident:初始化函数的参数
[subsystem]:
subsystem可以取值如下,这也提供了一种学习bsd内核的方法,如果按照这个顺序把相应的初始化函数分析完,那么freebsd内核你已经掌握的差不多了:- 70 /*
- 71 * Enumerated types for known system startup interfaces.
- 72 *
- 73 * Startup occurs in ascending numeric order; the list entries are
- 74 * sorted prior to attempting startup to guarantee order. Items
- 75 * of the same level are arbitrated for order based on the 'order'
- 76 * element.
- 77 *
- 78 * These numbers are arbitrary and are chosen ONLY for ordering; the
- 79 * enumeration values are explicit rather than implicit to provide
- 80 * for binary compatibility with inserted elements.
- 81 *
- 82 * The SI_SUB_RUN_SCHEDULER value must have the highest lexical value.
- 83 *
- 84 * The SI_SUB_SWAP values represent a value used by
- 85 * the BSD 4.4Lite but not by FreeBSD; it is maintained in dependent
- 86 * order to support porting.
- 87 */
- 88 enum sysinit_sub_id {
- 89 SI_SUB_DUMMY = 0x0000000, /* not executed; for linker*/
- 90 SI_SUB_DONE = 0x0000001, /* processed*/
- 91 SI_SUB_TUNABLES = 0x0700000, /* establish tunable values */
- 92 SI_SUB_COPYRIGHT = 0x0800001, /* first use of console*/
- 93 SI_SUB_SETTINGS = 0x0880000, /* check and recheck settings */
- 94 SI_SUB_MTX_POOL_STATIC = 0x0900000, /* static mutex pool */
- 95 SI_SUB_LOCKMGR = 0x0980000, /* lockmgr locks */
- 96 SI_SUB_VM = 0x1000000, /* virtual memory system init*/
- 97 SI_SUB_KMEM = 0x1800000, /* kernel memory*/
- 98 SI_SUB_KVM_RSRC = 0x1A00000, /* kvm operational limits*/
- 99 SI_SUB_WITNESS = 0x1A80000, /* witness initialization */
- 100 SI_SUB_MTX_POOL_DYNAMIC = 0x1AC0000, /* dynamic mutex pool */
- 101 SI_SUB_LOCK = 0x1B00000, /* various locks */
- 102 SI_SUB_EVENTHANDLER = 0x1C00000, /* eventhandler init */
- 103 SI_SUB_VNET_PRELINK = 0x1E00000, /* vnet init before modules */
- 104 SI_SUB_KLD = 0x2000000, /* KLD and module setup */
- 105 SI_SUB_CPU = 0x2100000, /* CPU resource(s)*/
- 106 SI_SUB_RACCT = 0x2110000, /* resource accounting */
- 107 SI_SUB_RANDOM = 0x2120000, /* random number generator */
- 108 SI_SUB_KDTRACE = 0x2140000, /* Kernel dtrace hooks */
- 109 SI_SUB_MAC = 0x2180000, /* TrustedBSD MAC subsystem */
- 110 SI_SUB_MAC_POLICY = 0x21C0000, /* TrustedBSD MAC policies */
- 111 SI_SUB_MAC_LATE = 0x21D0000, /* TrustedBSD MAC subsystem */
- 112 SI_SUB_VNET = 0x21E0000, /* vnet 0 */
- 113 SI_SUB_INTRINSIC = 0x2200000, /* proc 0*/
- 114 SI_SUB_VM_CONF = 0x2300000, /* config VM, set limits */
- 115 SI_SUB_DDB_SERVICES = 0x2380000, /* capture, scripting, etc.*/
- 116 SI_SUB_RUN_QUEUE = 0x2400000, /* set up run queue */
- 117 SI_SUB_KTRACE = 0x2480000, /* ktrace */
- 118 SI_SUB_OPENSOLARIS = 0x2490000, /* OpenSolaris compatibility */
- 119 SI_SUB_CYCLIC = 0x24A0000, /* Cyclic timers */
- 120 SI_SUB_AUDIT = 0x24C0000, /* audit */
- 121 SI_SUB_CREATE_INIT = 0x2500000, /* create init process 创建1号进程 */
- 122 SI_SUB_SCHED_IDLE = 0x2600000, /* required idle procs 创建每cpu上的idle线程 */
- 123 SI_SUB_MBUF = 0x2700000, /* mbuf subsystem */
- 124 SI_SUB_INTR = 0x2800000, /* interrupt threads */
- 125 SI_SUB_SOFTINTR = 0x2800001, /* start soft interrupt thread */
- 126 SI_SUB_ACL = 0x2900000, /* start for filesystem ACLs */
- 127 SI_SUB_DEVFS = 0x2F00000, /* devfs ready for devices */
- 128 SI_SUB_INIT_IF = 0x3000000, /* prep for net interfaces */
- 129 SI_SUB_NETGRAPH = 0x3010000, /* Let Netgraph initialize */
- 130 SI_SUB_DTRACE = 0x3020000, /* DTrace subsystem */
- 131 SI_SUB_DTRACE_PROVIDER = 0x3048000, /* DTrace providers */
- 132 SI_SUB_DTRACE_ANON = 0x308C000, /* DTrace anon enabling */
- 133 SI_SUB_DRIVERS = 0x3100000, /* Let Drivers initialize */
- 134 SI_SUB_CONFIGURE = 0x3800000, /* Configure devices */
- 135 SI_SUB_VFS = 0x4000000, /* virtual filesystem*/
- 136 SI_SUB_CLOCKS = 0x4800000, /* real time and stat clocks*/
- 137 SI_SUB_CLIST = 0x5800000, /* clists*/
- 138 SI_SUB_SYSV_SHM = 0x6400000, /* System V shared memory*/
- 139 SI_SUB_SYSV_SEM = 0x6800000, /* System V semaphores*/
- 140 SI_SUB_SYSV_MSG = 0x6C00000, /* System V message queues*/
- 141 SI_SUB_P1003_1B = 0x6E00000, /* P1003.1B realtime */
- 142 SI_SUB_PSEUDO = 0x7000000, /* pseudo devices */
- 143 SI_SUB_EXEC = 0x7400000, /* execve() handlers */
- 144 SI_SUB_PROTO_BEGIN = 0x8000000, /* VNET initialization */
- 145 SI_SUB_PROTO_IF = 0x8400000, /* interfaces*/
- 146 SI_SUB_PROTO_DOMAININIT = 0x8600000, /* domain registration system */
- 147 SI_SUB_PROTO_DOMAIN = 0x8800000, /* domains (address families?)*/
- 148 SI_SUB_PROTO_IFATTACHDOMAIN = 0x8800001, /* domain dependent data init*/
- 149 SI_SUB_PROTO_END = 0x8ffffff, /* VNET helper functions */
- 150 SI_SUB_KPROF = 0x9000000, /* kernel profiling*/
- 151 SI_SUB_KICK_SCHEDULER = 0xa000000, /* start the timeout events*/
- 152 SI_SUB_INT_CONFIG_HOOKS = 0xa800000, /* Interrupts enabled config */
- 153 SI_SUB_ROOT_CONF = 0xb000000, /* Find root devices */
- 154 SI_SUB_DUMP_CONF = 0xb200000, /* Find dump devices */
- 155 SI_SUB_RAID = 0xb380000, /* Configure GEOM classes */
- 156 SI_SUB_SWAP = 0xc000000, /* swap */
- 157 SI_SUB_INTRINSIC_POST = 0xd000000, /* proc 0 cleanup*/
- 158 SI_SUB_SYSCALLS = 0xd800000, /* register system calls */
- 159 SI_SUB_VNET_DONE = 0xdc00000, /* vnet registration complete */
- 160 SI_SUB_KTHREAD_INIT = 0xe000000, /* init process*/
- 161 SI_SUB_KTHREAD_PAGE = 0xe400000, /* pageout daemon*/
- 162 SI_SUB_KTHREAD_VM = 0xe800000, /* vm daemon*/
- 163 SI_SUB_KTHREAD_BUF = 0xea00000, /* buffer daemon*/
- 164 SI_SUB_KTHREAD_UPDATE = 0xec00000, /* update daemon*/
- 165 SI_SUB_KTHREAD_IDLE = 0xee00000, /* idle procs*/
- 166 SI_SUB_SMP = 0xf000000, /* start the APs 负责**暂停激活的AP*/
- 167 SI_SUB_RACCTD = 0xf100000, /* start raccd*/
- 168 SI_SUB_RUN_SCHEDULER = 0xfffffff /* scheduler*/
- 169 };
复制代码 [order]-order参数可以取值如下:- 172 /*
- 173 * Some enumerated orders; "ANY" sorts last.
- 174 */
- 175 enum sysinit_elem_order {
- 176 SI_ORDER_FIRST = 0x0000000, /* first*/
- 177 SI_ORDER_SECOND = 0x0000001, /* second*/
- 178 SI_ORDER_THIRD = 0x0000002, /* third*/
- 179 SI_ORDER_FOURTH = 0x0000003, /* fourth*/
- 180 SI_ORDER_MIDDLE = 0x1000000, /* somewhere in the middle */
- 181 SI_ORDER_ANY = 0xfffffff /* last*/
- 182 };
复制代码 下面以虚拟内存系统的初始化为例,说明一下SYSINIT宏的工作过程。
在源代码文件"release/9.2.0/sys/vm/vm_init.c"中,使用了下面的SYSINIT宏声明:- SI_SUB_VM = 0x1000000, /* virtual memory system init*/
- SYSINIT(vm_mem, SI_SUB_VM, SI_ORDER_FIRST, vm_mem_init, NULL);
复制代码 下面逐步展开宏SYSINIT:
宏SYSINIT定义如下所示:- 239 #define SYSINIT(uniquifier, subsystem, order, func, ident) \
- 240 C_SYSINIT(uniquifier, subsystem, order, \
- 241 (sysinit_cfunc_t)(sysinit_nfunc_t)func, (void *)(ident))
复制代码 [1]--展开宏SYSINIT:- C_SYSINIT(vm_mem, SI_SUB_VM, SI_ORDER_FIRST,vm_mem_init, NULL)
复制代码 [2]--展开宏C_SYSINIT:
宏C_SYSINIT定义如下所示:- 230 #define C_SYSINIT(uniquifier, subsystem, order, func, ident) \
- 231 static struct sysinit uniquifier ## _sys_init = { \
- 232 subsystem, \
- 233 order, \
- 234 func, \
- 235 (ident) \
- 236 }; \
- 237 DATA_SET(sysinit_set,uniquifier ## _sys_init)
复制代码 展开宏C_SYSINIT如下所示:- 231 static struct sysinit vm_mem_sys_init = {
- 232 SI_SUB_VM, /* subsystem成员 */
- 233 SI_ORDER_FIRST, /* order成员 */
- 234 vm_mem_init, /* func成员 */
- 235 NULL /* udata成员 */
- 236 };
- 237 DATA_SET(sysinit_set,vm_mem_sys_init)
复制代码 [3]--展开宏DATA_SET:
宏DATA_SET定义如下所示:- #define DATA_SET(set, sym) __MAKE_SET(set, sym)
复制代码 展开宏DATA_SET如下所示:- 231 static struct sysinit vm_mem_sys_init = {
- 232 SI_SUB_VM, /* subsystem成员 */
- 233 SI_ORDER_FIRST, /* order成员 */
- 234 vm_mem_init, /* func成员 */
- 235 NULL /* udata成员 */
- 236 };
- 237 __MAKE_SET(sysinit_set,vm_mem_sys_init)
复制代码 [4]--展开宏__MAKE_SET:
宏__MAKE_SET定义如下所示:- 47 #define __MAKE_SET(set, sym) \
- 48 __GLOBL(__CONCAT(__start_set_,set)); \
- 49 __GLOBL(__CONCAT(__stop_set_,set)); \
- 50 static void const * const __set_##set##_sym_##sym \
- 51 __section("set_" #set) __used = &sym
复制代码 展开宏__MAKE_SET如下所示:- 231 static struct sysinit vm_mem_sys_init = {
- 232 SI_SUB_VM, /* subsystem成员 */
- 233 SI_ORDER_FIRST, /* order成员 */
- 234 vm_mem_init, /* func成员 */
- 235 NULL /* udata成员 */
- 236 };
- 48 __GLOBL(__CONCAT(__start_set_,sysinit_set));
- 49 __GLOBL(__CONCAT(__stop_set_,sysinit_set));
- 50 static void const * const __set_sysinit_set_sym_vm_mem_sys_init __section("set_" sysinit_set) __used = &vm_mem_sys_init
复制代码 从宏SYSINIT的展开过程来看,宏SYSINIT用其参数构造一个类型为struct sysinit的数据对象,并将这个数据对象的地址保存到set_sysinit_set节中,mi_startup函数会遍历
该节,依次调用初始化函数对系统进行初始化。- 118 /*
- 119 * The sysinit table itself. Items are checked off as the are run.
- 120 * If we want to register new sysinit types, add them to newsysinit.
- set_sysinit_set节的起始和结束地址由链接器确定,同时链接器构造了两个全局符号来标识该数据
- 节的起始和结束地址:
- __start_set_sysinit_set:set_sysinit_set节的起始地址
- __stop_set_sysinit_set: set_sysinit_set节的结束地址
- 宏SET_DECLARE展开后如下所示:
- extern struct sysinit *__start_set_sysinit_set;
- extern struct sysinit *__stop_set_sysinit_set;
- 因为__start_set_sysinit_set和__stop_set_sysinit_set变量是由链接器自动生成的,所以内核
- 想要使用这两个变量的话就得使用SET_DECLARE(sysinit_set, struct sysinit),表明
- 这两个变量是在别处定义的。这里有点疑惑,__start_set_sysinit_set和__stop_set_sysinit_set
- 应该是struct sysinit **类型,但是宏SET_DECLARE(sysinit_set, struct sysinit)展开后的类型
- 却是struct sysinit *?
- sysinit:set_sysinit_set节的起始地址
- sysinit_end: set_sysinit_set节的结束地址
- 如果执行了SI_SUB_KLD子系统的初始化函数后,set_sysinit_set节可能会改变,此时
- newsysinit:更新后set_sysinit_set节的起始地址
- newsysinit_end:更新后set_sysinit_set节的结束地址
- 121 */
- 122 SET_DECLARE(sysinit_set, struct sysinit);
- 123 struct sysinit **sysinit, **sysinit_end;
- 124 struct sysinit **newsysinit, **newsysinit_end;
- 185 /*
- 186 * A system initialization call instance
- 187 *
- 188 * At the moment there is one instance of sysinit. We probably do not
- 189 * want two which is why this code is if'd out, but we definitely want
- 190 * to discern SYSINIT's which take non-constant data pointers and
- 191 * SYSINIT's which take constant data pointers,
- 192 *
- 193 * The C_* macros take functions expecting const void * arguments
- 194 * while the non-C_* macros take functions expecting just void * arguments.
- 195 *
- 196 * With -Wcast-qual on, the compiler issues warnings:
- 197 * - if we pass non-const data or functions taking non-const data
- 198 * to a C_* macro.
- 199 *
- 200 * - if we pass const data to the normal macros
- 201 *
- 202 * However, no warning is issued if we pass a function taking const data
- 203 * through a normal non-const macro. This is ok because the function is
- 204 * saying it won't modify the data so we don't care whether the data is
- 205 * modifiable or not.
- 206 */
- 207
- 208 typedef void (*sysinit_nfunc_t)(void *);
- 209 typedef void (*sysinit_cfunc_t)(const void *);
- 210
- 211 struct sysinit {
- 212 enum sysinit_sub_id subsystem; /* subsystem identifier SYSINIT宏的第二个参数 */
- 213 enum sysinit_elem_order order; /* init order within subsystem SYSINIT宏的第三个参数 */
- 214 sysinit_cfunc_t func; /* function 初始化函数 */
- 215 const void *udata; /* multiplexer/argument 初始化函数的参数 */
- 216 };
复制代码 |
|