Github: idr_get_free
Email: BuddyZhang1 buddy.zhang@aliyun.com
目录
源码分析
idr_get_free() 函数用于从 radix-tree 中获得一个可用的 slot。由于函数较长,分段解析。
参数 root 指向 radix-tree 的根;参数 iter 存于存储找到的节点 slot;参数 gfp
用于分配内存时使用的标志;参数 max 表示分配的最大 id。函数定义了局部变量,其中
slot 指向 root->rnode。start 变量表示起始的索引,其指向 iter->next_index。
函数首先调用 radix_tree_load_root() 函数获得当前 radix-tree 的根节点,以及支持
的最大索引值,以及使用整形变量的 shift。函数首先判断当前 radix-tree 的 tag 是否
标记为 IDR_FREE,如果没有标记 IDR_FREE,那么表示目前的 radix-tree 没有空间,那么
需要从 radix-tree 支持的最大索引之后分配,因此将 start 设置为 start 和 maxindex + 1
之间最大的一个。如果此时 start 大于参数 max,那么表示目前 radix-tree 不符合
分配条件,直接返回错误码 ENOSPC;如果上面的条件都满足,那么函数继续执行,并判断
start 是否大于 maxindex,如果大于,那么表示目前 radix-tree 不够存储索引,需要
增加树的高度;如果不大于,那么表示目前的 radix-tree 可以存储需求的索引。当需要增加
树的高度时,函数调用 radix_tree_extend() 函数增加树的高度。并将 shift 指向新的
偏移。最后将 child 重新指向了 radix-tree 的根节点。
函数根据 shift 的值进行循环,每次 shift 遍历的时候,首先判断对应的 slot 是否存在,
如果不存在,那么调用 radix_tree_node_alloc() 函数去分配需求的节点。并将分配到的
内存初始化,设置 tag 为 IDR_TREE。接着将 slot 指向新分配的节点;如果对于的 slot
存在,那么就判断此时是否已经到达 radix-tree 的叶子,如果到达就结束循环;如果没有
到达,则继续遍历。
当每次遍历的时候,还未找打叶子节点或刚分配一个新的 slot 节点的时候,函数调用
entry_to_node() 函数获得入口对应的节点地址,然后调用 radix_tree_descend()
函数进入下一层节点。在进入下一层之后,函数调用 tag_get() 函数判断当前 offset
对应的节点是否可用,如果不可用,那么函数就调用 radix_tree_find_next_bit()
去查找下一个可用的节点,调用 next_index() 指向下一个可以的节点。如果此时
start 的值大于 max,那么直接返回 ENOSPC,表示此时 radix-tree 不支持这么大
的索引;如果 start 可以支持,那么继续查找可以节点。如果此时 offset 的值与
RADIX_TREE_MAP_SIZE 的值相等,代表一个节点的所有 slot 已经被使用了,那么
将 offset 指向 node->offset 的兄弟节点,此时将 node 指向其父节点,如果父节点
不存在,那么跳转到 grow,从新申请兄弟节点的路径上的节点,并将 shift 指向
此时 node 的 shift,并不断循环。最后在兄弟节点中找到一个可用的 slot,那么
将 child 指向这个 slot。
在上面的循环结束之后,找到一个可用的 slot。此时将 start 的值赋值给 iter->index。
如果此时 node 存在,那么将 iter->next_index 设置为 max 和 start 之间最小的那一个;
如果 node 不存在,那么 iter->next_index 就设置为 1.将 iter->node 指向 node。
接着调用 __set_iter_shift() 函数设置 iter 的 shift 成员,最后调用 set_iter_tags()
设置,返回 slot。
实践
驱动源码
驱动安装
驱动的安装很简单,首先将驱动放到 drivers/BiscuitOS/ 目录下,命名为 atomic.c,
然后修改 Kconfig 文件,添加内容参考如下:
接着修改 Makefile,请参考如下修改:
驱动配置
驱动配置请参考下面文章中关于驱动配置一节。在配置中,勾选如下选项,如下:
具体过程请参考:
Linux 5.0 开发环境搭建 – 驱动配置
驱动编译
驱动编译也请参考下面文章关于驱动编译一节:
Linux 5.0 开发环境搭建 – 驱动编译
驱动运行
驱动的运行,请参考下面文章中关于驱动运行一节:
Linux 5.0 开发环境搭建 – 驱动运行
启动内核,并打印如下信息:
驱动分析
附录
BiscuitOS Home
BiscuitOS Driver
BiscuitOS Kernel Build
Linux Kernel
Bootlin: Elixir Cross Referencer
搭建高效的 Linux 开发环境
赞赏一下吧 🙂