深入理解Linux内核中的链表
最近,开始研读一下Linux的内核代码,刚一开始,就有令人惊叹的发现,不得不感叹内核代码设计得之美!单是最常用的链表也设计得不得不令人佩服!
1.1.链表list_head
include/linux/list.h
很经典,链表在内核中很常用,例如管理进程,进程的各个状态队列都是使用这个双向链表实现的。内核中的链表定义成和数据无关的形式,而不是通常我们使用的链表格式,例如
typedef struct _list{
Elemtype elem;
struct _list *next;
}list;
内核中的链表定义为
struct list_head{
struct list_head *next, *prev;
};
可见,这个链表节点中不包含任何数据,只有两个指针。当需要使用链表来组织数据结构时,这个结构中就包含一个list_head成员,例如
struct _list_struct{
Elemtype elem;
struct list_head list;
...
};
显而易见,链表实现成和数据分离的好处是,不用为每种数据都定义链表操作,可以使用统一的链表操作即可。但是问题是:只知道数据成员list的地址,怎样去访问自身以及其他成员呢?
#define list_entry(ptr,type,member) \
container_of(ptr,type,member)
而container_of(ptr,type,member)宏定义在include/list/kernel.h中
#define container_of(ptr,type,member) ({
const typeof( ((type *)0)->member) *__ptr=ptr;
(type *)( (char *)__ptr - offsetof(type,member));})
上面的宏有几点需要解释:
1)typeof(type) 宏
typeof(type) 宏返回变量type的类型,例如:int a; typeof(a) b;等价于int b;
2)offsetof(type,member)宏
它定义在include/linx/stddef.h中,如下:
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
这个宏返回member在type类型中的偏移量,type是一个结构,例如:
typeof(list_head,next);返回0,也就是返回相对于结构起始地址的偏移量。
3)为什么要使用typeof(((type *)0)->member)来定义指针 __ptr,而不是这样:
const typeof(member) *__ptr=ptr;?
其实,这个很简单,因为member是结构的成
相关文档:
介绍一种多LINUX系统的实现方法
目前,LINUX版本众多,桌面环境包括Gnome,KDE等,在一台电脑上安装Windows系统和多LINUX系统很有必要.这里介绍一种方法,多个LINUX系统之间各自独立,互不访问,各自都能访问Windows资源. ......
apache-tomact的安装
一.JDK的安装
1. 先从网上下载jdk(jdk-1_5_0-linux-i586.rpm) ,推荐SUN的官方网站http://www.sun.com/,下载后放在/home目录中(可以使用winscp软件施行上传),当然其它地方也行。
进入安装目录
#cd /home
#cp jdk-1_5_0_-linux-i586.rpm.bin /usr/local (拷贝命令)
#cd /usr/lo ......
在Redhat 9.0成功安装了ffmpeg,现记录如下。
1、下载ffmpeg。
http://download.chinaunix.net/do ... 532&ResourceID=2990
我是在这个网址上下载ffmpeg-0.4.9-p20051120.tar.bz2,看网上有人用的是svn下载,但是我的机子中没有svn客户端,然后就在网上搜索,下载了这个版本。如果利用svn可以下载ffmpeg� ......
我们知道默认外设I/O资源是不在Linux内核空间中的(如sram或硬件接口寄存器等),若需要访问该外设I/O资源,必须先将其地址映射到内核空间中来,然后才能在内核空间中访问它。
Linux内核访问外设I/O内存资源的方式有两种:动态映射(ioremap)和静态映射(map_desc)。
一、动态映射(ioremap)方式
� ......
gcc的编译过程分为四步,分别为:
(1)预编译 (Pre-Processing)
(2)编译 (Compiling)
(3)汇编 (Assembling)
(4)链接 (Linking)
以hello.c为例说明:
#include<stdio.h>
int main(void)
{
printf("Hello World!");
return 0;
}
(1)预编译阶段 (Pre-Processing)
&nbs ......