亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 1047 | 回復: 0
打印 上一主題 下一主題

在用戶空間編程使用linux內(nèi)核鏈表list,hlist宏定義和操作 [復制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2009-08-15 17:03 |只看該作者 |倒序瀏覽

在用戶空間編程使用linux內(nèi)核鏈表list,hlist宏定義和操作.
linux內(nèi)核中的list_head和hlist_head/hlist_node是將數(shù)據(jù)結(jié)構(gòu)串起來成為鏈表的兩個重要鏈表構(gòu)造工具。利用他們和其對應的宏定義,可以非常容易地將數(shù)據(jù)構(gòu)成鏈表,進行鏈表的各種操作,和數(shù)據(jù)查詢。
在內(nèi)核中,他們使用的十分廣泛。這些鏈表操作宏定義具有通用性,和具體數(shù)據(jù)結(jié)構(gòu)無關。
利用他們,編程者就不必要自己具體操作鏈表的指針,而集中精力關心數(shù)據(jù)本身。使用這些工具的程序效率是很高的。
因為他們是內(nèi)核定義的數(shù)據(jù)結(jié)構(gòu),在內(nèi)核編程使用起來十分簡單。
struct list_head { struct list_head *prev, *next; } 尺寸為2個指針大小。32位系統(tǒng)上為8個字節(jié)。
struct hlist_node 也是包含2個指針占8個字節(jié)。
struct hlist_head 占4個字節(jié).
用他們將多個相同的數(shù)據(jù)結(jié)構(gòu)串起來,必須在數(shù)據(jù)結(jié)構(gòu)中加上他們的定義。一個數(shù)據(jù)結(jié)構(gòu)也可以用多個相同鏈表或不同鏈表同時串起,串到多個不同的串中。
如果不在內(nèi)核而在用戶空間編程,也可以利用這些鏈表。(事實上,內(nèi)核其它的數(shù)據(jù)結(jié)構(gòu)多數(shù)都可以在用戶空間使用)。
要“移植到用戶空間”, 必須查找定義鏈表數(shù)據(jù)和宏的包含文件,將該文件拷貝出來,做適當改動,去掉內(nèi)核特定的定義開關。如果該文件中引用的其它內(nèi)核包含文件的關鍵數(shù)據(jù)定義,最好去掉引用,而將定義拷貝過來。
下面我給出的例子,就是一個用不同list_head和hash list將用戶數(shù)據(jù)struct ST同時串起來的例子。
i_list是普通list的串。
i_hash是hash list的串(實際是多個串,被HASH分散在數(shù)組中,HASH關鍵字即是數(shù)組下標)
你可以想象數(shù)據(jù)結(jié)構(gòu)是一個個貨場的相同型號的分散放置的集裝箱,為了將他們串起來,必須在箱子上安裝上有孔的鐵環(huán),然后用鐵絲通過這些安裝上鐵環(huán)就可以將他們串起來。
數(shù)據(jù)結(jié)構(gòu)中的定義struct list_head就相當于鐵環(huán),可以焊接到箱子的任何位置。頭部中間尾部都可以。
本例子中,一個箱子上安裝了2個環(huán),一個是i_list, 將箱子用一個長鐵絲全部穿起來的。
還安了一個環(huán)i_hash, 這個環(huán)的用途是將箱子分組串到不同的串中(每個串使用一個獨立的鐵絲,當然每根鐵絲長度就短了)。不同串的各個鐵絲的頭部排列放到一個hlist_head的數(shù)組中。
為了查找一個箱子,可以順著長鐵絲找(遍歷),一個一個比較,知道找到箱子。但這樣慢。
還可以直接順著某個短鐵絲找,如果事先可以確定要找的箱子必定在該端鐵絲串中--這是可以做到的,hash的作用。
struct hlist_head僅僅用了一個指針,占4個字節(jié),因為hash數(shù)組往往相當大,而每個串長度很短(hash的目的)。這樣可以節(jié)省4個字節(jié)乘以數(shù)據(jù)大小的空間。
文件list.h是 include/linux/list.h文件的用戶空間改編版本。
具體的定義的含義,我這里不再敘述,你可以自己查找。有許多內(nèi)核數(shù)據(jù)結(jié)構(gòu)分析的地方有解釋。
建議用戶用C編程時候,如涉及到鏈表使用,那么使用list_head! 可以極大節(jié)省你的工作量和調(diào)式時間。
linux內(nèi)核中還有許多定義好通用的東西,都是非常精彩和高效的。許多都可移植到用戶程序中使用。
#include stdio.h>
#include stdlib.h>
#include "list.h"
struct ST {
    unsigned char ch;
    int this_data;
     
    struct list_head i_list;
     
    int more_data;
     
    struct hlist_node i_hash;
     
    char str_data[32];
    //.......
    int end_data;
} *st;
struct list_head list1;
struct hlist_head hlist[1024];
#define LISTSIZE 1024
unsigned int gethash(int c)
{
    return (c & 0xff);
}
main()
{
int i;
unsigned int hash;
struct list_head *list;
struct list_head *n, *p;
struct ST *pst;
struct hlist_node *hp;
    INIT_LIST_HEAD(&list1);
    for(hash = 0; hash  LISTSIZE; hash++)
        INIT_HLIST_HEAD(&hlist[hash]);
    for(i = 0; i  LISTSIZE; i++) {
struct ST *p = malloc(sizeof(*p));
if(!p) {
    printf("malloc.\n");
    break;
}
p->ch = 'a' + i;
                //串入長串
                list_add(&p->i_list, &list1);
                //串入HASH短串
hash = gethash(p->ch);
printf("ALLOC %x %d %p %u\n", p->ch, i, p, hash);
hlist_add_head(&p->i_hash, &hlist[hash]);
    }
     
            
    //通過長鐵絲遍歷
    i = 0;
    list_for_each(list, &list1) {
struct ST *p = list_entry(list, struct ST, i_list);
        printf("%p value %d = %c\n", p, i, p->ch);
i++;
    }
    printf("total %d \n", i);
    //----------------------
    //通過hash串查找內(nèi)容'C'的箱子
    hash = gethash('c');
    hlist_for_each(hp, &hlist[hash]) {
struct ST *p = hlist_entry(hp, struct ST, i_hash);
printf("hlist: %c\n", p->ch);
    }
}

改編后的放在用戶空間的頭文件list.h

#ifndef _LINUX_LIST_H
#define _LINUX_LIST_H
  
#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 prefetch(const void *x) {;}
static inline void prefetchw(const void *x) {;}
#define LIST_POISON1 ((void *) 0x00100100)
#define LIST_POISON2 ((void *) 0x00200200)
struct list_head {
struct list_head *next, *prev;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
#define INIT_LIST_HEAD(ptr) do { \
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)
/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
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;
}
/**
* list_add - add a new entry
* @new: new entry to be added
* @head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
/**
* list_add_tail - add a new entry
* @new: new entry to be added
* @head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
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 = LIST_POISON1;
entry->prev = LIST_POISON2;
}
static inline void list_del_init(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
INIT_LIST_HEAD(entry);
}
static inline void list_move(struct list_head *list, struct list_head *head)
{
        __list_del(list->prev, list->next);
        list_add(list, head);
}
static inline void list_move_tail(struct list_head *list,
  struct list_head *head)
{
        __list_del(list->prev, list->next);
        list_add_tail(list, head);
}
static inline int list_empty(const struct list_head *head)
{
return head->next == head;
}
static inline int list_empty_careful(const struct list_head *head)
{
struct list_head *next = head->next;
return (next == head) && (next == head->prev);
}
static inline void __list_splice(struct list_head *list,
struct list_head *head)
{
struct list_head *first = list->next;
struct list_head *last = list->prev;
struct list_head *at = head->next;
first->prev = head;
head->next = first;
last->next = at;
at->prev = last;
}
/**
* list_splice - join two lists
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
static inline void list_splice(struct list_head *list, struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head);
}
/**
* list_splice_init - join two lists and reinitialise the emptied list.
* @list: the new list to add.
* @head: the place to add it in the first list.
*
* The list at @list is reinitialised
*/
static inline void list_splice_init(struct list_head *list,
    struct list_head *head)
{
if (!list_empty(list)) {
__list_splice(list, head);
INIT_LIST_HEAD(list);
}
}
#define list_entry(ptr, type, member) container_of(ptr, type, member)
#define list_for_each(pos, head) \
for (pos = (head)->next; prefetch(pos->next), pos != (head); \
         pos = pos->next)
