Chinaunix首页 | 论坛 | 博客
  • 博客访问: 309000
  • 博文数量: 72
  • 博客积分: 3111
  • 博客等级: 中校
  • 技术积分: 668
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-30 15:45
个人简介

朝着心的方向前进

文章分类

全部博文(72)

文章存档

2014年(5)

2013年(1)

2012年(1)

2011年(1)

2010年(24)

2009年(40)

我的朋友

分类: LINUX

2010-04-08 16:02:14

自己是个初学者,一直在学习国嵌的教程,本来是在本子上做的笔记,今天学习到内核链表了,老师留了个小问题,自己做了一下,算是写下自己的心得吧.
大牛们一定不要见笑...
源程序如下:
#include
#include
#include
#include
#include
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Xie");
MODULE_DESCRIPTION("List Module");
MODULE_ALIAS("List module");
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,*node;//add node
int mylist_init()
{
 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+1;
  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;
}

void mylist_exit()

 int i ;
 /* 实验:将for换成list_for_each来遍历删除结点,观察要发生的现象,并考虑解决办法 */
 for(i=0;i<5;i++)
        list_del(&(pstudent[i].list));
      
 kfree(pstudent);
}
module_init(mylist_init);
module_exit(mylist_exit);
makefile文件内容如下//顺便复习模块的基本知识,linux的东西真多呀,看来嵌入式之路漫漫呀...
ifneq ($(KERNELRELEASE),)
obj-m := mylist.o
else
 
KDIR := /lib/modules/2.6.18-53.el5/build
all:
 make -C $(KDIR) M=$(PWD) modules
clean:
 rm -f *.ko *.o *.mod.o *.mod.c *.symvers
endif
按老师的留的思考题:
如果是换成list_for_each遍历删除节点,我开始是如下修改的
void mylist_exit()

 list_for_each(pos,&student_list);   //这里写的真是乱改,反正出现的情况就是死机,
    list_del(&student_list);            //这里的格式都不对,list_for_list原型是for,后来语句是{}的,这里
 kfree(pstudent);                    // 都没有做,另外还要用list_entry提到数据后才能遍历操作...
}
总之,一直是死机,后来也修改了一些格式,还是死机,问了群里的朋友,说是要用到list_for_list_safe才能安全删除
于是就G了一下,发现:
函数原型分析
#define list_for_each(pos, head) \
for (pos = (head)->next; prefetch(pos->next), pos != (head); \
pos = pos->next)
由定义可知,list_del(pos)(将pos的前后指针指向undefined state)panic,list_del_init(pos)(将pos前后指针指向自身)导致死循环.--当删除时,链表指针变为特殊类型,所以死机.
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
由定义可知,safe函数首先将pos的后指针缓存到n,处理一个流程后再赋回pos,避免了这种情况的发生。
因此只遍历链表不删除节点时可以使用前者,若有删除节点的操作,则要使用后者。
由safe的说明可知,是专门为删除节点时准备的:iterate over a list safe against removal of list entry。
其他带safe的处理也基本源于这个原因。
下面进行了更改
修改程序为:
先定义一个和pos同样类型的node指针用以保存pos的后的指针
然后修改 exit_mylist函数,修改后如下:
void mylist_exit()

 //int i ;
 /* 实验:将for换成list_for_each来遍历删除结点,观察要发生的现象,并考虑解决办法 */
 //for(i=0;i<5;i++)
    list_for_each_safe(pos,node,&student_list)
 {
  //list_del(&(pstudent[i].list));
        tmp_student = list_entry(pos,struct student,list);//提取数据,我开始这个也不知道,哎...
        list_del(&(tmp_student->list));
        printk("<0>student %d name: %s is being deleted.\n",tmp_student->num,tmp_student->name);
 }
 
 kfree(pstudent);
}
这样,就不会死机了...
注:没有学过数据结构,看看那么厚的一本书,也不知道如何下手,老师讲到这了,就学点东西吧.
阅读(10934) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

jackyding26792011-12-20 17:51:17

不错