《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技术教程书籍,为开源技术爱好者努力做得更多更好: