=========================== Linux 内核使用的 GNU C 扩展 ===========================
GNC CC 是一个功能非常强大的跨平台 C 编译器,它对 C 语言提供了很多扩展, 这些扩展对优化、目标代码布局、更安全的检查等方面提供了很强的支持。本文把 支持 GNU 扩展的 C 语言称为 GNU C。
Linux 内核代码使用了大量的 GNU C 扩展,以至于能够编译 Linux 内核的唯一编 译器是 GNU CC,以前甚至出现过编译 Linux 内核要使用特殊的 GNU CC 版本的情 况。本文是对 Linux 内核使用的 GNU C 扩展的一个汇总,希望当你读内核源码遇 到不理解的语法和语义时,能从本文找到一个初步的解答,更详细的信息可以查看 gcc.info。文中的例子取自 Linux 2.4.18。
语句表达式 ==========
GNU C 把包含在括号中的复合语句看做是一个表达式,称为语句表达式,它可以出 现在任何允许表达式的地方,你可以在语句表达式中使用循环、局部变量等,原本 只能在复合语句中使用。例如:
将结构 ext2_file_operations 的元素 llseek 初始化为 generic_file_llseek, 元素 read 初始化为 genenric_file_read,依次类推。我觉得这是 GNU C 扩展中 最好的特性之一,当结构的定义变化以至元素的偏移改变时,这种初始化方法仍然 保证已知元素的正确性。对于未出现在初始化中的元素,其初值为 0。
Case 范围 =========
GNU C 允许在一个 case 标号中指定一个连续范围的值,例如:
++++ arch/i386/kernel/irq.c 1062: case '0' ... '9': c -= '0'; break; 1063: case 'a' ... 'f': c -= 'a'-10; break; 1064: case 'A' ... 'F': c -= 'A'-10; break;
case '0' ... '9':
相当于
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
声明的特殊属性 ==============
GNU C 允许声明函数、变量和类型的特殊属性,以便手工的代码优化和更仔细的代 码检查。要指定一个声明的属性,在声明后写
__attribute__ (( ATTRIBUTE ))
其中 ATTRIBUTE 是属性说明,多个属性以逗号分隔。GNU C 支持十几个属性,这 里介绍最常用的:
GNU CC 预定义了两个标志符保存当前函数的名字,__FUNCTION__ 保存函数在源码 中的名字,__PRETTY_FUNCTION__ 保存带语言特色的名字。在 C 函数中,这两个 名字是相同的,在 C++ 函数中,__PRETTY_FUNCTION__ 包括函数返回类型等额外 信息,Linux 内核只使用了 __FUNCTION__。
++++ fs/ext2/super.c 98: void ext2_update_dynamic_rev(struct super_block *sb) 99: { 100: struct ext2_super_block *es = EXT2_SB(sb)->s_es; 101: 102: if (le32_to_cpu(es->s_rev_level) > EXT2_GOOD_OLD_REV) 103: return; 104: 105: ext2_warning(sb, __FUNCTION__, 106: "updating to rev %d because of new feature flag, " 107: "running e2fsck is recommended", 108: EXT2_DYNAMIC_REV);