LDD-Data Type in the Kernel

内核中的数据类型主要是为了增强可移植性。

Standard C Types


从下表可以看到标准C语言各个数据类型在不同的平台上占用的存储空间(以字节计)可能不同:
为此,内核定义了长度和平台无关的数据类型:u8,u16,u32,u64。

Interface-Specific Types


内核中常用的数据类型都有自己的typedef语句,例如pid_t;但是现在内核程序员不再青睐这种定义——这种定义隐藏了真实的数据类型。原来的数据类型仍会保留,写驱动程序时需要保持一致的数据类型,否则产生警告信息。

Other Portability Issues


另外一些和移植性相关的问题主要是显式的常量值——预编译宏。
1. Time Intervals
不要认为1秒总是包含1000jiffies,使用HZ宏来计时,比如0.5s=HZ/2。
2. Page Size
一个内存页的大小为PAGE_SIZE,不一定是4KB。在向get_free_pages传入参数时,要注意order的值。
3. Byte Order
代码尽量和字节序无关,如果需要进行字节序的转换,参看文件linux/byteorder/big_endian.h、linux/byteorder/little_endian.h。
4. Data Alignment
i386用户经常访问不对齐的数据,但是很多处理器结构在访问不对齐的数据时会产生异常,读取的数据通过异常处理函数返回,性能开销很大。如果确实需要访问不对齐的数据,可以通过以下宏:
#include <asm/unaligned.h>
get_unaligned(ptr);
put_unaligned(val, ptr);
需要注意的是,有些编译器在编译的时候会对代码中的数据结构进行优化,导致定义的结构体占用的存储空间发生变化。为了解决这个问题,可以通过在结构体后指定__attribute__ ((packed))参数防止编译器填充字节。
struct {
    u16 id;
    u64 lun;
    u16 reserved1;
    u32 reserved2;
} __attribute__ ((packed)) scsi;
5. Pointers and Error Values
函数产生错误时,程序需要根据某些接口的返回值来决定下一步操作,这些值即错误代码定义在linux/err.h中。错误代码的相关操作函数:
void *ERR_PTR(long error);
long IS_ERR(const void *ptr);
long PTR_ERR(const void *ptr);

Linked Lists


 内核的很多数据结构通过双向链表管理,因此内核在linux/list.h定义了链表的数据结构,各种初始化、遍历、增删方法可以参见文件。

posted @ 2018-11-21 17:13  glob  阅读(188)  评论(0编辑  收藏  举报