当前位置: 首页 > news >正文

Linux中匿名设备和安全相关以及VFS的slab缓存对象创建

初始化未命名设备号的 ID 分配unnamed_dev_init

void __init unnamed_dev_init(void)
{idr_init(&unnamed_dev_idr);
}
static struct idr unnamed_dev_idr;
void idr_init(struct idr *idp)
{init_id_cache();memset(idp, 0, sizeof(struct idr));spin_lock_init(&idp->lock);
}static  int init_id_cache(void)
{if (!idr_layer_cache)idr_layer_cache = kmem_cache_create("idr_layer_cache",sizeof(struct idr_layer), 0, 0, idr_cache_ctor, NULL);return 0;
}

整体功能概述

这些函数用于初始化未命名设备号的 ID 分配系统,基于 IDR(ID Radix Tree)机制来高效管理和分配设备号。

代码详细解释

第一部分:未命名设备初始化入口

void __init unnamed_dev_init(void)
{idr_init(&unnamed_dev_idr);
}
  • __init:这个宏表示函数只在系统初始化期间使用,初始化完成后内存会被释放
  • 函数名unnamed_dev_init - 未命名设备初始化
  • 单行实现idr_init(&unnamed_dev_idr);
    • 调用 IDR 初始化函数来初始化全局的 unnamed_dev_idr 结构
    • unnamed_dev_idr 是静态全局变量,用于管理未命名设备的 ID 分配

第二部分:全局变量声明

static struct idr unnamed_dev_idr;
  • static:限制变量只在当前文件内可见
  • struct idr:IDR 数据结构,用于实现基数树(Radix Tree)的 ID 分配
  • 这个全局变量将用于管理所有未命名设备的设备号分配

第三部分:IDR 结构初始化

void idr_init(struct idr *idp)
{init_id_cache();memset(idp, 0, sizeof(struct idr));spin_lock_init(&idp->lock);
}
  • 参数struct idr *idp - 指向要初始化的 IDR 结构的指针
  1. init_id_cache();

    • 初始化 IDR 层缓存(slab 缓存)
    • 确保有可用的内存来分配 IDR 树的节点
  2. memset(idp, 0, sizeof(struct idr));

    • 将整个 idr 结构体清零
    • 确保所有字段都处于已知的初始状态
    • 防止未初始化内存导致的问题
  3. spin_lock_init(&idp->lock);

    • 初始化自旋锁,用于保护对 IDR 结构的并发访问
    • 确保多核环境下的线程安全

第四部分:IDR 层缓存初始化

static int init_id_cache(void)
{if (!idr_layer_cache)idr_layer_cache = kmem_cache_create("idr_layer_cache",sizeof(struct idr_layer), 0, 0, idr_cache_ctor, NULL);return 0;
}
  • static int:静态函数,返回整型(总是返回 0)

  • 条件检查if (!idr_layer_cache)

    • 检查全局变量 idr_layer_cache 是否已经初始化
    • 如果为 NULL(未初始化),则创建 slab 缓存
    • 这确保了缓存只被创建一次
  • slab 缓存创建kmem_cache_create(...)

    • 名称"idr_layer_cache" - 标识这个缓存的名称
    • 对象大小sizeof(struct idr_layer) - IDR 树节点的大小
    • 对齐0 - 使用默认对齐
    • 标志0 - 无特殊标志
    • 构造函数idr_cache_ctor - 对象创建时的初始化函数
    • 析构函数NULL - 无特殊析构函数
  • 返回值return 0; - 总是成功返回

未命名设备的应用场景

  • 临时设备:不需要持久设备名的设备
  • 内部设备:内核内部使用的虚拟设备
  • 动态设备:生命周期短暂的设备对象
  • 匿名设备:不需要在 /dev 下创建节点的设备

初始化 Linux 安全框架security_init

int __init security_init(void)
{printk(KERN_INFO "Security Framework v" SECURITY_FRAMEWORK_VERSION" initialized\n");if (verify(&dummy_security_ops)) {printk(KERN_ERR "%s could not verify ""dummy_security_ops structure.\n", __FUNCTION__);return -EIO;}security_ops = &dummy_security_ops;do_security_initcalls();return 0;
}
static void __init do_security_initcalls(void)
{initcall_t *call;call = &__security_initcall_start;while (call < &__security_initcall_end) {(*call) ();call++;}
}

整体功能概述

这些函数用于初始化 Linux 安全框架(LSM - Linux Security Modules),建立系统安全子系统的基础设施

代码详细解释

第一部分:安全框架主初始化函数

