What are Control Groups (cgroups) and How Do They Limit Resources?
Understand Linux cgroups — how they cap CPU, memory, and I/O per process group — with a code example and OS interview questions.
Expected Interview Answer
Control groups, or cgroups, are a Linux kernel feature that organizes processes into hierarchical groups and enforces limits, accounting, and prioritization on the CPU, memory, disk I/O, and network resources those groups consume, forming the resource-control half of container isolation alongside namespaces.
Where namespaces control what a process can see, cgroups control how much of a resource it can use. Processes are attached to a cgroup, and controllers (subsystems) like `cpu`, `memory`, `blkio`, and `pids` attach limits to that cgroup — for example, a memory cgroup can cap a group of processes to 512MB, and the kernel’s OOM killer will terminate a process in that group rather than starving the rest of the system. Cgroups v2 unifies these controllers under a single hierarchy mounted at `/sys/fs/cgroup`, exposing tunable files such as `memory.max` and `cpu.max` that tools like Docker, systemd, and Kubernetes write to when starting a container or service. Because limits are enforced by the kernel itself rather than by cooperative user-space code, a runaway process cannot exceed its cgroup’s quota no matter how it misbehaves, which is what lets many containers safely share one physical machine without one tenant starving the others.
- Prevents a single process or container from starving others of CPU or memory
- Kernel-enforced, so limits hold even for misbehaving or malicious processes
- Provides per-group resource accounting for monitoring and billing
- Underpins container resource limits in Docker and Kubernetes pod QoS
AI Mentor Explanation
Cgroups are like a groundskeeper allocating each practice net a fixed daily quota of bowling machine balls and a capped number of floodlight hours, tracked and enforced regardless of how eager any one squad is to use more. If a squad’s net exceeds its ball quota, the machine simply stops feeding balls to that net rather than starving the others, just as a memory cgroup halts or kills a process that exceeds its cap. This is separate from roping off which players belong to which net — that visibility split is the namespace, while the quota enforcement is the cgroup.
Step-by-Step Explanation
Step 1
Create the cgroup
A new cgroup directory is created under the unified hierarchy at /sys/fs/cgroup, e.g. mkdir /sys/fs/cgroup/mygroup.
Step 2
Set resource limits
Controller files inside the cgroup are written, such as memory.max or cpu.max, defining the enforced ceiling.
Step 3
Attach processes
A process PID is written into the cgroup's cgroup.procs file, placing it under that group's limits.
Step 4
Kernel enforcement
The kernel throttles or OOM-kills processes that exceed their cgroup's limits, independent of other cgroups.
What Interviewer Expects
- Correct distinction between cgroups (resource limits) and namespaces (visibility isolation)
- Naming at least two controllers (cpu, memory, blkio, pids) and what each governs
- Understanding that limits are kernel-enforced, not cooperative
- Awareness that cgroups v2 uses a single unified hierarchy
Common Mistakes
- Confusing cgroups with namespaces (or believing they do the same job)
- Thinking resource limits are advisory rather than kernel-enforced
- Not knowing what happens when a memory cgroup limit is exceeded (OOM kill)
- Assuming cgroups only apply to containers and not services like systemd units
Best Answer (HR Friendly)
“Cgroups are the kernel feature that lets you cap how much CPU, memory, or disk I/O a group of processes is allowed to use, and the kernel enforces that cap directly rather than trusting the process to behave. That is what stops one noisy container or service from starving everything else running on the same machine, and it is the resource-limiting half of what makes Docker and Kubernetes safe to run many workloads on shared hardware.”
Code Example
#include <stdio.h>
#include <stdlib.h>
/* Writes a memory limit into a cgroup v2 controller file, then
attaches the current process to that cgroup. Requires the cgroup
directory to already exist under /sys/fs/cgroup. */
int apply_memory_limit(const char *cgroup_path, long max_bytes, pid_t pid) {
char limit_file[256];
char procs_file[256];
snprintf(limit_file, sizeof(limit_file), "%s/memory.max", cgroup_path);
snprintf(procs_file, sizeof(procs_file), "%s/cgroup.procs", cgroup_path);
FILE *f = fopen(limit_file, "w");
if (!f) return -1;
fprintf(f, "%ld", max_bytes); /* e.g. 536870912 for 512MB */
fclose(f);
f = fopen(procs_file, "w");
if (!f) return -1;
fprintf(f, "%d", pid); /* attach this PID to the cgroup */
fclose(f);
return 0;
}Follow-up Questions
- What happens when a process exceeds its memory cgroup limit?
- What is the difference between cgroups v1 and cgroups v2?
- How does Kubernetes use cgroups to implement pod QoS classes?
- How would you monitor real-time CPU usage of a specific cgroup?
MCQ Practice
1. What is the primary role of a cgroup in Linux?
Cgroups organize processes into groups and let controllers enforce limits and accounting on resources such as CPU, memory, and I/O.
2. What typically happens when a process exceeds its cgroup memory.max limit?
When a cgroup hits its memory ceiling, the kernel invokes the OOM killer scoped to that cgroup rather than affecting unrelated processes.
3. How do cgroups differ from namespaces?
Namespaces control what a process can see (PIDs, network, mounts); cgroups control how much of a resource it is allowed to consume.
Flash Cards
What is a cgroup? — A kernel mechanism that groups processes and enforces limits on their resource usage, such as CPU or memory.
Cgroups vs namespaces? — Cgroups limit how much of a resource a process can use; namespaces isolate what it can see.
What happens on a memory cgroup limit breach? — The kernel's OOM killer terminates a process within that cgroup.
Name two cgroup controllers. — cpu and memory — also blkio (disk I/O) and pids (process count).