天衣有缝

冠盖满京华,斯人独憔悴~
posts - 35, comments - 115, trackbacks - 0, articles - 0
   :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

在用户程序中使用linux内核list(原创)

Posted on 2007-04-23 12:14 天衣有缝 阅读(5344) 评论(4)  编辑 收藏 引用 所属分类: program

    在我们日常程序中,常碰到写链表的情况。对于c++程序,stl提供了list和vector两个模板,使用起来很方便。但是很多环境下,我们只能使用c,大多数人都是自己封装相关接口,花费了不必要的时间。linux内核提供了基于面向对象思想的链表:include/linux/list.h。通过简单的修改就可以用到我们的用户程序中去。

转载请保留原创(msn and emailjinglexy at yahoo dot com dot cn)http://www.cppblog.com/jinglexy

这里是从montavista内核linux-2.6.10取出来的链表程序,2.62.4内核存在一些差异。具体程序分析可以参考:http://www-128.ibm.com/developerworks/cn/linux/kernel/l-chain,这里只说明使用情况。

首先修改源程序,在#ifdef __KERNEL__3include语句的后面加入下面程序:

(蓝色是加入部分)

#ifdef __KERNEL__


#include <linux/stddef.h>

#include <linux/prefetch.h>

#include <asm/system.h>

#elif 1

 

#define prefetch(x) 1

#define smp_wmb(x)     1

 

#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) );})

 

 

下面做一个测试程序:

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

#include "list.h"

 

#define DEBUG do {                                 \

       printf("**************************\n");        \

       printf("list 1:\n");                         \

       list_for_each(i, &list1) {              \

              mylist_t *ops =            \

              list_entry(i,                         \

              mylist_t, list);         \

              printf("pf is %d\n", ops->pf);              \

       }                                        \

                                                 \

       printf("list 2:\n");                         \

       list_for_each(i, &list2) {              \

              mylist_t *ops =            \

              list_entry(i,                         \

              mylist_t, list);         \

              printf("pf is %d\n", ops->pf);              \

       }                                        \

} while(0);

 

#if 1

typedef struct __mylist {

       int pf;

       char name[FILENAME_MAX];

 

       struct list_head list;

} mylist_t;

#else

typedef struct __mylist {

       struct list_head list;

 

       int pf;

       char name[FILENAME_MAX];

} mylist_t;

#endif

 

static LIST_HEAD(list1);             /* define 2 list */

static LIST_HEAD(list2);

 

int main(int argc, char *argv[])

{

       struct list_head *i;

       mylist_t elem1;

       mylist_t elem2;

 

       INIT_LIST_HEAD(&list1);

       INIT_LIST_HEAD(&list2);

       elem1.pf = 2008;

       elem2.pf = 8002;

       list_add(&elem1.list, &list1);

       list_del(&elem1.list);

 

       list_add(&elem1.list, &list1);

       list_add_tail(&elem2.list, &list1);

       DEBUG;

 

       /* move element to another list */

       list_move_tail(&elem2.list, &list2);

       list_splice_init(&list1, &list2);       /* merge */

       DEBUG;

 

       return 0;

}

 

 

使用gcc编译,gcc test.c,运行程序,结果正是我们想要的。

Feedback

# re: 在用户程序中使用linux内核list(原创)  回复  更多评论   

2007-04-23 12:31 by 天下无双
晕,写内核才有,写普通程序不是每个版本的Linux都有list可以用,比如FC6默认安装就没有它。还是要自己写一个,为了更好的移植性。

# re: 在用户程序中使用linux内核list(原创)  回复  更多评论   

2007-04-23 16:22 by 天衣有缝
使用list.h可不是内核的‘专利’,当然我假定大家都有一份2.6的内核源代码,
linux环境使用起来是很方便的,就是上面写的。

对于移植性,可能的确不太好吧,vc6就不指望编译通过了。我这没有vc7来验证一下,
听说改进挺大的。编译的时候可能会碰到一些问题,如果是gcc特性的话改一下相关地方:
({ …… })这个不知道是否支持
求0地址结构体域偏移也不知道是否支持

虽然麻烦,但是总比自己重新写、调试来的快。何况一个文件里面包含了普通链表,
哈希链表,rcu链表,算是比较‘超值’了

欢迎讨论

# re: 在用户程序中使用linux内核list(原创)  回复  更多评论   

2007-04-24 12:12 by hobbes
不错好东西:)

# re: 在用户程序中使用linux内核list(原创)  回复  更多评论   

2009-11-03 16:00 by DKs
有人试过在APP上多pthread使用这个rcu吗?

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理