欢迎来到天天文库
浏览记录
ID:40749610
大小:24.50 KB
页数:10页
时间:2019-08-07
《Linux 内核中的GCC特性了解用于C语言的GCC扩展》由会员上传分享,免费在线阅读,更多相关内容在行业资料-天天文库。
1、GCC和Linux是出色的组合。尽管它们是独立的软件,但是Linux完全依靠GCC在新的体系结构上运行。Linux还利用GCC中的特性(称为扩展)实现更多功能和优化。本文讨论一些重要的扩展,讲解如何在Linux内核中使用它们。 GCC当前的稳定版本(版本4.3.2)支持C标准的三个版本: InternationalOrganizationforStandardization(ISO)最初的C语言标准(ISOC89或C90) 带修正1的ISOC90 当前的ISOC99(这是GCC使用的默认标准,本文也假设采用这种标准) 注意:
2、本文假设使用ISOC99标准。如果指定比ISOC99版本旧的标准,那么可能无法使用本文描述的一些扩展。可以在命令行上使用-std选项指定GCC使用的实际标准。可以通过GCC手册查看哪个标准版本支持哪些扩展。 可以以几种方式对可用的C扩展进行分类。本文把它们分为两大类: 功能性扩展提供新功能。 优化扩展帮助生成更高效的代码。 功能性扩展 先讨论一些扩展标准C语言的GCC扩展。 类型发现 GCC允许通过变量的引用识别类型。这种操作支持泛型编程。在C++、Ada和Java™语言等许多现代编程语言中都可以找到相似的功能。Linu
3、x使用typeof构建min和max等依赖于类型的操作。清单1演示如何使用typeof构建一个泛型宏(见./linux/include/linux/kernel.h)。 清单1.使用typeof构建一个泛型宏#define min(x, y) ({ typeof(x) _min1 = (x); typeof(y) _min2 = (y); (void) (&_min1 == &_min2); _min1 < _min2 ? _min1 : _min2; }) 范围扩展 GCC支持范围,在C语言的许
4、多方面都可以使用范围。其中之一是switch/case块中的case语句。在复杂的条件结构中,通常依靠嵌套的if语句实现与清单2(见./Linux/drivers/scsi/sd.c)相同的结果,但是清单2更简洁。使用switch/case也可以通过使用跳转表实现进行编译器优化。 清单2.在case语句中使用范围 static int sd_major(int major_idx) { switch (major_idx) { case 0: return SCSI_DISK0_MAJOR; case 1 ...
5、7: return SCSI_DISK1_MAJOR + major_idx - 1; case 8 ... 15: return SCSI_DISK8_MAJOR + major_idx - 8; default: BUG; return 0; /* shut up gcc */ } } 还可以使用范围进行初始化,如下所示(见./linux/arch/cris/arch-v32/kernel/smp.c)。在这个示例中,spinlock_t创建一个大小为LOCK_COUNT的数组。数组的每个元素初始化为SPIN_L
6、OCK_UNLOCKED值。/* Vector of locks used for various atomic operations */ spinlock_t cris_atomic_locks = { [0 ... LOCK_COUNT - 1] = SPIN_LOCK_UNLOCKED}; 范围还支持更复杂的初始化。例如,以下代码指定数组中几个子范围的初始值。 int widths = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 }; 零长度的数组 在C标准中,必须定
7、义至少一个数组元素。这个需求往往会使代码设计复杂化。但是,GCC支持零长度数组的概念,这对于结构定义尤其有用。这个概念与ISOC99中灵活的数组成员相似,但是使用不同的语法。下面的示例在结构的末尾声明一个没有成员的数组(见./Linux/drivers/IEee1394/raw1394-private.h)。这允许结构中的元素引用结构实例后面紧接着的内存。在需要数量可变的数组成员时,这个特性很有用。 struct iso_block_store { atomic_t refcount; size_t data_s
8、ize; quadlet_t data[0]; }; 判断调用地址 在许多情况下,需要判断给定函数的调用者。GCC提供用于此用途的内置函数__builtin_return_address。这个函数通常用于调
此文档下载收益归作者所有