Linux设备驱动程序学习笔记——第十一章 内核的数据结构

Linux设备驱动程序学习笔记

第十一章 内核的数据结构

坚持使用严格的数据类型,并且使用-Wall -Wstrict-prototypes选项编译可以防止大多数的代码缺陷,提高可移植性。
内核使用的数据类型主要被分为三大类:
类似int的标准C语言类型
类似u32的有确定大小的类型
类似pid_t这样用于特定内核对象的类型
一、使用标准C语言类型
要避免类型冲突和潜在的风险。标准C语言类型会随体系架构发生变化,所占空间大小并不相同,主要表现在long类型。
内核的普通内存地址通常是unsigned long。

二、为数据项分配确定的空间大小

#include
u8;
u16;
u32;
u64;

//如果一个用户空间程序需要使用这些类型,可以在名字前加双下划线作为前缀:
__u8;

三、接口特定的类型
内核最常用的数据类型由它自己的typedef声明,这样可以防止出现任何移植性问题。

四、其他有关移植性的问题
时间间隔
在处理时间间隔时,不要假定每秒一定有100个jiffies。因为HZ值可能已被改变,使用jiffies计算时间间隔时,应该是用HZ来衡量。例如半秒:HZ/2
页大小
内存页大小为PAGE_SIZE字节,其不一定是4KB。
例如需要申请16KB空间:

#include
int order = get_order(16*1024);
buf = get_free_pages(GFP_KERNEL, order);

字节序
即大端小端。代码编写应尽量不依赖于字节序。
如必须,头文件定义了__BIG_ENDIAN或者_LITTLE_ENDIAN,取决于处理器的字节序。
在头文件中提供函数,可以将CPU使用的值转换成多少位的大头/小头数值,或者相反转换。

数据对齐
如果需要访问未对齐的数据应该是用以下宏:

#include
get_unaligned(ptr);
put_unaligned(val, ptr);

应该始终强制数据项的自然对齐:数据项的大小的整数倍的地址处存储数据项。
如果正在定义一个和设备所要求的结构体相匹配的结构体,要避免编译器本身的自动填充:

struct{
	u16 id;
	u64 lun;
	u16 reserved1;
	u32 reserved2;
}__attribute__ ((packed)) scsi;

指针和错误值
在函数失败时可以返回NULL,但其不能传递问题的确切性质。某些结构需要返回一个实际的错误编码,以帮助调用者根据实际出错情况做出正确的决策。
许多内核接口通过吧错误值编码到一个指针值中来返回错误信息。
创建和使用这种接口:

#include 
void *ERR_PTR(long err);//由错误码求指针,-1 -> 0xFFFFFFFF
long IS_ERR(const void *ptr)// 判断x是不是在(0xfffff000,0xffffffff)之间,x是不是一个错误编码
long PTR_ERR(const void *ptr);//由指针求错误码,0xFFFFFFFF -> -1

五、链表
略。

你可能感兴趣的:(Linux设备驱动笔记)