#define __list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
#define list_for_each_prev(pos, head) \
for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
         pos = pos->prev)
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
     prefetch(pos->member.next), &pos->member != (head); \
     pos = list_entry(pos->member.next, typeof(*pos), member))
#define list_for_each_entry_reverse(pos, head, member) \
for (pos = list_entry((head)->prev, typeof(*pos), member); \
     prefetch(pos->member.prev), &pos->member != (head); \
     pos = list_entry(pos->member.prev, typeof(*pos), member))
#define list_prepare_entry(pos, head, member) \
((pos) ? : list_entry(head, typeof(*pos), member))
#define list_for_each_entry_continue(pos, head, member) \
for (pos = list_entry(pos->member.next, typeof(*pos), member); \
     prefetch(pos->member.next), &pos->member != (head); \
     pos = list_entry(pos->member.next, typeof(*pos), member))
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
     &pos->member != (head); \
     pos = n, n = list_entry(n->member.next, typeof(*n), member))
//HASH LIST
struct hlist_head {
struct hlist_node *first;
};
struct hlist_node {
struct hlist_node *next, **pprev;
};
#define HLIST_HEAD_INIT { .first = NULL }
#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
#define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->pprev = NULL)
static inline int hlist_unhashed(const struct hlist_node *h)
{
return !h->pprev;
}
static inline int hlist_empty(const struct hlist_head *h)
{
return !h->first;
}
static inline void __hlist_del(struct hlist_node *n)
{
struct hlist_node *next = n->next;
struct hlist_node **pprev = n->pprev;
*pprev = next;
if (next)
next->pprev = pprev;
}
static inline void hlist_del(struct hlist_node *n)
{
__hlist_del(n);
n->next = LIST_POISON1;
n->pprev = LIST_POISON2;
}
static inline void hlist_del_init(struct hlist_node *n)
{
if (n->pprev) {
__hlist_del(n);
INIT_HLIST_NODE(n);
}
}
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
struct hlist_node *first = h->first;
n->next = first;
if (first)
first->pprev = &n->next;
h->first = n;
n->pprev = &h->first;
}
/* next must be != NULL */
static inline void hlist_add_before(struct hlist_node *n,
struct hlist_node *next)
{
n->pprev = next->pprev;
n->next = next;
next->pprev = &n->next;
*(n->pprev) = n;
}
static inline void hlist_add_after(struct hlist_node *n,
struct hlist_node *next)
{
next->next = n->next;
n->next = next;
next->pprev = &n->next;
if(next->next)
next->next->pprev = &next->next;
}
#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
#define hlist_for_each(pos, head) \
for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
     pos = pos->next)
#define hlist_for_each_safe(pos, n, head) \
for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
     pos = n)
#define hlist_for_each_entry(tpos, pos, head, member) \
for (pos = (head)->first; \
     pos && ({ prefetch(pos->next); 1;}) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
     pos = pos->next)
#define hlist_for_each_entry_continue(tpos, pos, member) \
for (pos = (pos)->next; \
     pos && ({ prefetch(pos->next); 1;}) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
     pos = pos->next)
#define hlist_for_each_entry_from(tpos, pos, member) \
for (; pos && ({ prefetch(pos->next); 1;}) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
     pos = pos->next)
#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
for (pos = (head)->first; \
     pos && ({ n = pos->next; 1; }) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
     pos = n)
#endif


本文來自ChinaUnix博客,如果查看原文請點:http://blog.chinaunix.net/u2/87570/showart_2028785.html
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復

  

北京盛拓優(yōu)訊信息技術有限公司. 版權所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP