Linux Kernel-Zswap 2.上下层依赖

yyi
yyi
2023-08-01 / 0 评论 / 161 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2023年08月08日,已超过345天没有更新,若内容或图片失效,请留言反馈。

上下层依赖

重要数据结构

zswap_pool

struct zswap_pool { // 挂 zswap 所用的内存池
    struct zpool *zpool; 
    struct crypto_acomp_ctx __percpu *acomp_ctx;
    struct kref kref;
    struct list_head list;
    struct work_struct release_work;
    struct work_struct shrink_work;
    struct hlist_node node;
    char tfm_name[CRYPTO_MAX_ALG_NAME];
};
  1. struct zpool *zpool:指向 zpool 对象的指针,用于表示当前 zswap 池所对应的 zpool。可能需要基于 uma 进一步封装实现。
  2. struct crypto_acomp_ctx __percpu *acomp_ctx:指向压缩算法。

    struct crypto_acomp_ctx {
        struct crypto_acomp *acomp;
        struct acomp_req *req;
        struct crypto_wait wait;
        u8 *dstmem;
        struct mutex *mutex;
    };
  3. struct kref kref:用于实现引用计数技术的 kref 对象,用于管理 zswap 池对象的生命周期。当一个 zswap 池对象被创建时,其引用计数值初始化为 1;当该对象被使用时,其引用计数值增加;当不再需要该对象时,其引用计数值减少,当引用计数值降为 0 时,该对象将会被释放。 FreeBSD 支持 refcount 特性,我们认为是可以迁移的。
  4. struct list_head list:用于实现链表的 list_head 结构体,用于将当前 zswap 池对象添加到 zswap 的池列表中。普通链表头,可以迁移。
  5. struct work_struct release_work:表示一个工作队列对象,用于异步释放当前 zswap 池对象。在该工作队列中执行的操作会在一个单独的内核线程上运行,从而避免阻塞当前进程。
  6. struct work_struct shrink_work:表示一个工作队列对象,用于在 zswap 池中的页面数量超过一定阈值时触发缩减操作。该工作队列也是异步执行的,在单独的内核线程上运行。

    FreeBSD 的 taskqueue 和 workqueue类似,都支持异步调用,可以迁移。

  7. struct hlist_node node:表示一个哈希表节点,用于将当前 zswap 池对象添加到 zswap 的池哈希表中。
  8. char tfm_name[CRYPTO_MAX_ALG_NAME]:表示保存压缩算法名称的字符数组,用于指定 zswap 池所使用的压缩算法名称。在进行前端交换时,内核将会根据该名称来查找相应的压缩算法,并使用其进行数据压缩处理。

zswap_entry

struct zswap_entry {
    struct rb_node rbnode;
    pgoff_t offset;
    int refcount;
    unsigned int length;
    struct zswap_pool *pool;
    union {
        unsigned long handle;
        unsigned long value;
    };
    struct obj_cgroup *objcg;
};

struct zswap_entry 表示单个被压缩页面元数据。

  1. struct rb_node rbnode:红黑树节点
  2. pgoff_t offset:表示该页面在交换分区中的偏移量,也是红黑树的 idx
  3. int refcount:表示对该页面的引用计数,用于保证在页面同时被加载、失效和写回等操作时不会出现条件竞争,从而避免页面被过早地释放。
  4. unsigned int length:被压缩后页面长度。
  5. struct zswap_pool *pool:标识该页面所属的 zswap 池。
  6. union

    a) unsigned long handle:压缩页面数据句柄。这个是 zpool 用的。

    b) unsigned long value:内容相同的空白页面填充值。

  7. struct obj_cgroup *objcg:指向 obj_cgroup 结构体的指针,用于标识该页面所属的 cgroup(如果按 cgroup 进行回收)。

zswap_tree

struct zswap_tree {
    struct rb_root rbroot;
    spinlock_t lock;
};

这个结构体代表了一个 zswap 树的元信息,分别有一个红黑树的根和一个自旋锁。

一点对 zswap_pool\entry\tree的理解

enrty 是页面单元,包括该页在内存中的位置大小等信息,pool是实际存储 entry 元信息对应页面压缩后数据的内存池,tree 维护了一颗平衡树,用于找到对应 type+offset 的元信息entry。

zswap_header

一个 ulong

其他全局变量

一般为 config 或者全局状态量,易于迁移。

page

篇幅过长,Linux 的基础页面数据结构

重要依赖模块

内存管理池 zpool

  • zpool 是 linux 的一类内存管理 API,是 zswap 所依赖的最底层的数据结构。zswap_pool 通过 zpool 的各类内存管理工具,包括申请、映射、收缩等关键操作

异步压缩 acompress

  • acompress 是 linux crypto 下的模块,它提供了类似队列式的异步的压缩和解压缩能力
  • 同时,crypto 模块还提供了统一的同步方式

swap 框架 frontswap

  • 提供了一种 swap 接口层,通过实现 frontswap 提供的函数指针,可以自定义swap 的实现方式
  • 有了 frontswap,我们只需要关注 swap 后端的设计,并向对应的初始化、存入、取出等接口实现逻辑、提供功能即可。frontswap 是zswap 最重要的依赖之一

平衡树 rbtree

  • 维护 zswap_tree 的核心数据结构,保证插入和索引 offset 对应的页面的时候的复杂度。

工作队列work_queue

  • 提供一个异步工作的机制,包括对 pool 的 shrink 和 release

引用计数 kref

  • 需要一个引用计数器,主要是保证在 pool 和 entry被释放时的内存安全性

锁与信号量

  • 主要需要关于自旋锁和互斥锁的 aquire/release的实现,避免线程竞争带来的各类安全和数据访问问题。

原子操作

一般依赖模块

认为一般依赖模块仅是为了某些特性准备,不影响 swap 的关键流程

scatterlist

为了支持 acomp 的参数而依赖,属于间接依赖

多 CPU 系列的宏和回调注册

有的为了支持 CPU 热插拔事件、有的为了实现 acomp 在多 CPU 上的真并行

kmem_cache

entry_cache 的底层申请与管理依赖于 kmem_cache,属于性能优化。

1

评论 (0)

取消