9 个版本 (4 个稳定版)
新版本 1.0.3 | 2024 年 8 月 21 日 |
---|---|
1.0.2 | 2024 年 8 月 9 日 |
1.0.1 | 2024 年 7 月 15 日 |
0.5.0 | 2024 年 6 月 3 日 |
0.1.1 | 2024 年 4 月 4 日 |
419 在 内存管理 中排名
每月下载 111 次
在 2 crate 中使用
2.5MB
2.5K SLoC
用户空间运行的 sched_ext 调度器的框架
sched_ext 是一个 Linux 内核功能,它允许在 BPF 中实现内核线程调度器并动态加载它们。
此 crate 提供了一个通用层,可用于实现运行在用户空间的 sched-ext 调度器。
它提供了一个通用的 BPF 抽象层,与用户空间中实现的特定调度策略无关。
开发者可以使用此类抽象使用纯 Rust 代码实现调度器,无需处理任何内核 / BPF 内部细节。
API
主要的 BPF 接口由 BpfScheduler
结构体提供。当此对象初始化时,它将负责注册和初始化 BPF 组件。
然后调度器可以使用 BpfScheduler
实例接收任务(以 QueuedTask
对象的形式)和调度任务(以 DispatchedTask 对象的形式),分别使用 dequeue_task()
和 dispatch_task()
方法。
示例用法(FIFO 调度器)
struct Scheduler<'a> {
bpf: BpfScheduler<'a>,
}
impl<'a> Scheduler<'a> {
fn init() -> Result<Self> {
let topo = Topology::new().expect("Failed to build host topology");
let bpf = BpfScheduler::init(5000, topo.nr_cpus() as i32, false, false, false)?;
Ok(Self { bpf })
}
fn schedule(&mut self) {
match self.bpf.dequeue_task() {
Ok(Some(task)) => {
// task.cpu < 0 is used to to notify an exiting task, in this
// case we can simply ignore it.
if task.cpu >= 0 {
let _ = self.bpf.dispatch_task(&DispatchedTask {
pid: task.pid,
cpu: task.cpu,
cpumask_cnt: task.cpumask_cnt,
slice_ns: 0,
});
}
}
Ok(None) => {
// Notify the BPF component that all tasks have been dispatched.
self.bpf.update_tasks(Some(0), Some(0))?
break;
}
Err(_) => {
break;
}
}
}
此外,可以使用方法 get_cpu_pid()
访问 CPU 拥有者映射(该映射记录了哪些 PID 在哪个 CPU 上运行)。这也可以用来跟踪空闲和忙碌的 CPU,以及与之关联的相应 PID。
可以使用方法 nr_*_mut()
访问 BPF 计数器和统计信息,特别是 nr_queued_mut()
和 nr_scheduled_mut()
可以更新,以通知 BPF 组件用户空间调度器是否还有待完成的工作。
最后,可以使用方法 exited()
和 shutdown_and_report()
分别来测试 BPF 组件是否已退出,以及关闭并报告退出信息。
依赖项
~20–32MB
~549K SLoC