第十二章:宏,列举(enum)RTL

 

定义常量和列举里的标签的宏的名字需要大写。

 

#define CONSTANT 0x12345

 

在定义几个相关的常量时,最好用列举。

 

宏的名字请用大写字母,不过形如函数的宏的名字可以用小写字母。

 

一般的,如果能写成内联函数就不要写成像函数的宏。

 

含有多个语句的宏应该被包含在一个do-while代码块里:

 

#define macrofun(a, b, c)                      \

        do {                                   \

                if (a == 5)                    \

                        do_this(b, c);         \

        } while (0)

 

使用宏的时候应避免的事情:

 

1) 影响控制流程的宏:

 

#define FOO(x)                                 \

        do {                                   \

                if (blah(x) < 0)               \

                        return -EBUGGERED;     \

        } while(0)

 

非常不好。它看起来像一个函数,不过却能导致“调用”它的函数退出;

don't break the internal parsers of those who will read the code.

 

 

2) 依赖于一个固定名字的本地变量的宏:

 

#define FOO(val) bar(index, val)

 

可能看起来像是个不错的东西,不过它非常容易把读代码的人搞糊涂,而且容易导致看起来不相关的改动带来错误。

 

3) 作为左值的带参数的宏: FOO(x) = y;如果有人把FOO变成一个内联函数的话,这种用法就会出错了。

 

4) 忘记了优先级:使用表达式定义常量的宏必须将表达式置于一对小括号之内。带参数的宏也要注意此类问题。

 

#define CONSTANT 0x4000

#define CONSTEXP (CONSTANT | 3)

cpp手册对宏的讲解很详细。Gcc internals手册也详细讲解了RTL(译注:register

transfer language),内核里的汇编语言经常用到它。

 

 

                第十三章:打印内核消息

 

内核开发者应该是受过良好教育的。请一定注意内核信息的拼写,以给人以好的印象。不要用不规范的单词比如“dont”,而要用“do not”或者“don't”。保证这些信息简单、

明了、无歧义。

 

内核信息不必以句点结束。

 

在小括号里打印数字(%d)没有任何价值,应该避免这样做。

 

<linux/device.h>里有一些驱动模型诊断宏,你应该使用它们,以确保信息对应于正确的设备和驱动,并且被标记了正确的消息级别。这些宏有:dev_err(), dev_warn(),

dev_info()等等。对于那些不和某个特定设备相关连的信息,<linux/kernel.h>定义了pr_debug()pr_info()

 

写出好的调试信息可以是一个很大的挑战;当你写出来之后,这些信息在远程除错的时候就会成为极大的帮助。当DEBUG符号没有被定义的时候,这些信息不应该被编译进内核里(也就是说,默认地,它们不应该被包含在内)。如果你使用dev_dbg()或者pr_debug(),就能自动达到这个效果。很多子系统拥有Kconfig选项来启用-DDEBUG。还有一个相关的惯例是使用VERBOSE_DEBUG来添加dev_vdbg()消息到那些已经由DEBUG启用的消息之上。