linuxのリストリストの操作
記事の転載は原文の住所を表示してください。http://blog.csdn.net/uranus_wm/articale/detail/11933201
Linux駆動開発はよくチェーンを使います。ここでチェーンの関連操作をまとめます。
1.ファイルの位置:/include/linux/type.h
linuxで定義されているチェーンは双方向循環リンク表であり、構造体のタイプの定義は以下の通りである。
2.直接リストを使うheadタイプのサブメンバーはチェーンを初期化して、最初はchノード自身だけで、prevとnextポインタのドメインは自分を指す:
3.チェーンノードを追加して、チェーンの頭または尾に追加してもいいです。同様の削除と追加が可能です。ここでは詳しく説明していません。
次に、IDによってマッチングするかどうかは、検索が必要なノードである。
リスト.for_each_entry(pos,head,member)はfor(初期条件;条件判断;ブロック終了文)です。ループ
初期条件語句:list_によるentryはチェーンチャンネルを獲得します。リスト後の最初のノードは、親タイプs 3 c_に戻る。pl 330_チャンネル
条件判定文:置換後は&ch.node!=(&chan_list);今ならs 3 c_pl 330_chanの父のタイプのノードのnodeチェーンの針は&chan_;ではありません。リストヘッドポインタは、チェーンがまだ全て通っていないということです。
ブロック終了文:posは現在のノードの次のノードを指します。
このような構造体があり、ptrはmemberタイプのポインタであり、memberのメモリ中のアドレスを指すことが理解できる。
Linux駆動開発はよくチェーンを使います。ここでチェーンの関連操作をまとめます。
1.ファイルの位置:/include/linux/type.h
linuxで定義されているチェーンは双方向循環リンク表であり、構造体のタイプの定義は以下の通りである。
struct list_head {
struct list_head *next, *prev;
};
使用者は通常自分の構造体の内部にlist_を含む。headメンバー、例えば:struct s3c_pl330_chan {
unsigned long sdaddr;
struct list_head node;
struct pl330_req *lrq;
struct list_head xfer_list;
};
上s 3 c_pl 330_chanという構造体の内部には二つのstruct list_があります。headタイプメンバー、説明s 3 c_pl 330_チャンという構造体験は同時に二つのチェーンに現れます。2.直接リストを使うheadタイプのサブメンバーはチェーンを初期化して、最初はchノード自身だけで、prevとnextポインタのドメインは自分を指す:
struct s3c_pl330_chan *ch;
INIT_LIST_HEAD(&ch->xfer_list);
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
マクロ定義を使うとLIST_HEADはnameという名前のグローバルチェーンを作って、最初はheadノードが一つしかなくて、prevとnextポインタ領域は自分を指します。#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
/* chan_list*/
static LIST_HEAD(chan_list);
3.チェーンノードを追加して、チェーンの頭または尾に追加してもいいです。同様の削除と追加が可能です。ここでは詳しく説明していません。
ch = kmalloc(sizeof(*ch), GFP_KERNEL);
/* */
list_add(&ch->node, &chan_list);
/* */
list_add_tail(&ch->node, &chan_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_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
4.以上は分かりやすいです。チェーンの使い方について説明します。struct s3c_pl330_chan *ch;
list_for_each_entry(ch, &chan_list, node)
if (ch->id == id)
return ch;
このコードの役割は、chタイプを親タイプとし、nodeをその子メンバーとして、chan_リストはチェーンのヘッドポインタをnextに通し、chタイプのポインタを返します。次に、IDによってマッチングするかどうかは、検索が必要なノードである。
リスト.for_each_entry(pos,head,member)はfor(初期条件;条件判断;ブロック終了文)です。ループ
初期条件語句:list_によるentryはチェーンチャンネルを獲得します。リスト後の最初のノードは、親タイプs 3 c_に戻る。pl 330_チャンネル
条件判定文:置換後は&ch.node!=(&chan_list);今ならs 3 c_pl 330_chanの父のタイプのノードのnodeチェーンの針は&chan_;ではありません。リストヘッドポインタは、チェーンがまだ全て通っていないということです。
ブロック終了文:posは現在のノードの次のノードを指します。
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
もう一度リストを説明しますイベント実行:#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
主にcontainer_です。ofの定義では、このマクロの役割は、既知のメンバーメンバーmemberのtype中のオフセットアドレスとメンバーのメモリ内のアドレスを取得し、親タイプtypeのメモリアドレスを取得することです。このような構造体があり、ptrはmemberタイプのポインタであり、memberのメモリ中のアドレスを指すことが理解できる。
struct type {
member0;
member1;
member; //ptr member , member
member3;
};