日期:2014-05-16  浏览次数:20599 次

【Linux 驱动】第十一章 内核的数据类型

一,内核数据数据类型

        主要分为: 标准 C 语言类型、确定大小的类型和特定内核对象的类型。

        1)标准 C 语言类型

              当需要"一个2字节填充符"或"用一个4字节字串来代表某个东西",就不能使用标准C语言类型,因为在不同的体系结构,C 语言的数据类型所占的空间大小不同。例如:long 在32位系统和64位系统中占用的字节数不同。

              有的构架,内核空间和用户空间的C 数据类型所占空间大小也可能不同。kdatasize模块显示了当前模块的内核空间C 数据类型所占空间大小。

             尽管概念上地址是指针,但使用一个无符号整型可以更好地实现内存管理; 内核把物理内存看成一个巨型数组, 内存地址就是该数组的索引。 我们可以方便地对指针取值,但直接处理内存地址时,我们几乎从不会以这种方式对他取值。使用一个整数类型避免了这种取值,因此避免了 bug。所以,利用至少在 Linux 目前支持的所有平台上,指针长整型始终是相同大小的这一事实,内核中内存地址常常是 unsigned long
             

        2)确定大小的类型

              当需要知道你定义的数据的大小时,可以使用内核提供的下列数据类型(所有的数据声明在 <asm/types.h>, 被包含在 <linux/types.h> ):

               u8; /* unsigned byte (8 bits) */

              u16; /* unsigned word (16 bits) */

              u32; /* unsigned 32-bit value */

              u64; /* unsigned 64-bit value */
              /*虽然很少需要有符号类型,但是如果需要,只要用 s 代替 u*/

             若一个用户空间程序需要使用这些类型,可在符号前加一个双下划线: __u8和其它类型是独立于 __KERNEL__ 定义的。

             这些类型是 Linux 特定的,它们妨碍了移植软件到其他的 Unix 机器。

             新的编译器系统支持 C99-标准 类型,如 uint8_t 和 uint32_t。若考虑移植性,使用这些类型比 Linux特定的变体要好。


        3)接口特定的类型(_t 类型)

              内核中最常用的数据类型由它们自己的 typedef 声明,阻止了任何移植性问题。"接口特定(interface-specific)"由某个库定义的一种数据类型, 以便为了某个特定的数据结构提供接口。很多 _t 类型在 <linux/types.h> 中定义。

              注意:近来已经很少定义新的接口特定的类型。有许多内核开发者已经不再喜欢使用 typedef 语句,他们宁愿看到代码中直接使用的真实类型信息。很多老的接口特定类型在内核中保留,他们不会很快消失。

              即使没有定义接口特定类型,也应该始终是用和内核其他部分保持一致、适当的数据类型。只要驱动使用了这种"定制"类型的函数,但又不遵照约定,编译器会发出警告,这时使用 -Wall 编译器选项并小心去除所有的警告,就可以确信代码的可移植性了。

             _t 类型的主要问题是:打印它们时,常常不容易选择正确的 printk 或 printf 格式。打印接口特定的数据的最好方法是:将其强制转换为可能的最大类型(常常是 long 或 unsigned long ) 并用相应的格式打印。

二,其他移植性问题