While cgroups (control groups) traditionally require root privileges, modern Linux systems (kernel 4.6+) support delegated cgroup management through the cgroups v2 filesystem hierarchy. The key lies in proper filesystem permissions and namespace configuration.
Before attempting user-level cgroup management, verify these system conditions:
# Check cgroup v2 mount
mount | grep cgroup2
# Verify kernel version
uname -r
# Check for cpu controller availability
cat /sys/fs/cgroup/cgroup.controllers
System administrators must first enable user delegation:
# As root:
mkdir /sys/fs/cgroup/user.slice
echo '+cpu +memory +pids' > /sys/fs/cgroup/user.slice/cgroup.subtree_control
chown -R user:user /sys/fs/cgroup/user.slice
Once configured, users can create their own hierarchy:
# As regular user:
mkdir -p ~/my_cgroups/cpu_limited
echo "100000" > ~/my_cgroups/cpu_limited/cpu.max
echo "1" > ~/my_cgroups/cpu_limited/cpu.weight
To launch a process in your cgroup:
# Using cgroup-tools (if installed)
cgexec -g cpu:~/my_cgroups/cpu_limited my_command
# Manual method
echo $$ > ~/my_cgroups/cpu_limited/cgroup.procs
./my_application
Confirm your process is properly constrained:
cat /proc/$(pgrep my_application)/cgroup
cat ~/my_cgroups/cpu_limited/cpu.stat
If encountering permission errors:
- Verify systemd unit files aren't overriding your cgroups
- Check for existing cgroupv1 hierarchies that might conflict
- Confirm your user has write access to all parent cgroup directories
For older systems without cgroupv2:
# Requires admin setup first
sudo cgcreate -a $USER -g cpu:/user_$USER
cgset -r cpu.cfs_period_us=100000 -r cpu.cfs_quota_us=50000 user_$USER
cgexec -g cpu:user_$USER ./cpu_intensive_process
Modern Linux systems (kernel 4.15+) with cgroups v2 support user delegation through the cgroup.subtree_control interface. The key filesystem locations are:
/sys/fs/cgroup/
└── user.slice
└── user-{uid}.slice
System administrators must first enable user delegation:
# As root:
echo "+cpu +memory +pids" > /sys/fs/cgroup/cgroup.subtree_control
mkdir -p /sys/fs/cgroup/user.slice
chmod 755 /sys/fs/cgroup/user.slice
After configuration, regular users can create their own hierarchies:
# As regular user:
CGROUP_PATH="/sys/fs/cgroup/user.slice/user-$(id -u).slice/my-app"
mkdir -p "$CGROUP_PATH"
To restrict a process to use only one CPU core:
# Set CPU quota (100000 = 1 core)
echo "100000" > "$CGROUP_PATH/cpu.max"
# Launch process in cgroup
echo $$ > "$CGROUP_PATH/cgroup.procs"
./cpu_intensive_task
Memory limits can be similarly enforced:
# Set 1GB memory limit
echo "1G" > "$CGROUP_PATH/memory.high"
# Optional OOM killer setting
echo "1" > "$CGROUP_PATH/memory.oom.group"
Managing process groups efficiently:
# Move existing process
echo 12345 > "$CGROUP_PATH/cgroup.procs"
# Fork new process directly in cgroup
cgexec -g cpu,memory:my-app ./new_process
- Permission denied: Verify
user.slicepermissions - No such file: Check if cgroups v2 is mounted (
mount | grep cgroup2) - Invalid argument: Ensure kernel supports the specific controller