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++;             
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值