int __init security_init(void)
{printk(KERN_INFO "Security Framework v" SECURITY_FRAMEWORK_VERSION" initialized\n");
  • int __init:返回整型的初始化函数,__init 表示只在系统启动时运行
  • 版本信息打印
    • printk(KERN_INFO ...):输出信息级内核日志
    • SECURITY_FRAMEWORK_VERSION:安全框架版本号宏
    • 通知用户安全框架已初始化完成

第二部分:虚拟安全操作验证

        if (verify(&dummy_security_ops)) {printk(KERN_ERR "%s could not verify ""dummy_security_ops structure.\n", __FUNCTION__);return -EIO;}
  • 验证检查if (verify(&dummy_security_ops))

    • verify() 函数检查 dummy_security_ops 结构的完整性和有效性
    • dummy_security_ops 是虚拟的安全操作结构,提供空操作实现
  • 错误处理

    • 如果验证失败,输出错误日志:KERN_ERR 表示错误级别
    • __FUNCTION__ 宏展开为当前函数名 “security_init
    • 返回 -EIO(I/O 错误)表示初始化失败

第三部分:安全操作指针设置和初始化调用

        security_ops = &dummy_security_ops;do_security_initcalls();return 0;
}
  • 设置安全操作security_ops = &dummy_security_ops;

    • security_ops 是全局安全操作指针
    • 初始设置为虚拟操作,后续可能被具体的安全模块替换
  • 执行初始化调用do_security_initcalls();

    • 调用所有注册的安全模块初始化函数
  • 成功返回return 0; - 表示初始化成功完成

第四部分:安全初始化调用执行器

static void __init do_security_initcalls(void)
{initcall_t *call;call = &__security_initcall_start;while (call < &__security_initcall_end) {(*call) ();call++;}
}
  • 函数签名static void __init - 静态初始化函数,无返回值

  • 变量声明

    • initcall_t *call:初始化调用函数指针
    • initcall_t 通常是 int (*)(void) 类型的函数指针
  • 循环起点call = &__security_initcall_start;

    • __security_initcall_start 是链接器定义的符号
    • 指向安全初始化调用段的开始地址
  • 循环执行while (call < &__security_initcall_end)

    • __security_initcall_end 指向段的结束地址
    • 循环遍历段中的所有初始化函数
  • 函数调用(*call) ();

    • 解引用函数指针并调用(无参数)
    • 执行具体的安全模块初始化
  • 指针递增call++;

    • 移动到下一个函数指针
    • 继续循环直到处理完所有初始化函数

链接器段的魔法

内存布局示意

.security.initcall 段
┌─────────────────────────┐
│ __security_initcall_start  │ ← 段开始
├─────────────────────────┤
│ security_module1_init   │ ← 第一个初始化函数指针
├─────────────────────────┤
│ security_module2_init   │ ← 第二个初始化函数指针
├─────────────────────────┤
│ ...                    │
├─────────────────────────┤
│ security_moduleN_init   │ ← 第N个初始化函数指针
├─────────────────────────┤
│ __security_initcall_end   │ ← 段结束
└─────────────────────────┘

初始化VFS的各种缓存和数据结构vfs_caches_init

void __init vfs_caches_init(unsigned long mempages)
{unsigned long reserve;/* Base hash sizes on available memory, with a reserve equal to150% of current kernel size */reserve = min((mempages - nr_free_pages()) * 3/2, mempages - 1);mempages -= reserve;names_cachep = kmem_cache_create("names_cache", PATH_MAX, 0,SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0,SLAB_HWCACHE_ALIGN|SLAB_PANIC, filp_ctor, filp_dtor);dcache_init(mempages);inode_init(mempages);files_init(mempages);mnt_init(mempages);bdev_cache_init();chrdev_init();
}

函数功能概述

vfs_caches_init 函数用于初始化虚拟文件系统(VFS)的各种缓存和数据结构,为文件系统操作提供基础设施。

代码详细解释

第一部分:函数签名和变量声明

