Linux TCP/IP协议栈的通用编码模式解析
因此,如果abc在不同的代码中被使用,每一个代码都使用相同的基本定义(避免做同样的事情而采用不同的方法),同时可以根据自己的需求来扩展abc。
1.2.8. 条件编译 (#ifdef and family)
编译器的条件编译有时很有必要。过度地使用条件编译会降低代码的可读性,但是我可以声明,linux内核没有滥用它们。条件编译可以在多种情况下使用,但是我们感兴趣的是它用于检查内核是否支持某一特性。make xconfig这样配置工具会决定某一特性是编译到内核,或者完全不支持,或者编译成内核模块。
使用#ifdef或#if defined检查内核是否支持某一特性的例子如下:
包含或者不包含数据结构的某个成员
struct sk_buff {
...
#ifdef CONFIG_NETFILTER_DEBUG
unsigned int nf_debug; #endif
...
}
在这个例子中,netfilter的调试功能需要sk_buff结构中的nf_debug项。如果内核不支持netfilter
调试功能(只有一小部分开发人员需要这项功能),就没必要包含这一项, 否则它只会使得每个网络包占用更多的内存。
函数中,包含或不包含某段代码
int ip_route_input(...)
{
...
if (rth->fl.fl4_dst == daddr &&
rth->fl.fl4_src == saddr &&
rth->fl.iif == iif &&
rth->fl.oif == 0 &&
#ifndef CONFIG_IP_ROUTE_FWMARK
rth->fl.fl4_fwmark == skb->nfmark &&
#endif
rth->fl.fl4_tos == tos) {
...
}
}
为一个函数选择正确的原型
#ifdef CONFIG_IP_MULTIPLE_TABLES
struct fib_table * fib_hash_init(int id)
#else
struct fib_table * _ _init fib_hash_init(int id)
{
...
}
为函数选择正确的定义
#ifndef CONFIG_IP_MULTIPLE_TABLES ... static inline struct fib_table *fib_get_table(int id)
{
if (id != RT_TABLE_LOCAL)
return ip_fib_main_table;
return ip_fib_local_table
} ...
#else
...
static inline struct fib_table *fib_get_table(int id)
{
if (id == 0)
id = RT_TABLE_MAIN;
return fib_tables[id]; }
...
#endif
请注意这个例子和前一个例子的区别。在前一个例子中,函数体在 #ifdef/#endif 块之外, 而这个例子中,每一块都包含一个完整的函数定义。
变量定义或初始化,还有宏,都可以使用条件编译。
知道某个函数或宏有多个定义非常重要,具体使用哪个函数或者宏与条件编译有关,前面就有这样的例子。否则,你看的函数,变量或者宏的定义可能不是你所希望看到的那个。


















文章评论
共有 位CH网友发表了评论 查看完整内容