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->