cgroup怎么使用
发表于:2025-02-04 作者:千家信息网编辑
千家信息网最后更新 2025年02月04日,本篇内容主要讲解"cgroup怎么使用",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"cgroup怎么使用"吧!runC项目中,与cgroups相关的代码,
千家信息网最后更新 2025年02月04日cgroup怎么使用
本篇内容主要讲解"cgroup怎么使用",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"cgroup怎么使用"吧!
runC项目中,与cgroups相关的代码,都在目录 runc/libcontainer/cgroups/下
我们关注的主要内容在apply_raw.go和各个cgroups子系统的操作方法实现定义文件,如上图中红色字体部分显示的文件。 apply_raw.go主要是实现了cgroups.go中定义的一系列接口:
type Manager interface { // Applies cgroup configuration to the process with the specified pid Apply(pid int) error // Returns the PIDs inside the cgroup set GetPids() ([]int, error) // Returns the PIDs inside the cgroup set & all sub-cgroups GetAllPids() ([]int, error) // Returns statistics for the cgroup set GetStats() (*Stats, error) // Toggles the freezer cgroup according with specified state Freeze(state configs.FreezerState) error // Destroys the cgroup set Destroy() error // NewCgroupManager() and LoadCgroupManager() require following attributes: // Paths map[string]string // Cgroups *cgroups.Cgroup // Paths maps cgroup subsystem to path at which it is mounted. // Cgroups specifies specific cgroup settings for the various subsystems // Returns cgroup paths to save in a state file and to be able to // restore the object later. GetPaths() map[string]string // Sets the cgroup as configured. Set(container *configs.Config) error}
apply_raw.go中对上面定义的Manager中的8个接口逐一实现:
type Manager struct { mu sync.Mutex Cgroups *configs.Cgroup Paths map[string]string} func (m *Manager) Apply(pid int) (err error) { if m.Cgroups == nil { return nil } m.mu.Lock() defer m.mu.Unlock() var c = m.Cgroups d, err := getCgroupData(m.Cgroups, pid) if err != nil { return err } if c.Paths != nil { paths := make(map[string]string) for name, path := range c.Paths { _, err := d.path(name) if err != nil { if cgroups.IsNotFound(err) { continue } return err } paths[name] = path } m.Paths = paths return cgroups.EnterPid(m.Paths, pid) } paths := make(map[string]string) for _, sys := range subsystems { if err := sys.Apply(d); err != nil { return err } // TODO: Apply should, ideally, be reentrant or be broken up into a separate // create and join phase so that the cgroup hierarchy for a container can be // created then join consists of writing the process pids to cgroup.procs p, err := d.path(sys.Name()) if err != nil { // The non-presence of the devices subsystem is // considered fatal for security reasons. if cgroups.IsNotFound(err) && sys.Name() != "devices" { continue } return err } paths[sys.Name()] = p } m.Paths = paths return nil} func (m *Manager) Destroy() error { if m.Cgroups.Paths != nil { return nil } m.mu.Lock() defer m.mu.Unlock() if err := cgroups.RemovePaths(m.Paths); err != nil { return err } m.Paths = make(map[string]string) return nil} func (m *Manager) GetPaths() map[string]string { m.mu.Lock() paths := m.Paths m.mu.Unlock() return paths} func (m *Manager) GetStats() (*cgroups.Stats, error) { m.mu.Lock() defer m.mu.Unlock() stats := cgroups.NewStats() for name, path := range m.Paths { sys, err := subsystems.Get(name) if err == errSubsystemDoesNotExist || !cgroups.PathExists(path) { continue } if err := sys.GetStats(path, stats); err != nil { return nil, err } } return stats, nil} func (m *Manager) Set(container *configs.Config) error { // If Paths are set, then we are just joining cgroups paths // and there is no need to set any values. if m.Cgroups.Paths != nil { return nil } paths := m.GetPaths() for _, sys := range subsystems { path := paths[sys.Name()] if err := sys.Set(path, container.Cgroups); err != nil { return err } } if m.Paths["cpu"] != "" { if err := CheckCpushares(m.Paths["cpu"], container.Cgroups.Resources.CpuShares); err != nil { return err } } return nil} // Freeze toggles the container's freezer cgroup depending on the state// providedfunc (m *Manager) Freeze(state configs.FreezerState) error { paths := m.GetPaths() dir := paths["freezer"] prevState := m.Cgroups.Resources.Freezer m.Cgroups.Resources.Freezer = state freezer, err := subsystems.Get("freezer") if err != nil { return err } err = freezer.Set(dir, m.Cgroups) if err != nil { m.Cgroups.Resources.Freezer = prevState return err } return nil} func (m *Manager) GetPids() ([]int, error) { paths := m.GetPaths() return cgroups.GetPids(paths["devices"])} func (m *Manager) GetAllPids() ([]int, error) { paths := m.GetPaths() return cgroups.GetAllPids(paths["devices"])}
再以cpu subsystem为例,看看各subsystem具体的操作方法定义:
type CpuGroup struct {} func (s *CpuGroup) Name() string { return "cpu"} // 将cgroup配置和对应的pid更新到cpu subsystemfunc (s *CpuGroup) Apply(d *cgroupData) error { // We always want to join the cpu group, to allow fair cpu scheduling // on a container basis path, err := d.path("cpu") if err != nil && !cgroups.IsNotFound(err) { return err } return s.ApplyDir(path, d.config, d.pid)} func (s *CpuGroup) ApplyDir(path string, cgroup *configs.Cgroup, pid int) error { // This might happen if we have no cpu cgroup mounted. // Just do nothing and don't fail. if path == "" { return nil } if err := os.MkdirAll(path, 0755); err != nil { return err } // We should set the real-Time group scheduling settings before moving // in the process because if the process is already in SCHED_RR mode // and no RT bandwidth is set, adding it will fail. if err := s.SetRtSched(path, cgroup); err != nil { return err } // because we are not using d.join we need to place the pid into the procs file // unlike the other subsystems if err := cgroups.WriteCgroupProc(path, pid); err != nil { return err } return nil} func (s *CpuGroup) SetRtSched(path string, cgroup *configs.Cgroup) error { if cgroup.Resources.CpuRtPeriod != 0 { if err := writeFile(path, "cpu.rt_period_us", strconv.FormatInt(cgroup.Resources.CpuRtPeriod, 10)); err != nil { return err } } if cgroup.Resources.CpuRtRuntime != 0 { if err := writeFile(path, "cpu.rt_runtime_us", strconv.FormatInt(cgroup.Resources.CpuRtRuntime, 10)); err != nil { return err } } return nil} func (s *CpuGroup) Set(path string, cgroup *configs.Cgroup) error { if cgroup.Resources.CpuShares != 0 { if err := writeFile(path, "cpu.shares", strconv.FormatInt(cgroup.Resources.CpuShares, 10)); err != nil { return err } } if cgroup.Resources.CpuPeriod != 0 { if err := writeFile(path, "cpu.cfs_period_us", strconv.FormatInt(cgroup.Resources.CpuPeriod, 10)); err != nil { return err } } if cgroup.Resources.CpuQuota != 0 { if err := writeFile(path, "cpu.cfs_quota_us", strconv.FormatInt(cgroup.Resources.CpuQuota, 10)); err != nil { return err } } if err := s.SetRtSched(path, cgroup); err != nil { return err } return nil} func (s *CpuGroup) Remove(d *cgroupData) error { return removePath(d.path("cpu"))} func (s *CpuGroup) GetStats(path string, stats *cgroups.Stats) error { f, err := os.Open(filepath.Join(path, "cpu.stat")) if err != nil { if os.IsNotExist(err) { return nil } return err } defer f.Close() sc := bufio.NewScanner(f) for sc.Scan() { t, v, err := getCgroupParamKeyValue(sc.Text()) if err != nil { return err } switch t { case "nr_periods": stats.CpuStats.ThrottlingData.Periods = v case "nr_throttled": stats.CpuStats.ThrottlingData.ThrottledPeriods = v case "throttled_time": stats.CpuStats.ThrottlingData.ThrottledTime = v } } return nil}
查看某个runC启动的容器state.json文件,能看到该容器对应的cgroup和namespace 路径信息: $ cat /var/run/runc/$containerName/state.json | jq .
"namespace_paths": { "NEWUTS": "/proc/30097/ns/uts", "NEWUSER": "/proc/30097/ns/user", "NEWPID": "/proc/30097/ns/pid", "NEWNS": "/proc/30097/ns/mnt", "NEWNET": "/proc/30097/ns/net", "NEWIPC": "/proc/30097/ns/ipc" }, "cgroup_paths": { "perf_event": "/sys/fs/cgroup/perf_event/user.slice/container1", "net_cls": "/sys/fs/cgroup/net_cls/user.slice/container1", "name=systemd": "/sys/fs/cgroup/systemd/user.slice/container1", "blkio": "/sys/fs/cgroup/blkio/user.slice/container1", "cpu": "/sys/fs/cgroup/cpu,cpuacct/user.slice/container1", "cpuacct": "/sys/fs/cgroup/cpu,cpuacct/user.slice/container1", "cpuset": "/sys/fs/cgroup/cpuset/user.slice/container1", "devices": "/sys/fs/cgroup/devices/user.slice/container1", "freezer": "/sys/fs/cgroup/freezer/user.slice/container1", "hugetlb": "/sys/fs/cgroup/hugetlb/user.slice/container1", "memory": "/sys/fs/cgroup/memory/user.slice/container1" },
到此,相信大家对"cgroup怎么使用"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
内容
文件
方法
容器
接口
学习
实用
更深
代码
信息
兴趣
如上
子系统
字体
实用性
实际
操作简单
更多
朋友
目录
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
穿越火线哪个服务器能玩
爱快怎么设置映射公网给服务器
计算机软件开发职业规划书
分析型数据库的应用
广州通信软件开发费用是多少
网络安全治理能力
数据库查询李勇所选课程的成绩
上海银联网络技术活动方案
软件开发单元测试完整版
支持主干网络技术的标准
魔兽世界怀旧服tbc服务器扩容
服务器内存加了发现不了
silva数据库的适用范围
raid卡和硬盘前提到新服务器
服务器接受消息
网络安全电脑桌面背景
数据库实验数据更新答案
泉州软件开发区
退出按钮数据库
狼人杀为啥服务器暂停服务
初学软件开发入门书籍
中国图书全文数据库
您没有服务器现正使用的内容
东丽区企业网络技术质量保证
服务器集群资源不够扩容方案
电力网络安全态势
数据库 项目设计
管家婆行业软件开发
魔兽世界tbc 埃提耶什服务器
米思米数据库