Google ghOSt 调度介绍

Google ghOSt 调度介绍

整体框架

ghOSt 是在 Linux 内核之上实现的通用调度策略委托。 ghOSt 框架提供了丰富的 API,可以从用户空间接收进程的调度决策,并将其作为事务来执行。 程序员可以使用任何语言或工具来开发策略,并且无需重新启动机器即可升级。 ghOSt 支持一系列调度目标的策略,从 µs 级延迟到吞吐量、能源效率等等,并且调度操作的开销很低。 许多策略只是几百行代码。 总体而言,ghOSt 提供了一个高性能框架,用于将线程调度策略委托给用户空间进程,从而实现策略优化、无中断升级和故障隔离。
ghost整体框架图
当启动 ghost 内核后,通过使用 mount 命令将 ghostfs 文件系统加载到虚拟文件系统下:

sudo mount --source ghost --target /sys/fs/ghost -t ghost

加载成功后,会在 /sys/fs/ghost 目录下存在如下两个重要文件:

OperationPathModeSuppored Operations
Get ABI version*/sys/fs/ghost/version0444read
Create an Enclave/sys/fs/ghost/ctl0660write
  • version 文件用于获取内核的 ghost 的版本号,用于跟用户态的版本号进行比较,如果不一致则不能使用;
  • ctl 文件用于创建 enclave ,可以通过 echo "<command>" > /sys/fs/ghost/ctl命令可以在 ghost 内核中创建一个新的 enclave

command 命令格式:create ${id} ${abi_version} ${extra_opts}

  • ${id} enclave 的 id 号,如果 id 为 1 ,则会在 /sys/fs/ghost 文件夹下产生 enclave_1 的子文件夹;
  • ${abi_version} enclave 中产生的 abi 的版本号;
  • ${extra_opts} 创建 enclave 的额外参数,该参数为可选项;
    • gid=${gid} kernfs 中新 enclave 目录的组 ID
    • ephemeral 是否将新 enclave 的生命周期与调用进程的生命周期关联起来,即当创建它的进程退出时,新的 enclave 也自动销毁。

ghOSt 调度内核实现

调度类

  1. ghOSt 调度在内核中新增加了两个调度类:
  • ghost_agent 调度类;

  • ghost 调度类;

  1. 这两个调度类与其他调度类的关系是:
  • stop 调度类 > ghost_agent 调度类 > dl 调度类 > rt 调度类 > cfs 调度类 > ghost 调度类 > idle 调度类
  1. ghOSt 调度类的任务工作在 ghost 调度类上;
  • ghost 调度类的任务通过 switch_to 方式直接运行在 CPU 上,其与 cfs 调度类没有优先级关系;
  1. ghost 代理工作在 ghost_agent 调度类上——实际上 ghost 代理也是 ghost 调度类,但是会被 ghost_agent 调度类的 pick_next_task() 函数来放到 CPU 上,所以相当于工作在 ghost_agent 调度类上;

文件系统

  • 新建了 ghostfs 文件系统,用于导出 ghost 调度类的相关文件用于与用户态的程序交互。

  • ghOSt 调度的根文件夹为 /sys/fs/ghost

  • 每个 enclave 会在根文件夹下创建一个 enclave_ 的文件夹;所有 enclave 交互的接口导出文件,都在此文件夹下;

  • 用户态的代理就是通过 enclaveghostfs 文件系统中导出的文件与内核进行通讯;

接口模块 enclave

每个 agent 进程都会在内核中产生一个对应的 enclave 接口模块,该模块提供了一系列的 abi 的 API 接口,通过该接口可以将内核的信息传递给用户态的 agent

