// CreateCgroupPath creates cgroupv2 path, enabling all the supported controllers.
func CreateCgroupPath(path string, c *configs.Cgroup) (Err error) {
if !strings.HasPrefix(path, UnifiedMountpoint) {
return fmt.Errorf("invalid cgroup path %s", path)
}
content, err := supportedControllers()
if err != nil {
return err
}
const (
cgTypeFile = "cgroup.type"
cgStCtlFile = "cgroup.subtree_control"
)
ctrs := strings.Fields(content)
res := "+" + strings.Join(ctrs, " +")
elements := strings.Split(path, "/")
elements = elements[3:]
current := "/sys/fs"
for i, e := range elements {
current = filepath.Join(current, e)
if i > 0 {
if err := os.Mkdir(current, 0o755); err != nil {
if !os.IsExist(err) {
return err
}
} else {
// If the directory was created, be sure it is not left around on errors.
current := current
defer func() {
if Err != nil {
os.Remove(current)
}
}()
}
cgType, _ := cgroups.ReadFile(current, cgTypeFile)
cgType = strings.TrimSpace(cgType)
switch cgType {
// If the cgroup is in an invalid mode (usually this means there's an internal
// process in the cgroup tree, because we created a cgroup under an
// already-populated-by-other-processes cgroup), then we have to error out if
// the user requested controllers which are not thread-aware. However, if all
// the controllers requested are thread-aware we can simply put the cgroup into
// threaded mode.
case "domain invalid":
if containsDomainController(c.Resources) {
return fmt.Errorf("cannot enter cgroupv2 %q with domain controllers -- it is in an invalid state", current)
} else {
// Not entirely correct (in theory we'd always want to be a domain --
// since that means we're a properly delegated cgroup subtree) but in
// this case there's not much we can do and it's better than giving an
// error.
_ = cgroups.WriteFile(current, cgTypeFile, "threaded")
}
// If the cgroup is in (threaded) or (domain threaded) mode, we can only use thread-aware controllers
// (and you cannot usually take a cgroup out of threaded mode).
case "domain threaded":
fallthrough
case "threaded":
if containsDomainController(c.Resources) {
return fmt.Errorf("cannot enter cgroupv2 %q with domain controllers -- it is in %s mode", current, cgType)
}
}
}
// enable all supported controllers
if i < len(elements)-1 {
if err := cgroups.WriteFile(current, cgStCtlFile, res); err != nil {
// try write one by one
allCtrs := strings.Split(res, " ")
for _, ctr := range allCtrs {
_ = cgroups.WriteFile(current, cgStCtlFile, ctr)
}
}
// Some controllers might not be enabled when rootless or containerized,
// but we don't catch the error here. (Caught in setXXX() functions.)
}
}
return nil
}
switch
中代码一些要点记录
fallthrough
关键字是干嘛的
一句话:执行下一个 case
中的语句,并且不执行 case 中的检测。如果没有其他逻辑代码在当前 case
执行,应该直接合并两个 case
.
*要点*:
1. golang `case`块默认有一个`break`语句,一般代码里也是直接不写的,也就是执行完之后会跳出`switch`。区别与其他的一些语言,所以有了 `fallthrough`。
2. 执行到下一个`case`是**不进行条件检查**的。
3. 因为要执行到下一个`case`,所以不能出现在最后一个`case`块。
cgroup.type
是什么
cgroup
的两种类型
-
domain
一个 cgroup 组创建出来,默认是
domain
类型的。进程的所有线程属于一个cgroup
,并对资源进行管理。 -
threaded
echo threaded > cgroup.type
,转换成thraeded
类型操作是单向的。
thread
类型用于管理进程的不同线程。- 父节点必须是
(thread)domain
或者thread
类型的 - 如果父节点是
non threaded
类型,不能开启domain
类型的controllers
.root
节点除外。
- 父节点必须是
-
thread domain
一组
threaded subtree
的根节点。
A(thread domain) -> B(threaded) ->C(threaded)
。 当cgroup
子树变成thread
类型的时候,父节点就会被更改为domain thread
。 -
domain invalid
不能
populate
以及不能开启controllers
的状态。
populated
每一个非根节点的 cgroup
都有一个 cgroup.event
文件。其中记录着 populated
字段。标识 当前 cgroup 的 sub-hierarchy
有没有活动的进程(0 没有 ;1 有)。
cat cgroup.events
populated 0
frozen 0
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于