《Linux就该这么学》是由全国多名红帽架构师(RHCA)基于最新Linux系统共同编写的高质量Linux技术自学教程,极其适合用于Linux技术入门教程或讲课辅助教材。
分类: LINUX
2016-05-26 21:45:20
导读 | Linux 内核中自己实现了双向链表,可以在 include/linux/list.h 找到定义。我们将会首先从双向链表数据结构开始介绍内核里的数据结构。为什么?因为它在内核里使用的很广泛,你只需要在 free-electrons.com 检索一下就知道了。 |
struct list_head { struct list_head *next, *prev; };
struct GList { gpointer data; GList *next; GList *prev; };
struct nmi_desc { spinlock_t lock; struct list_head head; };
#define MISC_MAJOR 10
ls -l /dev | grep 10 crw------- 1 root root 10, 235 Mar 21 12:01 autofs drwxr-xr-x 10 root root 200 Mar 21 12:01 cpu crw------- 1 root root 10, 62 Mar 21 12:01 cpu_dma_latency crw------- 1 root root 10, 203 Mar 21 12:01 cuse drwxr-xr-x 2 root root 100 Mar 21 12:01 dri crw-rw-rw- 1 root root 10, 229 Mar 21 12:01 fuse crw------- 1 root root 10, 228 Mar 21 12:01 hpet crw------- 1 root root 10, 183 Mar 21 12:01 hwrng crw-rw----+ 1 root kvm 10, 232 Mar 21 12:01 kvm crw-rw---- 1 root disk 10, 237 Mar 21 12:01 loop-control crw------- 1 root root 10, 227 Mar 21 12:01 mcelog crw------- 1 root root 10, 59 Mar 21 12:01 memory_bandwidth crw------- 1 root root 10, 61 Mar 21 12:01 network_latency crw------- 1 root root 10, 60 Mar 21 12:01 network_throughput crw-r----- 1 root kmem 10, 144 Mar 21 12:01 nvram brw-rw---- 1 root disk 1, 10 Mar 21 12:01 ram10 crw--w---- 1 root tty 4, 10 Mar 21 12:01 tty10 crw-rw---- 1 root dialout 4, 74 Mar 21 12:01 ttyS10 crw------- 1 root root 10, 63 Mar 21 12:01 vga_arbiter crw------- 1 root root 10, 137 Mar 21 12:01 vhci
struct miscdevice { int minor; const char *name; const struct file_operations *fops; struct list_head list; struct device *parent; struct device *this_device; const char *nodename; mode_t mode; };
static LIST_HEAD(misc_list);它实际上是对用list_head 类型定义的变量的扩展。
#define LIST_HEAD(name) \ struct list_head name = LIST_HEAD_INIT(name)
#define LIST_HEAD_INIT(name) { &(name), &(name) }
INIT_LIST_HEAD(&misc->list);
static inline void INIT_LIST_HEAD(struct list_head *list) { list->next = list; list->prev = list; }
list_add(&misc->list, &misc_list);
static inline void list_add(struct list_head *new, struct list_head *head) { __list_add(new, head, head->next); }
static inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next) { next->prev = new; new->next = next; new->prev = prev; prev->next = new; }
#define list_entry(ptr, type, member) \ container_of(ptr, type, member)
const struct miscdevice *p = list_entry(v, struct miscdevice, list)然后我们就可以使用p->minor 或者 p->name来访问miscdevice。让我们来看看list_entry 的实现:
#define list_entry(ptr, type, member) \ container_of(ptr, type, member)如我们所见,它仅仅使用相同的参数调用了宏container_of。初看这个宏挺奇怪的:
#define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );})
#include int main() { int i = 0; printf("i = %d\n", ({++i; ++i;})); return 0; }最终会打印出2。
#include struct s { int field1; char field2; char field3; }; int main() { printf("%p\n", &((struct s*)0)->field3); return 0; }结果显示0x5。
list_add list_add_tail list_del list_replace list_move list_is_last list_empty list_cut_position list_splice list_for_each list_for_each_entry等等很多其它API。
免费提供最新Linux技术教程书籍,为开源技术爱好者努力做得更多更好: