__set_up是一个宏
#define __setup(str, fn) \ __setup_param(str, fn, fn, 0) #define __setup_param(str, unique_id, fn, early) static char __setup_str_##unique_id[] __initdata = str; static struct obs_kernel_param __setup_##unique_id __attribute_used__ __attribute__((__section__(".init.setup"))) __attribute__((aligned((sizeof(long))))) = { __setup_str_##unique_id, fn, early } struct obs_kernel_param { const char *str; int (*setup_func)(char *); int early; }; #define __init __attribute__ ((__section__ (".init.text"))) #define __initdata __attribute__ ((__section__ (".init.data"))) #define __exitdata __attribute__ ((__section__(".exit.data")))
举例:
static int __init init_setup(char *str) { unsigned int i; execute_command = str; for (i = 1; i < MAX_INIT_ARGS; i++) argv_init[i] = NULL; return 1; } __setup("init=", init_setup); //转换为 static char __setup_str_init_setup[] __attribute__ ((__section__ (".init.data"))) ="init="; static struct obs_kernel_param __setup_init_setup __attribute_used__ __attribute__((__section__(".init.setup"))) __attribute__((aligned((sizeof(long))))) = { __setup_str_init_setup, init_setup, 0 }
/*vmlinux.lds的.init段中
{
...
__setup_start = .;
*(.init.setup)
__setup_end = .;
...
}*/
static int __init obsolete_checksetup(char *line)/* Handle obsolete-style parameters */ { struct obs_kernel_param *p; int had_early_param = 0; p = __setup_start; /*从.init.setup段的开始分析*/ do { int n = strlen(p->str); /*计算出.init.setup中字符串的长度*/ if (!strncmp(line, p->str, n)) { if (p->early) { /*这里的都是early属性为0的*/ /* Already done in parse_early_param? * (Needs exact match on param part). * Keep iterating, as we can have early * params and __setups of same names 8( */ if (line[n] == ‘\0‘ || line[n] == ‘=‘) had_early_param = 1; } else if (!p->setup_func) { printk(KERN_WARNING "Parameter %s is obsolete," " ignored\n", p->str); return 1; } else if (p->setup_func(line + n))/*调用参数中对应函数,参数为偏移n个(初始化是参数长度)后的字符串*/ return 1; } p++; /*继续处理,直到结束*/ } while (p < __setup_end); return had_early_param; }
static int __init init_setup(char *str) { unsigned int i; execute_command = str; /* * In case LILO is going to boot us with default command line, * it prepends "auto" before the whole cmdline which makes * the shell think it should execute a script with such name. * So we ignore all arguments entered _before_ init=... [MJ] */ for (i = 1; i < MAX_INIT_ARGS; i++) argv_init[i] = NULL; return 1; } //作用就是把“=”后边的传给execute_command。 //比如设置了init=/linuxrc 则execute_command=&“/linuxrc” 表示不正确 就是那个结构体的str参数偏移n个的地址
static int noinline init_post(void) { ... if (ramdisk_execute_command) { run_init_process(ramdisk_execute_command); printk(KERN_WARNING "Failed to execute %s\n", ramdisk_execute_command); } ... if (execute_command) { run_init_process(execute_command); printk(KERN_WARNING "Failed to execute %s. Attempting " "defaults...\n", execute_command); } run_init_process("/sbin/init"); run_init_process("/etc/init"); run_init_process("/bin/init"); run_init_process("/bin/sh"); panic("No init found. Try passing init= option to kernel."); }