parse_args是一个函数,用于解析输入字符串,而输入的字符串内是一些参数,其形式为变量名称=值,寻找特定关键字,并启用适当的处理函数。
内核组件可以利用__setup宏注册关键字和相关联的处理函数。
__setup宏把注册的信息存放在段.init.setup:
238 /*
239 * Only for really core code. See moduleparam.h for the normal way.
240 *
241 * Force the alignment so the compiler doesn't space elements of the
242 * obs_kernel_param "array" too far apart in .init.setup.
243 */
244 #define __setup_param(str, unique_id, fn, early) \
245 static const char __setup_str_##unique_id[] __initconst \
246 __aligned(1) = str; \
247 static struct obs_kernel_param __setup_##unique_id \
248 __used __section(.init.setup) \
249 __attribute__((aligned((sizeof(long))))) \
250 = { __setup_str_##unique_id, fn, early }
251
252 #define __setup(str, fn) \
253 __setup_param(str, fn, fn, 0)
start_kernel两次调用parse_arg以解析引导配置字符串的原因在于,引导期间选项实际上是分成两类,而每一次调用都是针对其中一类:
默认选项:
由__setup宏定义的选项。
初期选项:
内核引导期间,有些选项必须比其他选项更早处理。内核提供了宏early_param宏以声明这些选项替代__setup。
内存优化
1.执行期间最优化。当相关联的模块加载时,module_init函数只会执行一次。当该模块与内核静态链接时,在引导期间,module_init函数执行后内核就可以将其释放掉。
2.链接期间最优化。当相关联的模块与内核静态链接时,module_exit函数根本不会执行。因此,没必要把module_exit函数引入内核映像中(链接期间就可以被丢弃掉)。
上述代码和数据只在引导期间用一次,而后就不再需要了。一旦内核初始化阶段完成,就可以丢弃如图7-3的整个内存区域(调用free_init_mem)。