Google ghOSt 调度介绍
Google ghOSt 调度介绍
整体框架
ghOSt 是在 Linux 内核之上实现的通用调度策略委托。 ghOSt 框架提供了丰富的 API,可以从用户空间接收进程的调度决策,并将其作为事务来执行。 程序员可以使用任何语言或工具来开发策略,并且无需重新启动机器即可升级。 ghOSt 支持一系列调度目标的策略,从 µs 级延迟到吞吐量、能源效率等等,并且调度操作的开销很低。 许多策略只是几百行代码。 总体而言,ghOSt 提供了一个高性能框架,用于将线程调度策略委托给用户空间进程,从而实现策略优化、无中断升级和故障隔离。
当启动 ghost 内核后,通过使用 mount 命令将 ghostfs 文件系统加载到虚拟文件系统下:
sudo mount --source ghost --target /sys/fs/ghost -t ghost
加载成功后,会在 /sys/fs/ghost 目录下存在如下两个重要文件:
Operation | Path | Mode | Suppored Operations |
---|---|---|---|
Get ABI version* | /sys/fs/ghost/version | 0444 | read |
Create an Enclave | /sys/fs/ghost/ctl | 0660 | write |
- 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 调度内核实现
调度类
- ghOSt 调度在内核中新增加了两个调度类:
-
ghost_agent 调度类;
-
ghost 调度类;
- 这两个调度类与其他调度类的关系是:
stop 调度类 > ghost_agent 调度类 > dl 调度类 > rt 调度类 > cfs 调度类 > ghost 调度类 > idle 调度类
- ghOSt 调度类的任务工作在 ghost 调度类上;
- ghost 调度类的任务通过 switch_to 方式直接运行在 CPU 上,其与 cfs 调度类没有优先级关系;
- ghost 代理工作在 ghost_agent 调度类上——实际上 ghost 代理也是 ghost 调度类,但是会被 ghost_agent 调度类的 pick_next_task() 函数来放到 CPU 上,所以相当于工作在 ghost_agent 调度类上;
文件系统
-
新建了 ghostfs 文件系统,用于导出 ghost 调度类的相关文件用于与用户态的程序交互。
-
ghOSt 调度的根文件夹为 /sys/fs/ghost 。
-
每个 enclave 会在根文件夹下创建一个 enclave_ 的文件夹;所有 enclave 交互的接口导出文件,都在此文件夹下;
-
用户态的代理就是通过 enclave 在 ghostfs 文件系统中导出的文件与内核进行通讯;
接口模块 enclave
每个 agent 进程都会在内核中产生一个对应的 enclave 接口模块,该模块提供了一系列的 abi 的 API 接口,通过该接口可以将内核的信息传递给用户态的 agent 。
事务
- 内核通过消息事务将内核中的信息传递给用户空间的 agent;
- 事务提交时机:
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);
- 事务传递过程:
- 用户态的 agent 将内核中的 enclave 的消息通道和 ghost 任务的状态字通过 mmap 的方式映射到用户空间;
- 内核生成相应的消息并将其保存到消息通道中;
- 消息保存成功后唤醒用户态的 agent 任务;
- 用户态的 agent 处理消息;
汇合点 rendezvous
- 数据定义
-
rendezvous 字段的内容: <sign|cpu_num|poison|counter>
-
其中:
1 位用于 ,11 位用于 <cpu_num> ,1 位用于 ,51 位用于
- 保存汇合点时机
-
用户态的 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);
- 保存汇合点的函数
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 为例)
该 Agent 在 BUILD 配置文件中的配置为:
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 ,其依赖于 agent ,fifo_per_cpu_scheduler 这些库。
- 代理通过向 /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 ,其依赖于 base ,ghost 这些库。
在本测试用例中,与 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