freeBSD的VNET_DEFINE跟SYSCTL_VNET_INT

今天我初步研究了一下freeBSD的VNET_DEFINE跟SYSCTL_VNET_INT这二个宏,下面先摘取ip_input.c中的一段代码,把这二个宏展开来看看它是何方神圣。

VNET_DEFINE(int, ipforwarding);
SYSCTL_VNET_INT(_net_inet_ip, IPCTL_FORWARDING, forwarding, CTLFLAG_RW,&VNET_NAME(ipforwarding), 0, "Enable IP forwarding between interfaces");

其中宏VNET_DEFINE的定义如下:

#define VNET_DEFINE(t, n) t VNET_NAME(n) __section(VNET_SETNAME) __used
#define VNET_NAME(n) vnet_entry_##n

展开宏VNET_DEFINE(int, ipforwarding)将得到一个int型的变量:

int vnet_entry_ipforwarding __section("set_vnet") __used;

这个变量的后半部分二个宏可以不用管,是有关于这个变量的属性,因此可以简写成如下形式:

int vnet_entry_ipforwarding;

接下来将展开宏SYSCTL_VNET_INT。于这个宏相关的一些宏定义如下所示:

#define SYSCTL_VNET_INT(parent, nbr, name, access, ptr, val, descr) \
    SYSCTL_OID(parent, nbr, name,                   \
        CTLTYPE_INT|CTLFLAG_MPSAFE|CTLFLAG_VNET|(access), \
        ptr, val, vnet_sysctl_handle_int, "I", descr)

初步展开SYSCTL_VNET_INT,
SYSCTL_OID(_net_inet_ip, IPCTL_FORWARDING,forwarding,
            CTLTYPE_INT|CTLFLAG_MPSAFE|CTLFLAG_VNET|CTLFLAG_RW, 
            &vnet_entry_ipforwarding, 0, vnet_sysctl_handle_int, "I", 
            "Enable IP forwarding between interfaces")

接下来继续展开SYSCTL_OID,其宏定义如下:

#define SYSCTL_OID(parent, nbr, name, kind, a1, a2, handler, fmt, descr) \
    static struct sysctl_oid sysctl__##parent##_##name = {       \
        &sysctl_##parent##_children, { NULL }, nbr, kind,    \
        a1, a2, #name, handler, fmt, 0, 0, __DESCR(descr) };     \
    DATA_SET(sysctl_set, sysctl__##parent##_##name)

先展开SYSCTL_OID,因此可以得到

static struct sysctl_oid sysctl___net_inet_ip_forwarding = {
            &sysctl__net_inet_ip_children,
            { NULL },
            IPCTL_FORWARDING,
            CTLTYPE_INT|CTLFLAG_MPSAFE|CTLFLAG_VNET|CTLFLAG_RW,
            &vnet_entry_ipforwarding,
            0,
            "forwarding",
            vnet_sysctl_handle_int,
            "I",
            0,
            0,
            "Enable IP forwarding between interfaces"
            };
DATA_SET(sysctl_set, sysctl___net_inet_ip_forwarding)

这里定义了一个struct sysctl_oid类型的结构体,并对其初始化,这个结构体将在DATA_SET中被使用,接下来我们继续展开DATA_SET,其宏定义如下:

#define DATA_SET(set, sym) \
    extern __typeof__(__typeof__(sym) *) __CONCAT(__set_,set)[LINKER_SET_MAX_SIZE]; \
    extern unsigned int __CONCAT(__size_of_set_,set);       \
    static void __set_ ## set ## _register_ ## sym (void) __attribute__((__constructor__)); \
    static void __set_ ## set ## _register_ ## sym (void) { \
        if (__CONCAT(__size_of_set_,set) >= LINKER_SET_MAX_SIZE) \
            panic("Too many entries in DATA_SET %s\n", #set); \
        __CONCAT(__set_,set)[__CONCAT(__size_of_set_,set)] = &sym; \
        __CONCAT(__size_of_set_,set)++;             \
    }

因此得到最后一个宏展开后的代码如下:

extern __typeof__(__typeof__(sysctl___net_inet_ip_forwarding) *) __set_sysctl_set[LINKER_SET_MAX_SIZE]; 
extern unsigned int __size_of_set_sysctl_set;       
static void __set_sysctl_set_register_sysctl___net_inet_ip_forwarding (void) __attribute__((__constructor__)); 
static void __set_sysctl_set_register_sysctl___net_inet_ip_forwarding (void) {      
if (__size_of_set_sysctl_set >= LINKER_SET_MAX_SIZE) 
    panic("Too many entries in DATA_SET %s\n", "sysctl_set"); 
    __set_sysctl_set[__size_of_set_sysctl_set] = &sysctl___net_inet_ip_forwarding; 
    __size_of_set_sysctl_set++;             
}

对上述代码,去掉一些看起来不舒服的代码片段,并且加上之前转换完成的代码,原始二个宏展开后的代码如下:

int vnet_entry_ipforwarding __section("set_vnet") __used;
static struct sysctl_oid sysctl___net_inet_ip_forwarding = {
    &sysctl__net_inet_ip_children,
    { NULL },
    IPCTL_FORWARDING,
    CTLTYPE_INT|CTLFLAG_MPSAFE|CTLFLAG_VNET|CTLFLAG_RW,
    &vnet_entry_ipforwarding,
    0,
    "forwarding",
    vnet_sysctl_handle_int,
    "I",
    0,
    0,
    "Enable IP forwarding between interfaces"
    };
struct sysctl_oid *__set_sysctl_set[LINKER_SET_MAX_SIZE];
extern unsigned int __size_of_set_sysctl_set;
static void __set_sysctl_set_register_sysctl___net_inet_ip_forwarding (void)                                
            __attribute__((__constructor__));/*__attribute__((constructor))标志的代码将在main函数前调用*/
static void         
__set_sysctl_set_register_sysctl___net_inet_ip_forwarding (void) {      
if (__size_of_set_sysctl_set >= LINKER_SET_MAX_SIZE) 
        panic("Too many entries in DATA_SET %s\n", "sysctl_set"); 
    __set_sysctl_set[__size_of_set_sysctl_set] = &sysctl___net_inet_ip_forwarding; 
    __size_of_set_sysctl_set++;             
}

你可能感兴趣的:(FreeBSD,宏)