您的位置:首页 > 其它

freebsd的SYSINIT框架

2015-10-15 16:06 204 查看
个人觉的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 };

复制代码
原帖 http://bbs.chinaunix.net/thread-4142860-1-1.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: