Control groups (cgroups) are a Linux concept for tracking and controlling the resources used by a group of processes. All processes are tracked using cgroups. They are used to associate resources (CPU, memory, network,...) with process IDs. Resources are organized in a control group subsystem containing:
Each process ID is represented once in each subsystem in the "tasks" file : "/sys/fs/cgroup/cpu/tasks" for the "cpu cgroup" for example.
For each resource we have a "tasks" file that contains all the processes affected the cgroup "rule" for a certain resource.
For the "cpu" resources, all the processes affected by the "cpu cgroup" rules : "/sys/fs/cgroup/cpu/tasks"
The "tasks" file contains way more process IDs that shown above.
Child processes inherit "cgroups" from their parents process.
Cproup virtual filesystem:
Cgroups are represented in the system as by virtual filesystem located in : "/sys/fs/cgroup". The "tasks" file contains all the processes PIDs in a cgroup subsystem, example"/sys/fs/cgroup/cpu/tasks" for the "cpu". To have other resources sharing scheme for the "cpu" resource for example, we can create a "scheme_1" subdirectory under the "cpu" directory: "/sys/fs/cgroup/cpu/scheme_1".
The new "scheme_1" will inherit the same cgroup scheme from the parent directory "cpu".
In the example below we have two "cpu" sharing schemes.
The "tasks" file for the scheme_1 and scheme_2 are in the "/sys/fs/cgroup/cpu/scheme_1/tasks" and "/sys/fs/cgroup/cpu/scheme_2/tasks" respectively.
Cgroups on a system:
Displays all the cgroup subsystems on the machine.
We have the memory cgroup filesystem "/sys/fs/cgroup/memory", its file "/sys/fs/cgroup/memory/tasks" contains the PIDs of all the processes affected by the root memory cgroup rules.
The /proc filesystem and cgroups:
The proc filesystem allows us to have a peek into the kernel. It contains directories that correspond to all running processes in the system. We can access the cgroup of a given process using the below command:
Creating a new cgroup subsystem:
We do that by creating a new directory as mentioned above.
The newly created "memory_docker_container" directory will inherit the structure of its parent folder. We can put the process we want the rules of "memory_docker_container" to apply to in the "tasks" file as below:
We start by creating a subfolder under the "pid" cgroup:
We, then set the pids.max to one process:
We add the current shell process ID to the "tasks" file:
The child processes inherit the cgroups from the parent (with the same restriction as the parent, in our case -pids.max-).
When we run another commands in the shell, for example, the command "ls", the pid count reaches two exceeding the pids.max (current shell and the "ls" child program) and we get an error.