通过unregister_filesystem()函数学习linux单链表操作
基础介绍 在linux内核中,每一种注册了的文件系统都由一个类型为file_system_type的结构体来代表,该结构体中含有一个类型为file_system_type*的域next,linux正是通过这个next域把所有注册了的文件系统连接起来的,同时,linux还定义了一个指向链表中第一个元素的全局指针file_systems和一个用来用来防止并发访问该链表的读/写自旋锁file_systems_lock。有了这些基础知识,我们开始下面的unregister_filesystem函数的分析。
代码分析 unregister_filesystem源代码如下:
- int unregister_filesystem(struct file_system_type * fs)
- {
- struct file_system_type ** tmp;
- write_lock(&file_systems_lock);
- tmp = &file_systems;
- while (*tmp) {
- if (fs == *tmp) {
- *tmp = fs->next;
- fs->next = NULL;
- write_unlock(&file_systems_lock);
- return 0;
- }
- tmp = &(*tmp)->next;
- }
- write_unlock(&file_systems_lock);
- return -EINVAL;
- }
由该函数名字可知,这个函数的作用是注销一个已注册的文件系统,它的输入参数就是一个指向代表已注册文件系统的结构体的指针。整个函数的操作就是:查找文件系统链表,若找到需要注销的文件系统描述结构就将该结构从链表上摘除。这个算法的优秀之处就在于:在整个操作单链表的过程中它只使用了一个临时指针变量。
代码注释:
3 申请一个类型为struct file_system*的指针tmp,为什么要申请这种类型的指针?
5 获得保护单链表的自旋锁。
6 给3中申请的指针tmp赋值为指向单链表头那个指针变量的地址。
7 判断tmp是否为空。为空则退出。
8 判断tmp中的内容是否等于要注销的文件系统描述结构体首地址。
9—12 若8中判断相等,则将该fs指向的结构体从单链表中摘除,并返回成功。请体会下该代码如何摘除结构体的。
14 将tmp赋值为指向下一个结构体的指针next的地址。
16 释放保护单链表的自旋锁。
17 返回出错
整个算法的关键部分就在于:申请的临时指针变量不是直接指向单链表中的结构体的,而是指向的“指向结构体的指针”,这些“指向结构体的指针”包括:指向单链表第一个元素的指针以及每一个结构体中的next变量。这里我们可以把指向单链表第一个元素的指针file_systems看成一个特殊的next元素来理解。