Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2295985
  • 博文数量: 395
  • 博客积分: 10994
  • 博客等级: 上将
  • 技术积分: 5586
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-17 19:49
文章存档

2014年(1)

2013年(10)

2012年(74)

2011年(303)

2010年(7)

分类: LINUX

2011-06-23 20:58:15

前言:linux内核中会经常碰到内核链表,并且这些链表运用的算法非常经典。学习内核链表是你学习linux内核重要的一步。

 

[root@bogon guoqian]# mkdir 4-4-2

[root@bogon guoqian]# ls

4-1-1  4-1-4  4-2-6-1  4-3-3  4-3-6  nfsroot

4-1-2  4-2-1  4-3-1    4-3-4  4-4-1  u-boot-2008.10

4-1-3  4-2-6  4-3-2    4-3-5  4-4-2  u-boot-2008.10.tar.bz2

[root@bogon guoqian]# cd 4-4-2/

[root@bogon 4-4-2]# ll

总计 0

[root@bogon 4-4-2]# cp ../

 [root@bogon 4-4-2]# cp ../4-4-1/Makefile ./

[root@bogon 4-4-2]# ls

Makefile

[root@bogon 4-4-2]# vi mylist.c 

#include

#include

#include

#include

#include

 

MODULE_LICENSE("GPL");

MODULE_AUTHOR("feifei");

MODULE_DESCRIPTION("List Module");

MODULE_ALIAS("List moudle");

 

struct student{

        char name[100];

        int num;

        struct list_head list;

};

 

struct student *pstudent;

struct student *tmp_student;

struct list_head student_list;

struct list_head *pos;

 

static int __init mylist_init(void){

        int i=0;

 

        INIT_LIST_HEAD(&student_list);

 

        pstudent = kmalloc(sizeof(struct student)*5,GFP_KERNEL);

        memset(pstudent,0,sizeof(struct student)*5);

 

        for(i=0;i<5;i++){

                sprintf(pstudent[i].name,"Student%d",i+1);

                pstudent[i].num=i+i;

                list_add(&(pstudent[i].list),&student_list);

        }

 

        list_for_each(pos,&student_list){ //下面会解释这些宏的定义

                tmp_student=list_entry(pos,struct student,list);

                printk("<0>student %d name:%s\n",tmp_student->num,tmp_student->name);

        }

        return 0;

}

 

static void __exit mylist_exit(void){

        int i;

        for(i=0;i<5;i++){

                list_del(&(pstudent[i].list));

        }

        kfree(pstudent);

}

 

module_init(mylist_init);

module_exit(mylist_exit);

 

[root@bogon 4-4-2]# vi Makefile 

ifneq ($(KERNELRELEASE),)

 

obj-m :=mylist.o

 

else

KDIR :=/home/guoqian/4-3-1/linux-2.6.29

all:

        make -C $(KDIR) M=$(PWD) modules

 

clean:

        rm -f *.ko *.o *.mod.o *.mod.c *.symvers

endif

[root@bogon 4-4-2]# cp mylist.ko /home/guoqian/nfsroot/rootfs/tmp/

 

超级终端:

U-Boot 2008.10 (Jun 18 2011 - 18:29:43)

 

DRAM:  64 MB

Flash:  2 MB

In:    serial

Out:   serial

Err:   serial

Mini2440 #

Mini2440 # bootm 31000000

eth0: link down

IP-Config: Guessing netmask 255.0.0.0

IP-Config: Complete:

     device=eth0, addr=59.70.157.173, mask=255.0.0.0, gw=255.255.255.255,

     host=59.70.157.173, domain=, nis-domain=(none),

     bootserver=255.255.255.255, rootserver=59.70.157.174, rootpath=

Looking up port of RPC 100003/2 on 59.70.157.174

eth0: link up, 100Mbps, full-duplex, lpa 0x41E1

Looking up port of RPC 100005/1 on 59.70.157.174

VFS: Mounted root (nfs filesystem) on device 0:11.

Freeing init memory: 128K

 

Processing /etc/profile... Done

 

# cd /tmp/

# ls

alloc_mem.ko  mylist.ko

# insmod mylist.ko

student 5 name:Student5

student 4 name:Student4

student 3 name:Student3

student 2 name:Student2

student 1 name:Student1

# lsmod

mylist 1420 0 - Live 0xbf000000

# rmmod mylist

rmmod: module 'mylist' not found

# lsmod

#

 

对上面的一些宏的定义:

以下转自:http://blog.csdn.net/jiatingqiang/archive/2011/05/22/6437496.aspx

和:http://cutebunny.blog.51cto.com/301216/67517

list_entry的宏定义:

#define list_entry(ptr, type, member) \ 
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) 

 

再看上面这个以前,先看看这个定义:

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER);

分析:
(TYPE *)0,
0 强制转换为 TYPE 型指针,记 p = (TYPE *)0p是指向TYPE的指针,它的值是0。那么 p->MEMBER 就是 MEMBER 这个元素了,而&(p->MEMBER)就是MENBER的地址,而基地址为0,这样就巧妙的转化为了TYPE中的偏移量。再把结果强制转换为size_t型的就OK了,size_t其实也就是int


然后再看上面的
(char *)(ptr)
使得指针的加减操作步长为一字节,(unsigned long)(&((type *)0)->member)等于ptr指向的member到该member所在结构体基地址的偏移字节数。二者一减便得出该结构体的地址。转换为 (type *)型的指针

 

 

阅读(1365) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~