void __init vfs_caches_init(unsigned long mempages)
{unsigned long reserve;
  • void __init:无返回值的初始化函数,__init 表示只在系统启动时运行
  • 参数unsigned long mempages - 系统总内存页数
  • 局部变量unsigned long reserve - 用于计算内存保留量

第二部分:内存保留计算

        /* Base hash sizes on available memory, with a reserve equal to150% of current kernel size */reserve = min((mempages - nr_free_pages()) * 3/2, mempages - 1);mempages -= reserve;
  • 基于可用内存计算哈希表大小,保留当前内核大小的150%

  • 内存使用计算mempages - nr_free_pages()

    • nr_free_pages() 返回系统当前空闲页数
    • mempages - nr_free_pages() 计算已使用的内存页数(主要是内核占用)
  • 保留量计算(mempages - nr_free_pages()) * 3/2

    • 已用内存的1.5倍(150%)
    • 为内核运行保留足够的内存空间
  • 安全限制min(..., mempages - 1)

    • 确保保留量不超过总内存减1页
  • 调整可用内存mempages -= reserve

    • 从总内存中减去保留量
    • 后续初始化基于调整后的内存量进行

第三部分:路径名缓存创建

        names_cachep = kmem_cache_create("names_cache", PATH_MAX, 0,SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
  • 缓存名称"names_cache" - 路径名缓存
  • 对象大小PATH_MAX - 最大路径长度(通常是4096字节)
  • 对齐0 - 默认对齐
  • 标志SLAB_HWCACHE_ALIGN|SLAB_PANIC
    • 缓存行对齐优化性能
    • 创建失败时系统崩溃
  • 构造函数/析构函数NULL, NULL - 不需要特殊处理

第四部分:文件结构缓存创建

        filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0,SLAB_HWCACHE_ALIGN|SLAB_PANIC, filp_ctor, filp_dtor);
  • 缓存名称"filp" - file结构缓存
  • 对象大小sizeof(struct file) - file结构体大小
  • 标志:同样的性能和安全标志
  • 构造函数filp_ctor - file对象创建时初始化
  • 析构函数filp_dtor - file对象销毁时清理

第五部分:各子系统初始化

        dcache_init(mempages);inode_init(mempages);files_init(mempages);mnt_init(mempages);bdev_cache_init();chrdev_init();
}
  1. dcache_init(mempages) - 目录项缓存初始化

    • 管理目录项(dentry)缓存,加速路径查找
    • 基于内存大小调整哈希表尺寸
  2. inode_init(mempages) - inode缓存初始化

    • 管理inode缓存,文件元数据
    • 初始化inode哈希表和slab缓存
  3. files_init(mempages) - 文件描述符表初始化

    • 初始化文件描述符管理
    • 设置最大文件打开数限制
  4. mnt_init(mempages) - 文件系统挂载点初始化

    • 管理文件系统挂载信息
    • 初始化挂载点哈希表
  5. bdev_cache_init() - 块设备缓存初始化

    • 管理块设备特殊文件的缓存
    • 无内存参数,使用固定大小
  6. chrdev_init() - 字符设备初始化

    • 管理字符设备注册和查找
    • 无内存参数,初始化核心数据结构

创建新的 file 对象时进行初始化filp_ctor

