Github: list_splice_init
Email: BuddyZhang1 buddy.zhang@aliyun.com
目录
源码分析
/**
* 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 , head -> next );
INIT_LIST_HEAD ( list );
}
}
list_splice_init() 函数用于将 list 链表添加到 head 链表的头部,并重新初始化
list 链表。函数首先检查 list 链表是否为空,如果为空直接返回;如果不为空,那么
调用 __list_splice() 函数将 list 链表的节点添加到 head 链表的头部。最后
调用 INIT_LIST_HEAD() 函数初始化 list。
list_empty
list_empty 源码
__list_splice
[list_splice 源码](/blog/LIST _list_splice/)
INIT_LIST_HEAD
INIT_LIST_HEAD 源码
实践
驱动源码
/*
* bindirect-list
*
* (C) 20179.04.25 <buddy.zhang@aliyun.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/*
* bidirect-list
*
* +-----------+<--o +-----------+<--o +-----------+<--o +-----------+
* | | | | | | | | | | |
* | prev | o----| prev | o----| prev | o----| prev |
* | list_head | | list_head | | list_head | | list_head |
* | next |---o | next |---o | next |---o | next |
* | | | | | | | | | | |
* +-----------+ o--->+-----------+ o--->+-----------+ o--->+-----------+
*
*/
#include <linux/kernel.h>
#include <linux/init.h>
/* header of list */
#include <linux/list.h>
/* private structure */
struct node {
const char * name ;
struct list_head list ;
};
/* Initialize a group node structure */
static struct node node0 = { . name = "BiscuitOS_node0" , };
static struct node node1 = { . name = "BiscuitOS_node1" , };
static struct node node2 = { . name = "BiscuitOS_node2" , };
static struct node node3 = { . name = "BiscuitOS_node3" , };
static struct node node4 = { . name = "BiscuitOS_node4" , };
static struct node node5 = { . name = "BiscuitOS_node5" , };
static struct node node6 = { . name = "BiscuitOS_node6" , };
/* Declaration and implement a bindirect-list */
LIST_HEAD ( BiscuitOS_list );
LIST_HEAD ( BiscuitOS_blist );
static __init int bindirect_demo_init ( void )
{
struct node * np ;
/* add a new entry on special entry */
list_add_tail ( & node0 . list , & BiscuitOS_list );
list_add_tail ( & node1 . list , & BiscuitOS_list );
list_add_tail ( & node2 . list , & BiscuitOS_list );
list_add_tail ( & node3 . list , & BiscuitOS_list );
list_add_tail ( & node4 . list , & BiscuitOS_blist );
list_add_tail ( & node5 . list , & BiscuitOS_blist );
list_add_tail ( & node6 . list , & BiscuitOS_blist );
printk ( "BiscuitOS_list: \n " );
/* Traverser all node on bindirect-list */
list_for_each_entry ( np , & BiscuitOS_list , list )
printk ( "%s \n " , np -> name );
printk ( "BiscuitOS_blist: \n " );
/* Traverser all node on bindirect-list */
list_for_each_entry ( np , & BiscuitOS_blist , list )
printk ( "%s \n " , np -> name );
/* join two list and reinitialise the emptied list. */
list_splice_init ( & BiscuitOS_blist , & BiscuitOS_list );
printk ( "Splice BiscuitOS_list: \n " );
/* Traverser all node on bindirect-list */
list_for_each_entry ( np , & BiscuitOS_list , list )
printk ( "%s \n " , np -> name );
return 0 ;
}
device_initcall ( bindirect_demo_init );
驱动安装
驱动的安装很简单,首先将驱动放到 drivers/BiscuitOS/ 目录下,命名为 list.c,
然后修改 Kconfig 文件,添加内容参考如下:
diff --git a/drivers/BiscuitOS/Kconfig b/drivers/BiscuitOS/Kconfig
index 4edc5a5..1a9abee 100644
--- a/drivers/BiscuitOS/Kconfig
+++ b/drivers/BiscuitOS/Kconfig
@@ -6 ,4 +6,14 @@ if BISCUITOS_DRV
config BISCUITOS_MISC
bool "BiscuitOS misc driver"
+config BISCUITOS_LIST
+ bool "Bindirect-list"
+
+if BISCUITOS_LIST
+
+config DEBUG_BISCUITOS_LIST
+ bool "list_splice_init"
+
+endif # BISCUITOS_LIST
+
endif # BISCUITOS_DRV
接着修改 Makefile,请参考如下修改:
diff --git a/drivers/BiscuitOS/Makefile b/drivers/BiscuitOS/Makefile
index 82004c9..9909149 100644
--- a/drivers/BiscuitOS/Makefile
+++ b/drivers/BiscuitOS/Makefile
@@ -1 +1,2 @@
obj-$( CONFIG_BISCUITOS_MISC) += BiscuitOS_drv.o
+obj-$( CONFIG_BISCUITOS_LIST) += list.o
--
驱动配置
驱动配置请参考下面文章中关于驱动配置一节。在配置中,勾选如下选项,如下:
Device Driver--->
[ * ] BiscuitOS Driver--->
[ * ] Bindirect-list
[ * ] list_splice_init()
具体过程请参考:
Linux 5.0 开发环境搭建 – 驱动配置
驱动编译
驱动编译也请参考下面文章关于驱动编译一节:
Linux 5.0 开发环境搭建 – 驱动编译
驱动运行
驱动的运行,请参考下面文章中关于驱动运行一节:
Linux 5.0 开发环境搭建 – 驱动运行
启动内核,并打印如下信息:
usbcore: registered new interface driver usbhid
usbhid: USB HID core driver
BiscuitOS_list :
BiscuitOS_node0
BiscuitOS_node1
BiscuitOS_node2
BiscuitOS_node3
BiscuitOS_blist :
BiscuitOS_node4
BiscuitOS_node5
BiscuitOS_node6
Splice BiscuitOS_list :
BiscuitOS_node4
BiscuitOS_node5
BiscuitOS_node6
BiscuitOS_node0
BiscuitOS_node1
BiscuitOS_node2
BiscuitOS_node3
aaci - pl041 10004000 . aaci : ARM AC ' 97 Interface PL041 rev0 at 0x10004000 , irq 24
aaci - pl041 10004000 . aaci : FIFO 512 entries
驱动分析
list_splice_init() 函数适用于将一个链表的所有节点添加到另外一个链表的头部,
并初始化空链表。
附录
BiscuitOS Home
BiscuitOS Driver
BiscuitOS Kernel Build
Linux Kernel
Bootlin: Elixir Cross Referencer
搭建高效的 Linux 开发环境
赞赏一下吧 🙂