3个不稳定版本
0.3.0 | 2020年3月29日 |
---|---|
0.2.1 | 2019年9月15日 |
0.2.0 | 2019年9月11日 |
#265 in Unix APIs
890 每月下载量
310KB
6.5K SLoC
controlgroup-rs
原生Rust包,用于cgroup操作。
目前此包仅支持cgroup v1层次结构,实现在 v1
模块中。
支持
未实现的功能
以下功能尚未以方便的方式实现,但您可以通过低级API直接读取和写入cgroup文件。
- 内存子系统:读取
memory.kmem.slabinfo
文件
测试的发行版
此包已在以下系统上测试:
- Ubuntu 16.04 (Xenial)
- Ubuntu 18.04 (Bionic)
在Travis-CI上。
未测试的功能
- CPU子系统
- 读取和写入实时任务的调度参数
- Cpuset子系统
- 获取cgroup面临的内存压力
- 内存子系统
- 在NUMA系统上获取每个NUMA节点的统计信息
- HugeTLB子系统
- 监控cgroup的巨大页TLB使用情况
- BlkIO子系统
- 设置设备的权重
- 监控cgroup消耗的blkio吞吐量
- RDMA子系统
v1层次结构的示例
创建由CPU子系统控制的cgroup
use std::path::PathBuf;
use controlgroup::{Pid, v1::{cpu, Cgroup, CgroupPath, SubsystemKind, Resources}};
// Define and create a new cgroup controlled by the CPU subsystem.
let mut cgroup = cpu::Subsystem::new(
CgroupPath::new(SubsystemKind::Cpu, PathBuf::from("students/charlie")));
cgroup.create()?;
// Attach the self process to the cgroup.
let pid = Pid::from(std::process::id());
cgroup.add_task(pid)?;
// Define resource limits and constraints for this cgroup.
// Here we just use the default for an example.
let resources = Resources::default();
// Apply the resource limits.
cgroup.apply(&resources)?;
// Low-level file operations are also supported.
let stat_file = cgroup.open_file_read("cpu.stat")?;
// Do something ...
// Now, remove self process from the cgroup.
cgroup.remove_task(pid)?;
// ... and delete the cgroup.
cgroup.delete()?;
// Note that subsystem handlers does not implement `Drop` and therefore when the
// handler is dropped, the cgroup will stay around.
创建由多个子系统控制的cgroup集合
v1::Builder
通过构建器模式提供配置cgroup的方法。
use std::path::PathBuf;
use controlgroup::{
Max,
v1::{devices, hugetlb::{self, HugepageSize}, net_cls, rdma, Builder, SubsystemKind},
};
let mut cgroups =
// Start building a (set of) cgroup(s).
Builder::new(PathBuf::from("students/charlie"))
// Start configuring the CPU resource limits.
.cpu()
.shares(1000)
.cfs_quota_us(500 * 1000)
.cfs_period_us(1000 * 1000)
// Finish configuring the CPU resource limits.
.done()
// Start configuring the cpuset resource limits.
.cpuset()
.cpus([0].iter().copied().collect())
.mems([0].iter().copied().collect())
.memory_migrate(true)
.done()
.memory()
.limit_in_bytes(4 * (1 << 30))
.soft_limit_in_bytes(3 * (1 << 30))
.use_hierarchy(true)
.done()
.hugetlb()
.limits(
[
(HugepageSize::Mb2, hugetlb::Limit::Pages(4)),
(HugepageSize::Gb1, hugetlb::Limit::Pages(2)),
].iter().copied()
)
.done()
.devices()
.deny(vec!["a *:* rwm".parse::<devices::Access>().unwrap()])
.allow(vec!["c 1:3 mr".parse::<devices::Access>().unwrap()])
.done()
.blkio()
.weight(1000)
.weight_device([([8, 0].into(), 100)].iter().copied())
.read_bps_device([([8, 0].into(), 10 * (1 << 20))].iter().copied())
.write_iops_device([([8, 0].into(), 100)].iter().copied())
.done()
.rdma()
.max(
[(
"mlx4_0".to_string(),
rdma::Limit {
hca_handle: 2.into(),
hca_object: Max::Max,
},
)].iter().cloned(),
)
.done()
.net_prio()
.ifpriomap(
[("lo".to_string(), 0), ("wlp1s0".to_string(), 1)].iter().cloned(),
)
.done()
.net_cls()
.classid([0x10, 0x1].into())
.done()
.pids()
.max(42.into())
.done()
.freezer()
// Tasks in this cgroup will be frozen.
.freeze()
.done()
// Enable CPU accounting for this cgroup.
// Cpuacct subsystem has no parameter, so this method does not return a subsystem builder,
// just enables the accounting.
.cpuacct()
// Enable monitoring this cgroup via `perf` tool.
// Like `cpuacct()` method, this method does not return a subsystem builder.
.perf_event()
// Skip creating directories for Cpuacct subsystem and net_cls subsystem.
// This is useful when some subsystems share hierarchy with others.
.skip_create(vec![SubsystemKind::Cpuacct, SubsystemKind::NetCls])
// Actually build cgroups with the configuration.
.build()?;
let pid = std::process::id().into();
cgroups.add_task(pid)?;
// Do something ...
cgroups.remove_task(pid)?;
cgroups.delete()?;
在一个或多个cgroup中启动进程
v1::CommandExt
扩展了 std::process::Command
构建器,以便在启动时将命令进程附加到一个或多个cgroup上。
use std::path::PathBuf;
use controlgroup::v1::{cpu, Cgroup, CgroupPath, SubsystemKind};
// Import extension trait
use controlgroup::v1::CommandExt as _;
let mut cgroup = cpu::Subsystem::new(
CgroupPath::new(SubsystemKind::Cpu, PathBuf::from("students/charlie")));
cgroup.create()?;
let mut child = std::process::Command::new("sleep")
.arg("1")
// Attach this command process to a cgroup on start
.cgroup(&mut cgroup)
// This process will run within the cgroup
.spawn()
.unwrap();
println!("{:?}", cgroup.stat()?);
child.wait().unwrap();
cgroup.delete()?;
MSRV(最小支持的Rust版本)
rustc 1.37.0 (eae3437df 2019-08-13)
如果您想使用此包与较旧的Rust版本,请在 问题 #1 上留言。
免责声明
此项目最初作为 levex/cgroups-rs 的分支开始,通过重新设计和重新实现整个项目进行开发。 levex/cgroups-rs 依据MIT OR Apache-2.0许可。
请参阅LICENSE获取详细信息。
许可证
版权所有 2019 Hidehito Yabuuchi <[email protected]>
根据MIT许可证<LICENSE-MIT 或 http://opensource.org/licenses/MIT>或Apache许可证2.0版<LICENSE-APACHE 或 https://apache.ac.cn/licenses/LICENSE-2.0>进行许可,具体取决于您的选择。所有带有此类声明的项目文件,不得复制、修改或分发,除非符合这些条款。
除非您明确表示,否则您提交给作品的所有有意贡献,如Apache-2.0许可证中定义的,将按上述方式双重许可,不附加任何额外的条款或条件。