SW 개발

[Linux Kernel] 모듈 파라미터에 대한 분석..

. . . 2010. 8. 12. 14:12
반응형

이전 2.6 커널기준 이며, 최신커널에서는 해당내용들에 해당하지 않습니다.

module_param 호출에 대해서...

module_param(var, type, perm)
module_param(irq, int, 0);

이와 같이 호출한다. 호출하는곳을 따라가면...

#define module_param(name, type, perm)              \
    module_param_named(name, name, type, perm)
#define module_param_named(name, value, type, perm)            \
    param_check_##type(name, &(value));                \    
    module_param_call(name, param_set_##type, param_get_##type, &value, perm); \    
    __MODULE_PARM_TYPE(name, #type)

결국은 위와 같이 호출하게 되고... 궁극적으로 역할을 하는것은 아래의 매크로다.

#define module_param_call(name, set, get, arg, perm)                  \
    __module_param_call(MODULE_PARAM_PREFIX, name, set, get, arg, perm)
#define __module_param_call(prefix, name, set, get, arg, perm)      \
static char __param_str_##name[] = prefix #name;        \
static struct kernel_param const __param_##name         \
    __attribute_used__                      \
    __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \
    = { __param_str_##name, perm, set, get, arg }

딱보면.. 알겠지만.. 일단. \param\str##name[] 에 변수이름을 저장 하며, kernel\param 이라는 구조체를 선언한다.

struct kernel_param {
const char *name;
unsigned int perm;
    param_set_fn set;
    param_get_fn get;
void *arg;
};

그리고... 아래 \attribute\ 부분 보면... 추측이지만.. \param 이라는 섹션을 선언하고... 그곳에.. kernel\param 의 구조체를 넣는것 같다. 그리고.. 그 고제체의 멤버를 { \param\str##name, perm, set, get, arg } 순서대로 넣는것 같음;;

module_param_call(name, param_set_##type, param_get_##type, &value, perm); \    

위에 보면... 각 파라미터 type별로 param\set\fn/param\get\fn 로 연결시키는 함수가 틀린데요.. 그것은 아래 선언되어있더군요..

// kernel/params.c

#define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn)       \
int param_set_##name(const char *val, struct kernel_param *kp)  \
{                               \
char *endp;                     \
        tmptype l;                      \
                                    \
if (!val) return -EINVAL;               \
        l = strtolfn(val, &endp, 0);                \
if (endp == val || ((type)l != l))          \
return -EINVAL;                 \
        *((type *)kp->arg) = l;                 \
return 0;                       \
}                               \
int param_get_##name(char *buffer, struct kernel_param *kp) \
{                               \
return sprintf(buffer, format, *((type *)kp->arg)); \
}
STANDARD_PARAM_DEF(byte, unsigned char, "%c", unsigned long, simple_strtoul);
STANDARD_PARAM_DEF(short, short, "%hi", long, simple_strtol);
STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", unsigned long, simple_strtoul);
STANDARD_PARAM_DEF(int, int, "%i", long, simple_strtol);
STANDARD_PARAM_DEF(uint, unsigned int, "%u", unsigned long, simple_strtoul);
STANDARD_PARAM_DEF(long, long, "%li", long, simple_strtol);
STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", unsigned long, simple_strtoul);

다음..

MODULE_PARM_DESC(irq, "cs89x0 IRQ number");
#define MODULE_PARM_DESC(_parm, desc) \
    __MODULE_INFO(parm, _parm, #_parm ":" desc)
#define __MODULE_INFO(tag, name, info)                    \
static const char __module_cat(name,__LINE__)[]               \
  __attribute_used__                              \
  __attribute__((section(".modinfo"),unused)) = __stringify(tag) "=" info
irq = irq_parm : cs89x0 IRQ number
#define ___module_cat(a,b) __mod_ ## a ## b
#define __module_cat(a,b) ___module_cat(a,b)
#define __stringify_1(x)    #x
#define __stringify(x)      __stringify_1(x)
반응형