事务

  1. 内核通过消息事务将内核中的信息传递给用户空间的 agent
  2. 事务提交时机:
  • bool should_resched(int preempt_offset);
  • void scheduler_ipi(void);
  • unsigned long exit_to_user_mode_loop(struct pt_regs *regs, unsigned long ti_work);
  • void exit_to_user_mode_prepare(struct pt_regs *regs);
  • void ghost_commit_all_greedy_txns(void);
  • ghost 负载均衡的时候,static int _balance_ghost(struct rq *rq, struct task_struct *prev, struct rq_flags *rf);
  1. 事务传递过程:
  • 用户态的 agent 将内核中的 enclave 的消息通道和 ghost 任务的状态字通过 mmap 的方式映射到用户空间;
  • 内核生成相应的消息并将其保存到消息通道中;
  • 消息保存成功后唤醒用户态的 agent 任务;
  • 用户态的 agent 处理消息;

汇合点 rendezvous

  1. 数据定义
  • rendezvous 字段的内容: <sign|cpu_num|poison|counter>

  • 其中:

    1 位用于 ,11 位用于 <cpu_num> ,1 位用于 ,51 位用于

  1. 保存汇合点时机
  • 用户态的 agent 通过 ioctl() 操作 enclave 导出的文件在组同步函数中保存汇合点

    static int ghost_sync_group(struct ghost_enclave *e, struct ghost_ioc_commit_txn __user *arg);

  • 内核态在事务提交函数中保存汇合点

    static bool _ghost_commit_txn(int run_cpu, bool sync, int64_t rendezvous, int *commit_state, bool *need_rendezvous);

  1. 保存汇合点的函数
  • static void ghost_reached_rendezvous(int cpu, int64_t target)
  • smp_store_release(&rq->ghost.rendezvous, rendezvous);

ghost_reached_rendezvous() 函数实际是对 smp_store_release() 函数的封装;

用户态与内核态交互流程

代理部分(以 fifo_per_cpu_agent 为例)

AgentBUILD 配置文件中的配置为:

cc_binary(
    name = "fifo_per_cpu_agent",
    srcs = [
        "schedulers/fifo/per_cpu/fifo_agent.cc",
    ],
    copts = compiler_flags,
    deps = [
        ":agent",
        ":fifo_per_cpu_scheduler",
        "@com_google_absl//absl/debugging:symbolize",
        "@com_google_absl//absl/flags:parse",
    ],
)

从以上配置可以看出,该 agent 对应的源码为 fifo_agent.cc ,其依赖于 agentfifo_per_cpu_scheduler 这些库。

ghost 用户态到内核态流程

  • 代理通过向 /sys/fs/ghost/ctl 文件中写入命令来创建一个新的 enclave
  • 代理通过 ioctl() 系统函数将设置通知 ghost 调度;
  • 代理通过将 ghost 调度中处于内核态的消息队列通过 mmap() 函数映射到用户空间,并通过该映射空间获取 内核发送出来的消息;
  • 用户态之间的进程通讯(例如 rpc 相关函数)是通过进程间的共享内存机制来进行通讯;
  • 代理和用户程序之间没有直接的数据交换;

ghOSt 测试部分(以 simple_exp 为例)

该任务在 BUILD 配置文件中的配置为:

cc_binary(
    name = "simple_exp",
    srcs = [
        "tests/simple_exp.cc",
    ],
    copts = compiler_flags,
    deps = [
        ":base",
        ":ghost",
    ],
)

从以上配置可以看出,该测试任务对应的源码为 simple_exp.cc ,其依赖于 baseghost 这些库。

测试程序与内核流程图

在本测试用例中,与 ghost 调度交互的只有一个地方就是在新建线程时,将该线程设置为 ghost 调度类:

  • 通过向 ghost 的文件夹下 enclave_X 下的 “tasks" 文件写入 线程的 pid 字符串,来设置该任务的调度为 ghost 调度;

ghost 调度通过 ghostfs 来更改线程的调度类为 ghsot 调度类;
更改为其他调度类仍然使用 sched_setscheduler()函数来实现;

参考文档

《ghOSt: Fast & Flexible User Space Delegation of Linux Scheduling》

ghost 源码 ghost-kernel & ghost-userspace

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值