Os **grupos de controle do Linux**, também conhecidos como cgroups, são um recurso do kernel do Linux que permite **limitar**, policiar e priorizar **recursos do sistema** para uma coleção de processos. Os cgroups fornecem uma maneira de **gerenciar e isolar o uso de recursos** (CPU, memória, E/S de disco, rede, etc.) de grupos de processos em um sistema. Isso pode ser útil para muitos propósitos, como limitar os recursos disponíveis para um grupo específico de processos, isolar certos tipos de cargas de trabalho de outros ou priorizar o uso de recursos do sistema entre diferentes grupos de processos.
Existem **duas versões de cgroups**, 1 e 2, e ambas estão atualmente em uso e podem ser configuradas simultaneamente em um sistema. A diferença mais **significativa** entre a versão 1 e a **versão 2** dos cgroups é que esta última introduziu uma nova organização hierárquica para os cgroups, onde os grupos podem ser organizados em uma estrutura **semelhante a uma árvore** com relacionamentos pai-filho. Isso permite um controle mais flexível e refinado sobre a alocação de recursos entre diferentes grupos de processos.
Além da nova organização hierárquica, a versão 2 dos cgroups também introduziu **várias outras mudanças e melhorias**, como suporte a **novos controladores de recursos**, melhor suporte para aplicativos legados e melhor desempenho.
Em geral, os cgroups **versão 2 oferecem mais recursos e melhor desempenho** do que a versão 1, mas esta última ainda pode ser usada em determinados cenários em que a compatibilidade com sistemas mais antigos é uma preocupação.
Você pode listar os cgroups v1 e v2 para qualquer processo olhando para o arquivo cgroup em /proc/\<pid>. Você pode começar olhando para os cgroups do seu shell com este comando:
Não se preocupe se a **saída for significativamente mais curta** no seu sistema; isso apenas significa que você provavelmente **tem apenas cgroups v2**. Cada linha de saída aqui começa com um número e é um cgroup diferente. Aqui estão algumas dicas sobre como lê-lo:
* **Os números 2-12 são para cgroups v1**. Os **controladores** para esses são listados ao lado do número.
* **O número 1** também é para a **versão 1**, mas não tem um controlador. Este cgroup é apenas para **fins de gerenciamento** (neste caso, o systemd o configurou).
* A última linha, **número 0**, é para **cgroups v2**. Nenhum controlador é visível aqui. Em um sistema que não possui cgroups v1, esta será a única linha de saída.
* **Os nomes são hierárquicos e parecem partes de caminhos de arquivo**. Você pode ver neste exemplo que alguns dos cgroups são nomeados /user.slice e outros /user.slice/user-1000.slice/session-2.scope.
* **Nomes sob user.slice** que incluem sessão são sessões de login, atribuídas pelo systemd. Você os verá ao olhar para os cgroups de um shell. Os **cgroups** para seus **serviços do sistema** estarão **sob system.slice**.
Os cgroups são normalmente **acessados através do sistema de arquivos**. Isso é em contraste com a interface de chamada do sistema Unix tradicional para interagir com o kernel.\
Para explorar a configuração do cgroup de um shell, você pode olhar no arquivo `/proc/self/cgroup` para encontrar o cgroup do shell e, em seguida, navegar até o diretório `/sys/fs/cgroup` (ou `/sys/fs/cgroup/unified`) e procurar um **diretório com o mesmo nome do cgroup**. Mudar para este diretório e olhar ao redor permitirá que você veja as várias **configurações e informações de uso de recursos para o cgroup**.
Entre os muitos arquivos que podem estar aqui, **os principais arquivos de interface do cgroup começam com `cgroup`**. Comece olhando para `cgroup.procs` (usar cat está bem), que lista os processos no cgroup. Um arquivo semelhante, `cgroup.threads`, também inclui threads.
A maioria dos cgroups usados para shells tem esses dois controladores, que podem controlar a **quantidade de memória** usada e o **número total de processos no cgroup**. Para interagir com um controlador, procure os **arquivos que correspondem ao prefixo do controlador**. Por exemplo, se você quiser ver o número de threads em execução no cgroup, consulte pids.current:
Um valor de **max significa que este cgroup não tem limite específico**, mas porque os cgroups são hierárquicos, um cgroup de volta na cadeia de subdiretórios pode limitá-lo.
Assim é como as mudanças em cgroups funcionam. Por exemplo, se você quiser **limitar o número máximo de PIDs de um cgroup** (para, digamos, 3.000 PIDs), faça o seguinte:
**Criar cgroups é mais complicado**. Tecnicamente, é tão fácil quanto criar um subdiretório em algum lugar na árvore de cgroups; quando você faz isso, o kernel cria automaticamente os arquivos de interface. Se um cgroup não tiver processos, você pode remover o cgroup com rmdir mesmo com os arquivos de interface presentes. O que pode te confundir são as regras que regem os cgroups, incluindo:
* Você só pode colocar **processos em cgroups de nível externo ("folha")**. Por exemplo, se você tiver cgroups chamados /my-cgroup e /my-cgroup/my-subgroup, você não pode colocar processos em /my-cgroup, mas /my-cgroup/my-subgroup está ok. (Uma exceção é se os cgroups não tiverem controladores, mas não vamos nos aprofundar nisso.)
* Um cgroup **não pode ter um controlador que não esteja em seu cgroup pai**.
* Você deve **especificar explicitamente controladores para cgroups filhos**. Você faz isso através do arquivo `cgroup.subtree_control`; por exemplo, se você quiser que um cgroup filho tenha os controladores cpu e pids, escreva +cpu +pids neste arquivo.
Uma exceção a essas regras é o **cgroup raiz** encontrado na parte inferior da hierarquia. Você pode **colocar processos neste cgroup**. Uma razão pela qual você pode querer fazer isso é para desanexar um processo do controle do systemd.
Como este é o uso acumulado da CPU ao longo de toda a vida útil do cgroup, você pode ver como um serviço consome tempo do processador mesmo se ele gerar muitos subprocessos que eventualmente terminam.