How Linux CPU Cgroups Limit Process Usage
Control Groups (cgroups) are a core Linux kernel feature designed to isolate, allocate, and monitor system resources among groups of processes. When managing CPU utilization, the kernel combines cgroup accounting with scheduler logic—specifically the Completely Fair Scheduler (CFS)—to enforce both proportional time-sharing and strict processing ceilings. This mechanism ensures that high-priority workloads remain responsive while preventing misbehaving or resource-heavy processes from starving the rest of the system.
Core Scheduler Mechanisms
The Linux kernel relies on two primary mechanisms within the CPU controller to limit usage: proportional shares (soft limits) and bandwidth control (hard limits).
1. Proportional Bandwidth (Shares and Weights)
Proportional sharing determines how CPU time is divided when multiple processes are actively competing for cycles. If the system is idle, a process using this mechanism can consume up to 100% of available CPU capacity.
- cgroups v1 (
cpu.shares): The default share value is typically 1024. If Group A has 1024 shares and Group B has 2048 shares, Group B is entitled to twice as much CPU time as Group A under 100% system utilization. - cgroups v2 (
cpu.weight): Uses an integer scale between 1 and 10,000 (defaulting to 100). The kernel divides the sum of weights among active cgroups to allocate proportional CPU slices during contention.
2. CFS Bandwidth Control (Hard Limits)
CFS bandwidth control prevents a process from exceeding a specified absolute threshold, regardless of whether spare CPU capacity exists on the host. This mechanism operates on two main parameters: period and quota.
- Period: A sliding tracking window measured in microseconds (typically 100,000 microseconds or 100 ms).
- Quota: The maximum amount of time within that single period that the cgroup is allowed to spend running on the CPU.
In cgroups v1, these are configured using:
cpu.cfs_period_us: Sets the duration of the cycle (e.g.,100000).cpu.cfs_quota_us: Sets the allowed runtime (e.g.,50000limits the group to 50ms per 100ms, effectively capping it at 50% of a single CPU core. Setting it to200000allows it to use up to 2 full CPU cores).
In cgroups v2, these parameters are consolidated
into a single file called cpu.max:
- The format is
[quota] [period]. For instance, writing50000 100000limits the group to half a core, whilemax 100000removes the ceiling.
The Throttling Process
When a hard limit is configured, the kernel enforces it via throttling:
- Accounting: Each time a thread from the target cgroup is scheduled to run, the kernel tracks the CPU time it accumulates via timer interrupts and context switches.
- Quota Depletion: Once the aggregate runtime of all threads in the cgroup reaches the assigned quota before the period expires, the kernel flags the cgroup as throttled.
- Descheduling: Throttled processes are immediately removed from the CFS runqueue. Even if the system has idle cores, these processes cannot execute any instructions.
- Replenishment: When the next period begins (e.g., at the next 100ms interval), a timer interrupt resets the used quota, the cgroup transitions back to an unthrottled state, and its threads are requeued for execution.
Throttling statistics are recorded in cpu.stat, allowing
administrators and container engines to track metrics such as
nr_throttled (number of periods throttled) and
throttled_time (total time spent blocked).
Processor Pinning with the Cpuset Subsystem
In addition to bandwidth-based throttling, Linux provides the
cpuset cgroup controller. While the standard CPU controller
dictates how much processor time a process receives,
cpuset restricts where that execution occurs:
cpuset.cpus: Restricts the group to specific physical or logical CPU cores (e.g.,0-3binds execution strictly to cores 0 through 3).cpuset.mems: Enforces memory allocation affinity to specific NUMA nodes.
Combining CFS bandwidth control with cpuset isolates
processes both temporally (limiting total execution time) and spatially
(confining execution to designated hardware units), providing
deterministic resource controls across modern Linux environments.