void filp_ctor(void * objp, struct kmem_cache_s *cachep, unsigned long cflags)
{if ((cflags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==SLAB_CTOR_CONSTRUCTOR) {unsigned long flags;spin_lock_irqsave(&filp_count_lock, flags);files_stat.nr_files++;spin_unlock_irqrestore(&filp_count_lock, flags);}
}

函数功能概述

filp_ctor 是文件结构(struct file)的 slab 构造函数,用于在创建新的 file 对象时进行初始化,主要功能是统计全局文件打开数量。

代码详细解释

第一部分:函数签名和参数

void filp_ctor(void * objp, struct kmem_cache_s *cachep, unsigned long cflags)
  • 返回值void - 没有返回值
  • 参数
    • void *objp:指向要构造的 slab 对象的指针(这里是 struct file)
    • struct kmem_cache_s *cachep:指向所属 slab 缓存的指针
    • unsigned long cflags:构造标志位,控制构造行为

第二部分:构造模式检查

        if ((cflags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==SLAB_CTOR_CONSTRUCTOR) {
  • 位掩码操作cflags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)

    • SLAB_CTOR_VERIFY:验证模式标志(0x002)
    • SLAB_CTOR_CONSTRUCTOR:构造函数模式标志(0x001)
    • 按位与操作提取相关标志位
  • 条件判断:检查是否处于纯构造函数模式

    • 只有当 cflags 包含 SLAB_CTOR_CONSTRUCTOR 但不包含 SLAB_CTOR_VERIFY 时才执行
    • 这确保只在真正创建新对象时更新计数,验证模式时跳过

第三部分:自旋锁获取

                unsigned long flags;spin_lock_irqsave(&filp_count_lock, flags);
  • 局部变量unsigned long flags - 用于保存中断状态
  • 中断安全的锁spin_lock_irqsave(&filp_count_lock, flags)
    • filp_count_lock:保护文件计数的自旋锁
    • spin_lock_irqsave:在获取锁的同时禁用本地CPU中断,并保存中断状态
    • 为什么需要:防止中断处理程序与当前代码竞争导致死锁

第四部分:文件计数更新

                files_stat.nr_files++;
  • 全局统计files_stat 是全局文件统计结构
  • 字段nr_files - 当前系统分配的文件结构总数
  • 递增操作files_stat.nr_files++
    • 每次创建新的 struct file 时增加计数
    • 用于监控系统文件打开情况和资源使用

第五部分:自旋锁释放

                spin_unlock_irqrestore(&filp_count_lock, flags);}
  • 锁释放spin_unlock_irqrestore(&filp_count_lock, flags)
    • 释放保护文件计数的自旋锁
    • irqrestore:恢复之前保存的中断状态,重新启用中断
    • 确保并发安全的同时不破坏中断处理

销毁 file 对象时进行清理filp_dtor

void filp_dtor(void * objp, struct kmem_cache_s *cachep, unsigned long dflags)
{unsigned long flags;spin_lock_irqsave(&filp_count_lock, flags);files_stat.nr_files--;spin_unlock_irqrestore(&filp_count_lock, flags);
}

函数功能概述

filp_dtor 是文件结构(struct file)的 slab 析构函数,用于在销毁 file 对象时进行清理,主要功能是递减全局文件打开数量统计

代码详细解释

第一部分:函数签名和参数

void filp_dtor(void * objp, struct kmem_cache_s *cachep, unsigned long dflags)
  • 返回值void - 没有返回值
  • 参数
    • void *objp:指向要销毁的 slab 对象的指针(这里是 struct file)
    • struct kmem_cache_s *cachep:指向所属 slab 缓存的指针
    • unsigned long dflags:析构标志位,控制析构行为

第二部分:局部变量声明

        unsigned long flags;
  • 局部变量unsigned long flags
    • 用于保存当前 CPU 的中断状态
    • 在锁操作中传递中断状态信息
    • 确保锁操作不会破坏系统的中断处理

第三部分:自旋锁获取

        spin_lock_irqsave(&filp_count_lock, flags);
  • 中断安全的锁获取spin_lock_irqsave(&filp_count_lock, flags)
    • &filp_count_lock:指向保护文件计数的自旋锁的指针
    • flags:输出参数,保存当前中断状态
    • 操作语义
      • 禁用当前 CPU 的中断
      • 保存中断使能状态到 flags 变量
      • 获取自旋锁,如果锁被占用则自旋等待

第四部分:文件计数递减

        files_stat.nr_files--;
  • 全局统计更新files_stat.nr_files--
    • files_stat:全局文件统计结构
    • nr_files:当前系统分配的文件结构总数
    • 递减操作:每次销毁 struct file 时减少计数
    • 意义:准确反映系统当前实际使用的文件对象数量

第五部分:自旋锁释放

        spin_unlock_irqrestore(&filp_count_lock, flags);
  • 中断安全的锁释放spin_unlock_irqrestore(&filp_count_lock, flags)
    • &filp_count_lock:要释放的自旋锁
    • flags:之前保存的中断状态
    • 操作语义
      • 释放自旋锁
      • 根据 flags 恢复之前的中断状态(可能重新启用中断)
    • 重要性:确保不破坏系统的中断处理流程
http://www.dtcms.com/a/506868.html

相关文章:

  • B.NET编写不阻塞UI线程的同步延时
  • 论文泛读:DYNAPROMPT: DYNAMIC TEST-TIME PROMPT TUNING(动态测试时调优)
  • 做 58 那样的网站北京公司网页设计
  • PyTorch实战(9)——从零开始实现Transformer
  • 18.SELInux安全性
  • Layui连线题编辑器组件(ConnectQuestion)
  • 电影网站加盟可以做么网奇seo培训官网
  • 【Linux】Socket编程TCP
  • Debian编译Qt5
  • [3-03-01].第07节:搭建服务 - 服务重构cloud-consumer-ocommon
  • Ubuntu Certbot版本查询失败?Snap安装后报错终极修复指南(通用版)
  • Kafka底层解析:可靠性与高性能原理
  • 分布式链路追踪中的上下文传播与一致性维护技术
  • 为已有nextjs项目添加supabase数据库,不再需要冗余后端
  • 网站建设怎样上传程序微信网站搭建多少钱
  • rabbitmq在微服务中配置监听开关
  • 下一代时序数据库标杆:Apache IoTDB架构演进与AIoT时代的数据战略
  • k8s中的控制器
  • Blender入门学习02
  • 动态规划的“数学之魂”:从DP推演到质因数分解——巧解「只有两个键的键盘」
  • Blender入门学习01
  • 网站开发word文档精品简历模板网站
  • WrenAI:企业级AI数据分析平台技术解析
  • 【Processing】椭圆眼珠鼠标跟随
  • 工业显示器在矿用挖掘机中的应用
  • 济南企业网站开发网站建设域名
  • 【深度学习计算机视觉】14:实战Kaggle比赛:狗的品种识别(ImageNet Dogs)
  • 基于k8s的Python的分布式深度学习训练平台搭建简单实践
  • 网站服务器地址在哪里看前端工程师是做网站吗
  • 基于SpringBoot的环保行为记录与社区互动平台(Vue+MySQL)