list_splice(リスト結合)(2)
list_splice(リスト結合)では、明示的なヘッダーを有するリストの結合でした。list_splice()で結合されるリストの引数は、リストから削除されます。下記のような有効なノードとするヘッダーのリストの結合はどうしたらいいでしょうか?
サンプルです。ポイントはinit_module()でlist_add_tail()で、ダミーとしてのスタック変数上のjoinをlist 2のnode_head2の末尾に追加しています。追加する場所は、結合する任意のポイントに追加すればいいわけです。list_splice()の引数として、このjoinでもって結合する事で実現しています。
1 | 5 4 2 | 8 6 3 | 7この場合、結合するリストの結合位置にダミーのノード(head list)を追加して、それを引数にしてlist_splice()をコールする事で実現します。
サンプルです。ポイントはinit_module()でlist_add_tail()で、ダミーとしてのスタック変数上のjoinをlist 2のnode_head2の末尾に追加しています。追加する場所は、結合する任意のポイントに追加すればいいわけです。list_splice()の引数として、このjoinでもって結合する事で実現しています。
#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> struct my_object { struct list_head list; int sec; }; void disp_obj(int sel); void init_node_head1(void); void init_node_head2(void); static struct my_object *node_head1; static struct my_object *node_head2; int init_module(void) { struct my_object *myobj1, *myobj2; struct list_head join; int i; init_node_head1(); for (i = 2; i <= 10; ++i) { myobj1 = (struct my_object *)kmalloc(sizeof(struct my_object), GFP_KERNEL); myobj1->sec = i; list_add_tail(&myobj1->list, &node_head1->list); } init_node_head2(); for (i = 12; i <= 20; ++i) { myobj2 = (struct my_object *)kmalloc(sizeof(struct my_object), GFP_KERNEL); myobj2->sec = i; list_add_tail(&myobj2->list, &node_head2->list); } disp_obj(1); list_add_tail(&join, &node_head2->list); list_splice(&join, node_head1->list.prev); 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 1\n"); sprintf(tmp, "%2d->", node_head1->sec); strcat(entry, tmp); list_for_each(p, &node_head1->list) { myobj = list_entry(p, struct my_object, list); sprintf(tmp, "%2d->", myobj->sec); strcat(entry, tmp); } strcat(entry, "\n"); printk(entry); if (sel == 1) { entry[0] = 0; printk("list 2\n"); sprintf(tmp, "%2d->", node_head2->sec); strcat(entry, tmp); list_for_each(p, &node_head2->list) { myobj = list_entry(p, struct my_object, list); sprintf(tmp, "%d->", myobj->sec); strcat(entry, tmp); } strcat(entry, "\n"); printk(entry); } } void init_node_head1(void) { node_head1 = (struct my_object *)kmalloc(sizeof(struct my_object), GFP_KERNEL); INIT_LIST_HEAD(&node_head1->list); node_head1->sec = 1; } void init_node_head2(void) { node_head2 = (struct my_object *)kmalloc(sizeof(struct my_object), GFP_KERNEL); INIT_LIST_HEAD(&node_head2->list); node_head2->sec = 11; } void cleanup_module(void) { struct my_object *myobj; while(!list_empty(&node_head1->list)) { myobj = list_entry(node_head1->list.next, struct my_object, list); list_del(&myobj->list); kfree(myobj); } kfree(node_head1); }結果
[root@localhost lkm]# dmesg : : [63358.105255] list 1 [63358.105255] 1-> 2-> 3-> 4-> 5-> 6-> 7-> 8-> 9->10-> [63358.105255] list 2 [63358.105721] 11->12->13->14->15->16->17->18->19->20-> [63358.105728] list 1 [63358.105748] 1-> 2-> 3-> 4-> 5-> 6-> 7-> 8-> 9->10->11->12->13->14->15->16->17->18->19->20->