Once a cgroup subsystem is made available (by mounting it), a process is always part of a cgroup within this subsystem's hierarchy, and that will initially be its root cgroup, unless moved in an other cgroup, where its descendents will appear too. "Detaching" a process usually means moving it (back) to the root cgroup of the given subsystem(s).
Assuming subsystems are already adequately mounted, everything is available by creating/removing pseudo-directories or reading/writing adequate values to pseudo-files appearing in those directories usually under /sys/fs/cgroup
as described in man cgroups.7
, else the dedicated command provided along cgexec
is cgclassify
.
Here's an example (using cgroups v1) to illustrate it from a bash shell:
# ls /sys/fs/cgroup/{memory,cpu}/groupname/mygroup
ls: cannot access '/sys/fs/cgroup/memory/groupname/mygroup': No such file or directory
ls: cannot access '/sys/fs/cgroup/cpu/groupname/mygroup': No such file or directory
# cgcreate -g memory,cpu:groupname/mygroup
# ls -d /sys/fs/cgroup/{memory,cpu}/groupname/mygroup
/sys/fs/cgroup/cpu/groupname/mygroup /sys/fs/cgroup/memory/groupname/mygroup
Of course some dedicated settings could probably be applied after creating the cgroups above.
# cgexec -g memory,cpu:groupname/mygroup sh -c 'echo $$; exec sleep 999'
14682
Other terminal:
# grep -w 14682 /sys/fs/cgroup/{memory,cpu}/groupname/mygroup/cgroup.procs
/sys/fs/cgroup/memory/groupname/mygroup/cgroup.procs:14682
/sys/fs/cgroup/cpu/groupname/mygroup/cgroup.procs:14682
# grep -w 14682 /sys/fs/cgroup/{memory,cpu}/cgroup.procs
#
# cgclassify -g memory,cpu:/ 14682
# grep -w 14682 /sys/fs/cgroup/{memory,cpu}/groupname/mygroup/cgroup.procs
# grep -w 14682 /sys/fs/cgroup/{memory,cpu}/cgroup.procs
/sys/fs/cgroup/memory/cgroup.procs:14682
/sys/fs/cgroup/cpu/cgroup.procs:14682
The three dedicated commands above could have been replaced by these simple shell commands:
# mkdir -p /sys/fs/cgroup/{memory,cpu}/groupname/mygroup
# bash -c 'echo $$ | tee /sys/fs/cgroup/{memory,cpu}/groupname/mygroup/cgroup.procs; exec sleep 999'
15533
and (to "detach" it):
# echo 15533 | tee /sys/fs/cgroup/{memory,cpu}/cgroup.procs
15533
Note actually the dedicated command cgclassify
, at least on cgroups v1 acts on the process' threads (using .../tasks
) rather than the process itself (using .../cgroup.procs
). For simple processes, the pid (process ID) which is the unique thread and thus the task group ID (tgid=pid), is seen the same in both pseudo-files and there is no difference. For multi-threaded processes, moving the whole process requires to identify all of its threads when using .../tasks
or simply to use .../cgroup.procs
. It's in the man:
When writing a PID into the cgroup.procs
, all threads in the process
are moved into the new cgroup at once.
In cgroups v1, an individual thread can be moved to another cgroup by
writing its thread ID (i.e., the kernel thread ID returned by clone(2)
and gettid(2)) to the tasks
file in a cgroup directory. This file can
be read to discover the set of threads that are members of the cgroup.
That's why I chose to display and use .../cgroup.procs
after. It would matter when moving a multithreaded process like Firefox, a java application, etc. pgrep --lightweight
could be used to provide all the tasks to cgclassify
for this case (beware of races though).