無料Wikiサービス | デモページ
検索

アクセス数
最近のコメント
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
はじめ - ノース
はじめ - ノース
はじめ - 楽打連動ユーザー
はじめ - 楽打連動ユーザー
Adsense
広告情報が設定されていません。

list_splice(リスト結合)


list_splice()は、2つのlist_headリストを結合します。自明な事ですが、結合するリストは何らかのノードがある必要があります。
static inline void list_splice(struct list_head *list, struct list_head *head)
{
       if (!list_empty(list))
               __list_splice(list, head);
}

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;
}
頭の体操みたいな処理ですが、これは下記の様な処理となります。
  H2   |   H1
6    4 | 3    1
  5    |    2

  結合前       結合後
 4.prev=H2 ->  4.prev=H1
H1.next=1  -> H1.next=4

 6.next=H2 ->  6.next=1
 1.prev=H1 ->  1.prev=6
結合されたH1リストは、H1->4->5->6->1->2->3->H1となります。なお、H2からリストだと、H2->4->5->6->1->2->3->H1->4 とH2に戻ってきませんので、もはやヘッドとしての意味を持っていません。

サンプルです。
[root@localhost lkm]# cat hogehoge.c
#include <linux/kernel.h>
#include <linux/syscalls.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/unistd.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/slab.h>

static LIST_HEAD(head1);
static LIST_HEAD(head2);

struct my_object {
  struct list_head list;
  int sec;
};

void    disp_obj(int sel);

int init_module(void)
{
       struct my_object *myobj1, *myobj2;
       struct list_head;
       int i;

       for (i = 1; i <= 5; ++i) {
               myobj1 = (struct my_object *)kmalloc(sizeof(struct my_object), GFP_KERNEL);
               myobj1->sec = i;
               list_add_tail(&myobj1->list, &head1);
       }

       for (i = 6; i <= 10; ++i) {
               myobj2 = (struct my_object *)kmalloc(sizeof(struct my_object), GFP_KERNEL);
               myobj2->sec = i;
               list_add_tail(&myobj2->list, &head2);
       }

       disp_obj(1);
       list_splice(&head2, &head1);
       disp_obj(0);

       return 0;
}

void    disp_obj(int sel)
{
       struct list_head *p;
       struct my_object *myobj;
       char    entry[256], tmp[6];

       entry[0] = 0;
       printk("list head 1\n");
       list_for_each(p, &head1) {
               myobj = list_entry(p, struct my_object, list);
               sprintf(tmp, "%d->", myobj->sec);
               strcat(entry, tmp);
       }
       strcat(entry, "\n");
       printk(entry);

       if (sel == 1) {
               entry[0] = 0;
               printk("list head 2\n");
               list_for_each(p, &head2) {
                       myobj = list_entry(p, struct my_object, list);
                       sprintf(tmp, "%d->", myobj->sec);
                       strcat(entry, tmp);
               }
               strcat(entry, "\n");
               printk(entry);
       }
}

void cleanup_module(void)
{
 struct my_object *myobj;

   while(!list_empty(&head1)) {
      myobj = list_entry(head1.next, struct my_object, list);
      list_del(&myobj->list);
      kfree(myobj);
   }
}

[root@localhost lkm]# insmod hogehoge.ko
[root@localhost lkm]# dmesg
  :
  :
[  340.101170] list head 1
[  340.101170] 1->2->3->4->5->
[  340.101170] list head 2
[  340.101170] 6->7->8->9->10->
[  340.101170] list head 1
[  340.101170] 6->7->8->9->10->1->2->3->4->5->


最終更新 2013/05/30 17:20:21 - north
(2013/05/30 17:20:21 作成)