<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"></span><pre name="code" class="cpp">#include <linux/module.h>
#include <linux/init.h>
#include<linux/sched.h>
#include<linux/sem.h>
#include <linux/slab.h>
#include <linux/list.h>
MODULE_LICENSE("Dual BSD/GPL");
struct group{
int id;
char character;
struct list_head member;
};
int list_head_init(void)
{
printk("list_head init\n");
struct group testhead={
.id=-1,
.character='a',
.member=LIST_HEAD_INIT(testhead.member),
};
//插入10个元素
int i=0;
for(i=0;i<10;i++)
{
struct group *testtemp;
testtemp=kmalloc(sizeof(struct group),GFP_KERNEL);
if(testtemp==NULL) return -1;
testtemp->id=i;
testtemp->character=(char)(64+i);
list_add(&testtemp->member,&testhead.member);
//printk(KERN_ALERT"%d--->%c\n",testtemp->intdata,testtemp->chardata);
}
//遍历10个元素
//每一次由1个数据项(链表共10个数据项,前后数据项节点由该数据项节点的list_head类型成员member连接起来)
//节点的list_head成员member求出该数据项节点的地址,即&member-->(struct group *) ,求出数据项地址,就可使用数据项成员了
struct group *groups,*p;
struct list_head *pos;
int count=0;
printk(KERN_ALERT"Hello World enter begin:\n");
groups=&testhead;
//第一次 pos 为id = 9的数据项成员member的地址&member ,共10次
list_for_each(pos,&groups->member)
{
//第一次 由&member(id=9数据项成员member地址)计算出id=9数据项的地址,共10次
p=list_entry(pos, struct group, member);
count++;
printk(KERN_ALERT"id is %d---> name %c\n",p->id,p->character);
}
printk(KERN_ALERT"the member of group is:%d\n",count);
//删除元素
list_del(&p->member);
count=0;
//遍历剩余元素
list_for_each(pos,&groups->member)
{
p=list_entry(pos, struct group, member);
count++;
printk(KERN_ALERT"id is %d---> name %c\n",p->id,p->character);
}
printk(KERN_ALERT"the member of group is:%d\n",count);
return 0;
}
static void list_head_exit(void)
{
printk("list_head exit\n");
}
module_init(list_head_init);
module_exit(list_head_exit);
<pre name="code" class="cpp">Makefile:
KERN_DIR = /work/system/linux-2.6.22.6
all:
make -C $(KERN_DIR) M=`pwd` modules
clean:
make -C $(KERN_DIR) M=`pwd` modules clean
rm -rf modules.order
obj-m += list_head.o
//编译服务器上:
root@book-desktop:/work/xyc_drivers_and_test/testlist# make
make -C /work/system/linux-2.6.22.6 M=`pwd` modules
make[1]: Entering directory `/work/system/linux-2.6.22.6'
CC [M] /work/xyc_drivers_and_test/testlist/list_head.o
/work/xyc_drivers_and_test/testlist/list_head.c: In function `list_head_init':
/work/xyc_drivers_and_test/testlist/list_head.c:25: warning: ISO C90 forbids mixed declarations and code
/work/xyc_drivers_and_test/testlist/list_head.c:42: warning: ISO C90 forbids mixed declarations and code
/work/xyc_drivers_and_test/testlist/list_head.c:42: warning: 'p' might be used uninitialized in this function
Building modules, stage 2.
MODPOST 1 modules
CC /work/xyc_drivers_and_test/testlist/list_head.mod.o
LD [M] /work/xyc_drivers_and_test/testlist/list_head.ko
make[1]: Leaving directory `/work/system/linux-2.6.22.6'
root@book-desktop:/work/xyc_drivers_and_test/testlist# cp list_head.ko /work/nfs_root/xyc_first_fs/
//串口下:
# insmod list_head.ko
list_head init
Hello World enter begin:
id is 9---> name I
id is 8---> name H
id is 7---> name G
id is 6---> name F
id is 5---> name E
id is 4---> name D
id is 3---> name C
id is 2---> name B
id is 1---> name A
id is 0---> name @
the member of group is:10
id is 9---> name I
id is 8---> name H
id is 7---> name G
id is 6---> name F
id is 5---> name E
id is 4---> name D
id is 3---> name C
id is 2---> name B
id is 1---> name A
the member of group is:9
此测试模块依赖list.h头文件中断宏: LIST_HEAD_INIT list_for_each list_entry已经函数list_add等等,所以用的编译成内核模块的方式测试他,自己如果想在应用程序中使用list_head 的相应操作(当然应该没人使用了,C++ STL提供了list 用起来貌似更方便), 在应用程序中需要包含自己的 "list.h" 头文件:
/*
注:这个list.h 是为了配合示例程序而建的,内容来自:linux/include/linux/list.h 和相关文件
*/
#ifndef _LINUX_LIST_H
#define _LINUX_LIST_H
struct list_head {
struct list_head *next, *prev;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
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;
}
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
static inline void __list_del(struct list_head * prev, struct list_head * next)
{
next->prev = prev;
prev->next = next;
}
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = NULL;
entry->prev = NULL;
}
#define prefetch(x) __builtin_prefetch(x)
//注:这里prefetch 是gcc的一个优化,也可以不要
#define list_for_each(pos, head) \
for (pos = (head)->next; prefetch(pos->next), pos != (head); \
pos = pos->next)
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
#endif
写了一个简单的应用程序:
#include "list.h"
#include <stdio.h>
#include <string.h>
#define MAX_NAME_LEN 32
#define MAX_ID_LEN 10
typedef struct stud
{
struct list_head list;
char name[MAX_NAME_LEN];
char stu_number[MAX_ID_LEN];
}num_n_stu;
int main(void)
{
struct list_head head;
num_n_stu stu_1;
num_n_stu stu_2;
num_n_stu *entry;
struct list_head *p;
INIT_LIST_HEAD(&head);
strcpy(stu_1.name,"lisi");
strcpy(stu_1.stu_number,"10000000");
strcpy(stu_2.name,"zhangsan");
strcpy(stu_2.stu_number,"10000001");
list_add(&stu_1.list,&head);
list_add(&stu_2.list,&head);
list_del(&stu_2.list);
list_for_each(p,&head)
{
entry=list_entry(p,struct stud,list);
printf("name: %s\n",entry->name);
printf("stu_number: %s\n",entry->stu_number);
}
list_del(&stu_1.list);
return 0;
}
在Linux内核中可以使用这个以类似驱动模块的形式加载到内核:(这里就不用使用自定义的list.h了)
#include <linux/list.h>
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
#define MAX_NAME_LEN 32
#define MAX_ID_LEN 10
typedef struct stud
{
struct list_head list;
char name[MAX_NAME_LEN];
char stu_number[MAX_ID_LEN];
}num_n_stu;
static int my_main(void)
{
struct list_head head;
num_n_stu stu_1;
num_n_stu stu_2;
num_n_stu *entry;
struct list_head *p;
INIT_LIST_HEAD(&head);
strcpy(stu_1.name,"lisi");
strcpy(stu_1.stu_number,"10000000");
strcpy(stu_2.name,"zhangsan");
strcpy(stu_2.stu_number,"10000001");
list_add(&stu_1.list,&head);
list_add(&stu_2.list,&head);
list_del(&stu_2.list);
list_for_each(p,&head)
{
entry=list_entry(p,struct stud,list);
printk("name: %s\n",entry->name);
printk("stu_number: %s\n",entry->stu_number);
}
list_del(&stu_1.list);
return 0;
}
static void my_exit(void)
{
printk("my_exit ! \n");
}
module_init(my_main);
module_exit(my_exit);
操作系统:ubuntu10.04
前言:
typeof关键字是C语言中的一个新扩展(非c89 c99关键字),这个特性在linux内核中应用非常广泛。
一,说明
typeof的参数可以是两种形式:表达式或类型。
1,表达式的的例子:
typeof(x[0](1))
这里假设x是一个函数指针数组,这样就可以得到这个函数返回值的类型了。
如果将typeof用于表达式,则该表达式不会执行。只会得到该表达式的类型。
以下示例声明了int类型的var变量,因为表达式foo()是int类型的。由于表达式不会被执行,所以不会调用foo函数。
extern int foo();
typeof(foo()) var;
2,参数的例子:
typeof(int *) a,b;
等价于:
int *a,*b;
root@book-desktop:/work/xyc_drivers_and_test# cc typeof.c
root@book-desktop:/work/xyc_drivers_and_test# ./a.out
sizeof(a) = 4, sizeof(b) =4
前言:
typeof关键字是C语言中的一个新扩展(非c89 c99关键字),这个特性在linux内核中应用非常广泛。
一,说明
typeof的参数可以是两种形式:表达式或类型。
1,表达式的的例子:
typeof(x[0](1))
这里假设x是一个函数指针数组,这样就可以得到这个函数返回值的类型了。
如果将typeof用于表达式,则该表达式不会执行。只会得到该表达式的类型。
以下示例声明了int类型的var变量,因为表达式foo()是int类型的。由于表达式不会被执行,所以不会调用foo函数。
extern int foo();
typeof(foo()) var;
2,参数的例子:
typeof(int *) a,b;
等价于:
int *a,*b;
下面是两个等效声明,用于声明int类型的变量a。
typeof(int) a; /*int类型*/
typeof('b') a; /* GCC中这个表达式的类型是int(自动提升为int),
注意typeof(char)和typeof('b')得到的不是一样的,这个用sizeof可以看出来*/
测试:
typeof.c:
#include<stdio.h>
int main()
{
typeof(int) a;
typeof('c') b;
printf("sizeof(a) = %d, sizeof(b) =%d\n", sizeof(a), sizeof(b));
return 0;
}
root@book-desktop:/work/xyc_drivers_and_test# cc typeof.c
root@book-desktop:/work/xyc_drivers_and_test# ./a.out
sizeof(a) = 4, sizeof(b) =4
一般情况下用typeof就可以了,但是如果要于ISO C兼容的话,最好是用双下划线的形式:__typeof__。
typeof和typedef很像,事实上,只要能用typedef的地方就可以用typeof。
二,实例
1,把y定义成x指向的数据类型:
typeof(*x) y;
2,把y定义成x指向数据类型的数组:
typeof(*x) y[4];
3,把y定义成一个字符指针数组:
typeof(typeof(char *)[4] ) y;
这与下面的定义等价:
char *y[4];
char *y[4]换一种定义形式:
#define pointer(T) typeof(T *)
#define array(T,N) typeof(T [N])
array (pointer(char),4) y;
如果想把T定义成一个表达式的类型,则我们仅仅用typedef无法做到
但可以通过typeof做到:
typdef typeof(expr) T;
4, typeof(int *) p1,p2; /* Declares two int pointers p1, p2 */
int *p1, *p2;
5, typeof(int) *p3,p4;/* Declares int pointer p3 and int p4 */
int *p3, p4;
6, typeof(int [10]) a1, a2;/* Declares two arrays of integers */
int a1[10], a2[10];
三 ,局限
typeof构造中的类型名 不能 包含存储类说明符,如 extern 或 static 。不过允许包含类型限定符,如 const 或 volatile 。
例如,下列代码是无效的,因为它在typeof构造中声明了extern:
typeof(extern int) a;
下列代码使用外部链接来声明标识符b是有效的,表示一个int类型的对象。下一个声明也是有效的,它声明了一个使用const限定符的char类型指针, 表示指针p不能被修改。
extern typeof(int) b;
typeof(char * const) p = "a";
四,文件参考
1,http://blog.youkuaiyun.com/wslong/article/details/7728811
2,https://gcc.gnu.org/onlinedocs/gcc/Typeof.html
#define array(T,N) typeof(T [N])
array (pointer(char),4) y;
如果想把T定义成一个表达式的类型,则我们仅仅用typedef无法做到
但可以通过typeof做到:
typdef typeof(expr) T;
4, typeof(int *) p1,p2; /* Declares two int pointers p1, p2 */
int *p1, *p2;
5, typeof(int) *p3,p4;/* Declares int pointer p3 and int p4 */
int *p3, p4;
6, typeof(int [10]) a1, a2;/* Declares two arrays of integers */
int a1[10], a2[10];
三 ,局限
typeof构造中的类型名 不能 包含存储类说明符,如 extern 或 static 。不过允许包含类型限定符,如 const 或 volatile 。
例如,下列代码是无效的,因为它在typeof构造中声明了extern:
typeof(extern int) a;
下列代码使用外部链接来声明标识符b是有效的,表示一个int类型的对象。下一个声明也是有效的,它声明了一个使用const限定符的char类型指针, 表示指针p不能被修改。
extern typeof(int) b;
typeof(char * const) p = "a";
四,文件参考
1,http://blog.youkuaiyun.com/wslong/article/details/7728811
2,https://gcc.gnu.org/onlinedocs/gcc/Typeof.html