今天我初步研究了一下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++;
}