LDD读书笔记第十一章-内核的数据类型
Linux数据类型
| Arch | char | short | int | long | ptr | long-long | u8 | u16 | u32 | u64 |
| i386 | 1 | 2 | 4 | 4 | 4 | 8 | 1 | 2 | 4 | 8 |
| alpha | 1 | 2 | 4 | 8 | 8 | 8 | 1 | 2 | 4 | 8 |
| armv41 | 1 | 2 | 4 | 4 | 4 | 8 | 1 | 2 | 4 | 8 |
| ia64 | 1 | 2 | 4 | 8 | 8 | 8 | 1 | 2 | 4 | 8 |
| m86k | 1 | 2 | 4 | 4 | 4 | 8 | 1 | 2 | 4 | 8 |
| mips | 1 | 2 | 4 | 4 | 4 | 8 | 1 | 2 | 4 | 8 |
| ppc | 1 | 2 | 4 | 4 | 4 | 8 | 1 | 2 | 4 | 8 |
| sparc | 1 | 2 | 4 | 4 | 4 | 8 | 1 | 2 | 4 | 8 |
| sparc64 | 1 | 2 | 4 | 4 | 4 | 8 | 1 | 2 | 4 | 8 |
| x86_64 | 1 | 2 | 4 | 8 | 8 | 8 | 1 | 2 | 4 | 8 |
需要注意的是sparc64架构运行的是32位用户空间。但是在内核空间是64位的。
在当前的所有平台上指针和long型的大小总相同
u8等固定大小的值有其有符号版本以s代替u如:s8
如果需要在用户空间使用固定大小的话使用双下划线版本如__u8
固定大小的类型是linux特有的 如果考虑向其他unix变种移植应使用C99标准类型变量如:uint8_t
其他有关移植性的问题
时间变量
使用时间变量的时候不要使用特定的值而是使用HZ宏如:
n毫秒为:n*HZ/1000
页大小
同样不要使用特定的值。而是使用如下函数
1 2 3 | #include <asm/page.h> int order = get_order(16*1024); /*传递的参数必须是2的幂*/ buf = get_free_pages(GFP_KERNEL,order); |
字节序
不要对字节序做任何假设。
头文件asm/byteorder.h根据平台定义了__BIG_ENDIAN 或 __LITTLE_ENDIAN。
也可以使用如下函数转换成需要的类型
1 2 | u32 cpu_to_le32 (u32); u32 le32_to_cpu (u32); |
这些宏相对le有be版本如be32_to_cpu,并且有相应的16为版本。
更多资料查看:
linux/byteorder/big_endian.h
linux/byteorder/little_endian.h
数据对齐
访问未对其的数据
1 2 3 | #include <asm/unaligned.h> get_unaligned(ptr); put_unaligned(val, ptr); |
对结构添加__attribute__可防止编译器自动对齐如
1 2 3 4 5 6 | struct { u16 id; u64 lun; u16 reserved1; u32 reserved2; } __attribute__ ((packed)) scsi; |
指针和错误值
1 2 3 4 | #include <linux/err.h> void *ERR_PTR(long error);/*错误码到指针类型的错误指针*/ long IS_ERR(const void *ptr);/*判断是否为错误指针*/ long PTR_ERR(const void *ptr);/*错误指针到错误码*/ |
链表

如果重入的时候可能并发访问必须给链表添加锁机制。
定义在linux/list.h中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | struct list_head { struct list_head *next, *prev; }; 使用链表: <pre lang="C"> #include <linux/list.h> struct todo_struct { struct list_head list; int priority; /* driver specific */ /* 其他字段 */ }; /*运行时初始化链表头*/ struct list_head todo_list; INIT_LIST_HEAD(&todo_list); /*编译时初始化*/ LIST_HEAD(todo_list); /*添加删除相关函数*/ list_add(struct list_head *new, struct list_head *head); /*添加到头部*/ list_add_tail(struct list_head *new, struct list_head *head); /*添加到尾部*/ list_del(struct list_head *entry); list_del_init(struct list_head *entry); /*删除链表项,如果可能插入到其他链表,使用init版本*/ list_move(struct list_head *entry, struct list_head *head); list_move_tail(struct list_head *entry, struct list_head *head); /*把给定的链表移动到头部或尾部*/ list_empty(struct list_head *head); /*如果链表为空返回非零值*/ list_splice(struct list_head *list, struct list_head *head); /*head之后插入list来合并链表*/ |
获取包含链表的结构的指针
1 2 3 4 | list_entry(struct list_head *ptr, type_of_struct, field_name); /*ptr为链表结构,type_of_struct为包含链表的结构的名称 *field_name为结构中链表字段的名称 */ |
遍历链表
1 2 3 4 5 6 7 8 9 10 | list_for_each(struct list_head *cursor, struct list_head *list) /*遍历链表*/ list_for_each_prev(struct list_head *cursor, struct list_head *list) /*向前遍历链表*/ list_for_each_safe(struct list_head *cursor, struct list_head *next, struct list_head *list) /*如果在遍历中需要删除链表使用此方法*/ list_for_each_entry(type *cursor, struct list_head *list, member) list_for_each_entry_safe(type *cursor, type *next, struct list_head *list,member) /*遍历并且直接获取包含链表的结构体的指针*/ |
两个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 | void todo_add_entry(struct todo_struct *new) { struct list_head *ptr; struct todo_struct *entry; for (ptr = todo_list.next; ptr != &todo_list; ptr = ptr->next) { entry = list_entry(ptr, struct todo_struct, list); if (entry->priority < new->priority) { list_add_tail(&new->list, ptr); return; } } list_add_tail(&new->list, &todo_struct) } |
1 2 3 4 5 6 7 8 9 10 11 12 13 | void todo_add_entry(struct todo_struct *new) { struct list_head *ptr; struct todo_struct *entry; list_for_each(ptr, &todo_list) { entry = list_entry(ptr, struct todo_struct, list); if (entry->priority < new->priority) { list_add_tail(&new->list, ptr); return; } } ist_add_tail(&new->list, &todo_struct) } |
----------------- 全文结束 -----------------
© 该日志作者:Senghoo, 于2010年07月29日发表于分类"Linux Kernel"下;
© 除非另有注明本文采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。
© 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
© 转载请注明: LDD读书笔记第十一章-内核的数据类型 | 转自: Senghoo's Blog
© Tag: ldd , linux , 内核 , 数据类型
© 除非另有注明本文采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。
© 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
© 转载请注明: LDD读书笔记第十一章-内核的数据类型 | 转自: Senghoo's Blog
© Tag: ldd , linux , 内核 , 数据类型