JJJ:linux内核传参、解析流程

1 module_param_cb

1.1 待解析内容:

// block/genhd.c
module_param_cb(events_dfl_poll_msecs, &disk_events_dfl_poll_msecs_param_ops,
        		&disk_events_dfl_poll_msecs, 0644);

1.2 涉及到的相关定义:

// block/genhd.c
static const struct kernel_param_ops disk_events_dfl_poll_msecs_param_ops = {
    .set    = disk_events_set_dfl_poll_msecs,
    .get    = param_get_ulong,
};

/* disable in-kernel polling by default */
static unsigned long disk_events_dfl_poll_msecs;

#define MODULE_PARAM_PREFIX  "block."

1.3 涉及到的通用定义

module_param_cb 展开流程

/**

 * module_param_cb - general callback for a module/cmdline parameter
 * @name: a valid C identifier which is the parameter name.
 * @ops: the set & get operations for this parameter
 * @perm: visibility in sysfs.
   *
 * The ops can have NULL set or get functions.
   */
   #define module_param_cb(name, ops, arg, perm)                     \
   __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, -1, 0)


/* This is the fundamental function for registering boot/module
   parameters. */
#define __module_param_call(prefix, name, ops, arg, perm, level, flags) \
    /* Default value instead of permissions? */         \
    static const char __param_str_##name[] = prefix #name;      \
    static struct kernel_param __moduleparam_const __param_##name   \
    __used                              \
    __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \
    = { __param_str_##name, THIS_MODULE, ops,           \
        VERIFY_OCTAL_PERMISSIONS(perm), level, flags, { arg } }

struct kernel_param

// include/linux/moduleparam.h
struct kernel_param {
    const char *name;
    struct module *mod;
    const struct kernel_param_ops *ops;
    const u16 perm;
    s8 level;
    u8 flags;
    union {
        void *arg;
        const struct kparam_string *str;
        const struct kparam_array *arr;
    };
};

struct kernel_param_ops

// include/linux/moduleparam.h
struct kernel_param_ops {
    /* How the ops should behave */
    unsigned int flags;
    /* Returns 0, or -errno.  arg is in kp->arg. */
    int (*set)(const char *val, const struct kernel_param *kp);
    /* Returns length written or -errno.  Buffer is 4k (ie. be short!) */
    int (*get)(char *buffer, const struct kernel_param *kp);
    /* Optional function to free kp->arg when module unloaded. */
    void (*free)(void *arg);
};

kernel_param_ops 中 get、set函数的定义

// kernel/params.c
#define STANDARD_PARAM_DEF(name, type, format, strtolfn)            \
    int param_set_##name(const char *val, const struct kernel_param *kp) \
    {                               \
        return strtolfn(val, 0, (type *)kp->arg);       \
    }                               \
    int param_get_##name(char *buffer, const struct kernel_param *kp) \
    {                               \
        return scnprintf(buffer, PAGE_SIZE, format "\n",    \
                *((type *)kp->arg));            \
    }                               \
    const struct kernel_param_ops param_ops_##name = {          \
        .set = param_set_##name,                \
        .get = param_get_##name,                \
    };                              \
    EXPORT_SYMBOL(param_set_##name);                \
    EXPORT_SYMBOL(param_get_##name);                \
    EXPORT_SYMBOL(param_ops_##name)


STANDARD_PARAM_DEF(byte,    unsigned char,      "%hhu", kstrtou8);
STANDARD_PARAM_DEF(short,   short,          "%hi",  kstrtos16);
STANDARD_PARAM_DEF(ushort,  unsigned short,     "%hu",  kstrtou16);
STANDARD_PARAM_DEF(int,     int,            "%i",   kstrtoint);
STANDARD_PARAM_DEF(uint,    unsigned int,       "%u",   kstrtouint);
STANDARD_PARAM_DEF(long,    long,           "%li",  kstrtol);
STANDARD_PARAM_DEF(ulong,   unsigned long,      "%lu",  kstrtoul);
STANDARD_PARAM_DEF(ullong,  unsigned long long, "%llu", kstrtoull);

1.4 基于1.1的展开流程

1、

module_param_cb(events_dfl_poll_msecs, &disk_events_dfl_poll_msecs_param_ops,
        &disk_events_dfl_poll_msecs, 0644);

2、

__module_param_call(MODULE_PARAM_PREFIX, events_dfl_poll_msecs, &disk_events_dfl_poll_msecs_param_ops, &disk_events_dfl_poll_msecs, 0644, -1, 0)

3、

static const char __param_str_events_dfl_poll_msecs[] = "block.events_dfl_poll_msecs"; \
static struct kernel_param __moduleparam_const __param_events_dfl_poll_msecs \
__used \
__attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \
= { __param_str_events_dfl_poll_msecs, THIS_MODULE, &disk_events_dfl_poll_msecs_param_ops, \
VERIFY_OCTAL_PERMISSIONS(0644), -1, 0, { &disk_events_dfl_poll_msecs } }

2 module_param

module_param

#define module_param(name, type, perm)              \
    module_param_named(name, name, type, perm)

module_param_named

#define module_param_named(name, value, type, perm)            \
    param_check_##type(name, &(value));                \
    module_param_cb(name, &param_ops_##type, &value, perm);        \
    __MODULE_PARM_TYPE(name, #type)

param_check_( )

// include/linux/moduleparam.h
#define param_check_byte(name, p) __param_check(name, p, unsigned char)
#define param_check_short(name, p) __param_check(name, p, short)
#define param_check_ushort(name, p) __param_check(name, p, unsigned short)
#define param_check_int(name, p) __param_check(name, p, int)
#define param_check_uint(name, p) __param_check(name, p, unsigned int)
#define param_check_long(name, p) __param_check(name, p, long)
#define param_check_ulong(name, p) __param_check(name, p, unsigned long)
...

__param_check

// include/linux/moduleparam.h
// 注意name就是内核传参的参数名
#define __param_check(name, p, type) \
    static inline type __always_unused *__check_##name(void) { return(p); }

__MODULE_PARM_TYPE

// include/linux/moduleparam.h
#define __MODULE_PARM_TYPE(name, _type)                   \
  __MODULE_INFO(parmtype, name##type, #name ":" _type)

__MODULE_INFO (不深究此宏)

// include/linux/moduleparam.h
#ifdef MODULE
#define __MODULE_INFO(tag, name, info)                    \
static const char __UNIQUE_ID(name)[]                     \
  __used __attribute__((section(".modinfo"), unused, aligned(1)))     \
  = __stringify(tag) "=" info
#else  /* !MODULE */
/* This struct is here for syntactic coherency, it is not used */
#define __MODULE_INFO(tag, name, info)                    \
  struct __UNIQUE_ID(name) {}
#endif

3、推荐(详细的参数解析流程)

linux kernel的cmdline参数解析原理分析
或者
linux kernel的cmdline参数解析原理分析

他们是一样的内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值