当前位置:编程学习 > C/C++ >>

early_param和__setup宏

一.宏的定义
在/include/linux/Init.h中
[cpp] 
#define __setup(str, fn)        \  
 __setup_param(str, fn, fn, 0)  
 
[cpp] 
#define early_param(str, fn)    \  
__setup_param(str, fn, fn, 1)  
两个宏都会调用__setup_param
 
跟踪进__setup_param宏的定义
[cpp]  
#define __setup_param(str, unique_id, fn, early)            \  
    static const char __setup_str_##unique_id[] __initconst \  
        __aligned(1) = str;                 \  
    static struct obs_kernel_param __setup_##unique_id      \  
        __used __section(.init.setup)           \  
        __attribute__((aligned((sizeof(long)))))        \  
        = { __setup_str_##unique_id, fn, early }  
 
 这个宏里面有个结构体obs_kernel_param
[cpp] 
struct obs_kernel_param {  
    const char *str;  
    int (*setup_func)(char *);  
    int early;  
};  
 
结合上面两个宏和一个结构体展开__setup
__setup(str, fn)宏定义了
一个static const char  __setup_str_fn[]变量=str
接着定义了
一个static struct obs_kernel_param __setup_fn结构体,并赋值(标记编译进.init.setup段)
{
    str;
    fn(char *); 
    0,或1
}
二.宏的作用
1.编译相关
在/include/asm-generic/Vmlinux.lds.h文件中定义了__setup_start.....__setup_end段
[cpp]  
#define INIT_SETUP(initsetup_align)         \  
        . = ALIGN(initsetup_align);     \  
        VMLINUX_SYMBOL(__setup_start) = .;  \  
        *(.init.setup)          \  
        VMLINUX_SYMBOL(__setup_end) = .;  
标记了.init.setup的函数会被编译进该段
2.内核启动的相关调用关系
在start_kernel中调用parse_early_param()
[cpp]  
void __init parse_early_param(void)  
{  
    static __initdata int done = 0;  
    static __initdata char tmp_cmdline[COMMAND_LINE_SIZE];  
    if (done)  
        return;  
    strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE); //复制启动命令行数据  
    parse_early_options(tmp_cmdline);   //调用parse_early_options函数  
    done = 1;  
}  
parse_early_options函数
[cpp]  
void __init parse_early_options(char *cmdline)  
{  
    parse_args("early options", cmdline, NULL, 0, do_early_param);  
}  
接着调用parse_args函数
[cpp]  
int parse_args(const char *name,char *args,const struct kernel_param *params,unsigned num,int (*unknown)(char *param, char *val))  
{  
    char *param, *val;  
    DEBUGP("Parsing ARGS: %s\n", args);  
  
    args = skip_spaces(args);  
  
    while (*args) { //遍历启动命令行  
        int ret;  
        int irq_was_disabled;  
  
        args = next_arg(args, ¶m, &val);    //获取下一个参数,填充param和val参数(例如:param--console;val--tty2,115200n8)  
        irq_was_disabled = irqs_disabled();  
        ret = parse_one(param, val, params, num, unknown);  //解析一个命令行参数  
        if (irq_was_disabled && !irqs_disabled()) {  
            printk(KERN_WARNING "parse_args(): option '%s' enabled ""irq's!\n", param);  
        }  
        switch (ret) {  
        case -ENOENT:  
            printk(KERN_ERR "%s: Unknown parameter `%s'\n",name, param);  
            return ret;  
        case -ENOSPC:  
            printk(KERN_ERR "%s: `%s' too large for parameter `%s'\n",name, val ?: "", param);  
            return ret;  
        case 0:  
            break;  
        default:  
            printk(KERN_ERR"%s: `%s' invalid for parameter `%s'\n",name, val ?: "", param);  
            return ret;  
        }  
    }  
  
    /* All parsed OK. */  
    return 0;  
}  
命令行参数的解析parse_one
[cpp]  
static int parse_one(char *param,char *val,const struct kernel_param *params,unsigned num_params,int (*handle_unknown)(char *param, char *val))  
{  
    unsigned int i;  
    int err;  
  
    /* Find parameter */  
    for (i = 0; i < num_params; i++) {   //num_params=0  
        if (parameq(param, params[i].name)) {  
            if (!val && params[i].ops->set != param_set_bool)  
                return -EINVAL;  
            DEBUGP("They are equal!  Calling %p\n",params[i].ops->set);  
            mutex_lock(¶m_lock);  
            err = params[i].ops->set(val, ¶ms[i]);  
            mutex_unlock(¶m_lock);  
            return err;  
        }  
    }  
  
    if (handle_unknown) {   //若handle_unknown函数存在  
        DEBUGP("Unknown argument: calling %p\n", handle_unknown);  
        return handle_unknown(param, val);  //则调用handle_unknown函数,参数为param,val  
    }  
  补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,