Entendendo o Subsistema Térmico do Linux usando PocketBeagle
Introdução
O monitoramento térmico em sistemas embarcados é necessário para garantir a estabilidade operacional e a integridade do hardware. Processadores sob carga de trabalho intensa geram calor. O controle desse calor evita a degradação do chip e travamentos do sistema.
Para promover essa proteção, o Linux possui um subsistema térmico que padroniza a leitura de sensores de temperatura internos do SoC e gerencia as ações de resfriamento correspondentes.
Este artigo apresenta o funcionamento do subsistema térmico do Linux, abordando a arquitetura do kernel e suas interfaces expostas no espaço de usuário, com a realização de testes de atuação manual. Como resultado prático, foi desenvolvido um utilitário de monitoramento em linguagem C para validar a leitura contínua desses dados.
Ambiente de Estudo: Hardware e Software Utilizados
Para fundamentar as análises práticas deste estudo térmico, um ambiente composto pelos seguintes recursos de hardware e ferramentas de software foi configurado:
1. Especificações de Hardware
- Placa de Desenvolvimento: PocketBeagle, uma plataforma compacta para o estudo de sistemas operacionais embarcados.
- Based on Octavo Systems OSD3358-SM
- Texas Instruments AM3358 ARM Cortex-A8 32 bits 1GHz.
- RAM: 512MB DDR3.
2. Infraestrutura de Software
- Sistema Operacional: Imagem oficial do Debian GNU/Linux estável e otimizada para arquiteturas ARMv7 da BeagleBoard.
- Kernel Linux: Kernel ativo com suporte nativo ao subsistema térmico e ao driver do sensor interno da CPU.
- Conexão de Depuração: Acesso via SSH através do IP padrão de rede emulada sobre cabo USB (192.168.7.2 ou 192.168.6.2).
O Subsistema Thermal no Linux: Conceitos de Arquitetura
O subsistema de gerenciamento térmico do Linux fornece uma interface genérica para interagir com sensores de hardware (conhecidos como Thermal Zones) e atuadores de resfriamento (conhecidos como Cooling Devices). Essa interface é exposta de forma transparente no espaço de usuário (user space) através do sistema de arquivos virtual /sys/class/thermal/.
A arquitetura desse subsistema se apoia em quatro conceitos-chave:
- Thermal Zones (Zonas Térmicas): Representam os pontos de medição física de temperatura no hardware (por exemplo, sensores internos no núcleo da CPU, na GPU ou na proximidade do chip de gerenciamento de energia – PMIC).
- Cooling Devices (Dispositivos de Resfriamento): Abstraem qualquer componente capaz de mitigar o calor do sistema. Podem ser ativos, como ventoinhas e coolers cuja velocidade pode ser regulada de 0 a 100%, ou passivos, como o estrangulamento de frequência (conhecidos como CPU frequency throttling) que reduz dinamicamente a frequência de operação do processador para resfriá-lo).
- Trip Points (Pontos de Disparo): Limites térmicos de temperatura configurados que acionam comportamentos preventivos ou de emergência. Cada trip point possui um limite de temperatura em miligraus Celsius e um tipo:
- critical: O sistema corre risco iminente de dano físico e executa um desligamento de emergência (graceful shutdown).
- hot: Temperatura muito elevada; o espaço de usuário ou o kernel é alertado para tomar ações preventivas.
- passive: Ativa o resfriamento passivo, limitando o consumo de energia ou a frequência do processador.
- active: Ativa coolers ou dissipadores de calor ativos conectados.
- Governors (Governadores Térmicos): Algoritmos internos do kernel que controlam a associação entre as zonas térmicas e os dispositivos de resfriamento com base nos trip points atingidos.
Explorando a Camada Térmica via Terminal (Sysfs)
No Linux, a interface do sistema de arquivos virtual /sys/ expõe para o espaço de usuário as estruturas internas do kernel. Essa é uma interface para compreender como o sistema gerencia recursos de hardware.
Abaixo está o mapa hierárquico das interfaces expostas no caminho /sys/class/thermal/ analisadas neste estudo:
/sys/class/thermal/
├── thermal_zone[0-N]/ <-- Zonas de sensores de hardware
│ ├── type <-- Identificação do sensor (ex: CPU_thermal)
│ ├── temp <-- Temperatura atual em miligraus Celsius
│ ├── mode <-- Estado do sensor: 'enabled' ou 'disabled'
│ ├── policy <-- Governador térmico ativo (ex: step_wise)
│ ├── available_policies <-- Governadores suportados pelo kernel
│ ├── trip_point_X_temp <-- Limite térmico do gatilho X em m°C
│ └── trip_point_X_type <-- Tipo do gatilho X (passive, active, critical)
└── cooling_device[0-N]/ <-- Atuadores de dissipação térmica
├── type <-- Tipo do atuador (ex: Processor ou Fan)
├── max_state <-- Nível máximo de resfriamento/throttling suportado
└── cur_state <-- Nível atual do atuador (leitura/escrita)
Abaixo, são apresentados testes no terminal para compreender o comportamento do subsistema, com a interpretação e atuação sobre esses atributos térmicos.
1. Varrendo as Interfaces de Sensor e Atuação
Para listar de forma estruturada as pastas virtuais e arquivos de zonas térmicas e dispositivos de resfriamento do sistema:
find /sys/class/thermal/ -maxdepth 2
Saída observada no terminal:
/sys/class/thermal/
/sys/class/thermal/thermal_zone0
/sys/class/thermal/thermal_zone0/temp
/sys/class/thermal/thermal_zone0/type
/sys/class/thermal/thermal_zone0/trip_point_0_temp
/sys/class/thermal/thermal_zone0/trip_point_0_type
/sys/class/thermal/thermal_zone0/trip_point_1_temp
/sys/class/thermal/thermal_zone0/trip_point_1_type
/sys/class/thermal/cooling_device0
/sys/class/thermal/cooling_device0/type
/sys/class/thermal/cooling_device0/cur_state
/sys/class/thermal/cooling_device0/max_state
2. Lendo o Tipo do Sensor Térmico
Para ler a identificação do sensor físico registrado na zona térmica zero, leia o arquivo type:
$ cat /sys/class/thermal/thermal_zone0/type
Saída real obtida:
CPU_thermal
A saída indica que o sensor monitora a temperatura diretamente do núcleo do processador.
3. Leitura e Escalonamento Matemático de Temperatura
O arquivo temp expõe a temperatura em miligraus Celsius:
# Leitura do valor bruto exposto pelo sensor
$ cat /sys/class/thermal/thermal_zone0/temp
Saída obtida:
39500
A saída significa que o chip está operando à 39,5 °C.
4. Consultando Trip Points Ativos de Fábrica
Os trip points determinam os limites térmicos suportados pelo hardware antes da execução de ações preventivas. Abaixo são inspecionados os dois pontos de disparo configurados na plataforma:
- Trip Point 0 (Alerta Passivo – Throttling):
$ cat /sys/class/thermal/thermal_zone0/trip_point_0_temp
$ cat /sys/class/thermal/thermal_zone0/trip_point_0_type
Saída obtida:
90000
passive
A saída indica que a 90°C o kernel iniciará a redução automática de clock da CPU.
- Trip Point 1 (Desligamento de Emergência – Critical):
$ cat /sys/class/thermal/thermal_zone0/trip_point_1_temp
$ cat /sys/class/thermal/thermal_zone0/trip_point_1_type
Saída obtida:
110000
critical
A saída indica que se o processador atingir 110°C, o Linux executará um desligamento forçado instantâneo para salvar o circuito integrado.
5. Atuação Manual e Cooling Devices
Inspecionando os mecanismos de controle de resfriamento integrados ao SoC. O cooling_device0 controla o estado do driver de frequência da CPU (cpufreq).
- max_state: Indica quantos níveis de atenuação de frequência são suportados.
- cur_state: Indica o nível de mitigação térmica ativo (0 significa operação normal em velocidade máxima).
cat /sys/class/thermal/cooling_device0/type
cat /sys/class/thermal/cooling_device0/cur_state
cat /sys/class/thermal/cooling_device0/max_state
Saída obtida:
Processor
0
3
Com privilégios de superusuário (root), é possível ativar manualmente estados de redução de frequência para simular o comportamento térmico preventivo e validar a atuação do governador do kernel.
Para observar o impacto causado por este comando no sistema, monitora-se a frequência atual de operação da CPU (em kHz) localizada no subsistema cpufreq antes e após a atuação:
Passo A: Consultar a frequência atual do processador da PocketBeagle
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq
Saída obtida:
1000000
A saída indica que a CPU está operando em sua frequência máxima de 1,0 GHz.
Passo B: Ativar o estrangulamento térmico manual (Throttling máximo – Nível 3)
# Força o nível máximo de estrangulamento da CPU (nível 3)
echo 3 | sudo tee /sys/class/thermal/cooling_device0/cur_state
Consultar a frequência atual do processador da PocketBeagle
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq
Saída obtida:
300000
A saída indica que o processador imediatamente derrubou seu clock para 300 MHz para mitigar a dissipação térmica emulado.
Passo C: Reverter a CPU para o estado normal de velocidade máxima
echo 0 | sudo tee /sys/class/thermal/cooling_device0/cur_state
Gerenciando Permissões no Sysfs
A leitura das temperaturas e metadados dentro de /sys/class/thermal é acessível de forma pública para qualquer usuário comum do sistema de arquivos, o que viabiliza o monitoramento simples sem permissões elevadas.
No entanto, a modificação de limites térmicos (escrever em trip_point_*_temp) ou a ativação manual de estados de resfriamento (escrever em arquivos do cooling_device) requer privilégios de superusuário (root).
Caso se deseje executar rotinas de monitoramento contínuo sem a necessidade de executá-las via sudo, uma alternativa no Linux consiste em definir uma regra do gerenciador de dispositivos udev (criando um arquivo em /etc/udev/rules.d/99-thermal.rules) para conceder permissão de escrita ao grupo de usuários padrão:
SUBSYSTEM=="thermal", RUN+="/bin/chmod -R g+w /sys/class/thermal/%k"
Criando uma Zona Térmica Emulada para Testes
Em sensores físicos reais do kernel (como o sensor de silício da CPU), o arquivo /sys/class/thermal/thermal_zoneX/temp é exposto exclusivamente como leitura (read-only) para preservar a integridade do sistema. O sistema operacional apenas reporta o sinal elétrico recebido do hardware e restringe alterações arbitrárias do espaço de usuário.
Essa limitação física exige uma estratégia alternativa de validação: os testes dos limites de trip points e a verificação dos estados de alerta e shutdown de emergência devem ocorrer sem expor o chip a temperaturas de 90 °C ou 110 °C.
A criação de uma Zona Térmica Emulada (Mock) atende a essa necessidade de segurança. Ao estruturar um diretório virtual sob /tmp/mock_thermal/ que espelha as propriedades do sysfs, torna-se possível escrever valores arbitrários de temperatura no arquivo emulado temp. Essa abordagem viabiliza a simulação de aquecimento em tempo real e permite verificar o comportamento do monitor em C ao cruzar as barreiras térmicas de 60 °C (Passive) e 80 °C (Critical) de forma controlada.
Como a Emulação é Implementada em C
Para garantir a reprodução direta do estudo térmico, isolamos a lógica de emulação em um arquivo dedicado (thermal_mock.c). Em alternativa à geração manual de arquivos, o utilitário automatiza a criação do ambiente virtual gerando nós de arquivos estruturados sob /tmp.
O trecho de código abaixo apresenta a estrutura funcional dessa rotina, focando na escrita dos parâmetros de temperatura e trip points em formato texto e inteiro compatíveis com o sysfs:
// https://github.com/alvenan/thermal-monitor-c/blob/main/thermal_mock.c#L5
// Estrutura essencial para criação do nó térmico simulado
void setup_mock_environment(const char *base_path, const char *zone_name,
const char *type_val, int temp_val,
int trip_0_val, const char *trip_0_type) {
char path[128], file_path[128];
// 1. Cria o diretório da zona térmica simulada (ex: /tmp/mock_thermal/thermal_zone0)
snprintf(path, sizeof(path), "%s/%s", base_path, zone_name);
make_dir(path);
// 2. Cria e escreve o nó 'type' (identificação do sensor)
snprintf(file_path, sizeof(file_path), "%s/type", path);
write_sysfs_string(file_path, type_val);
// 3. Cria e escreve o nó 'temp' (temperatura atual simulada em m°C)
snprintf(file_path, sizeof(file_path), "%s/temp", path);
write_sysfs_int(file_path, temp_val);
// 4. Cria e escreve o limite de disparo e o tipo do Trip Point 0
snprintf(file_path, sizeof(file_path), "%s/trip_point_0_temp", path);
write_sysfs_int(file_path, trip_0_val);
snprintf(file_path, sizeof(file_path), "%s/trip_point_0_type", path);
write_sysfs_string(file_path, trip_0_type);
}
- Mapeamento de Tipos de Dados: As funções auxiliares write_sysfs_string e write_sysfs_int escrevem texto diretamente nos arquivos virtuais do sistema. Isso simula a forma como drivers reais expõem inteiros (como temp em miligraus) e textos (como type do sensor).
- Controle Dinâmico de Testes: Uma vez criada essa estrutura, qualquer terminal do usuário comum pode simular variações térmicas apenas atualizando o arquivo criado. Por exemplo, executar echo 65000 > /tmp/mock_thermal/thermal_zone0/temp altera a temperatura do sensor para 65,0 °C em tempo real, fornecendo um ambiente dinâmico para validar como os governadores e utilitários tratam o estado de emergência sem o estresse térmico no silício real.
Implementação Programática em C
Como resultado da consolidação dos conceitos térmicos e de acesso à API sysfs do kernel, foi desenvolvido um utilitário em C. O objetivo deste programa é realizar a validação programática, automatizando as leituras periódicas e monitorando a barreira dos trip points de maneira dinâmica.
Abaixo, são apresentados os trechos do código-fonte e o papel desempenhado por suas rotinas de extração de dados no sysfs do kernel.
1. Representação de Dados: Estrutura `ThermalZone`
Para que o monitor gerencie múltiplos sensores e diferencie áreas reais de simuladas, as propriedades descobertas foram agrupadas na seguinte estrutura:
// https://github.com/alvenan/thermal-monitor-c/blob/main/thermal_monitor.h#L9
typedef struct {
char name[64]; // Tipo de sensor lido do arquivo type (ex: CPU_thermal)
char path[256];// Caminho absoluto da pasta (ex: /sys/class/thermal/thermal_zone0)
int is_mock; // Flag lógico (1 para simulado, 0 para hardware real)
} ThermalZone;
2. Varredura e Descoberta Dinâmica de Sensores
Para mapear dinamicamente os sensores do sistema com caminhos flexíveis no código, utilizam-se as APIs POSIX de diretório para buscar pastas iniciadas pelo padrão thermal_zone:
// https://github.com/alvenan/thermal-monitor-c/blob/main/thermal_funcs.c#L59C1-L60C24
// Trecho essencial de varredura de diretórios usando dirent.h
int discover_thermal_zones(ThermalZone *zones, int max_zones, char *search_path) {
int zone_count = 0;
DIR *dir = opendir(search_path);
if (dir) {
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
if (strncmp(entry->d_name, "thermal_zone", 12) == 0) {
// Um diretório de zona térmica foi localizado!
// Adiciona o caminho completo ao vetor de estruturas zones[]
}
}
closedir(dir);
}
- Descoberta Transparente: Esta lógica garante a portabilidade do estudo. O programa listará e monitorará automaticamente todas as zonas térmicas disponíveis, funcionando sem alterações tanto em uma placa embarcada (com uma zona) quanto em um servidor robusto de múltiplos núcleos (com várias zonas registradas).
3. Apresentação das Configurações Térmicas do Kernel
O utilitário carrega e exibe de forma estruturada os limites de segurança configurados pelo kernel. O trecho abaixo demonstra como os trip points são extraídos abrindo-se de maneira recursiva os caminhos dos gatilhos:
// https://github.com/alvenan/thermal-monitor-c/blob/main/thermal_funcs.c#L83C1-L83C63
// Lógica programática para ler os limites dos trip points
void print_thermal_zones(ThermalZone *zones, int zone_count) {
...
for (int t = 0; t < 5; t++) {
// Monta o caminho ex: /sys/.../thermal_zone0/trip_point_0_temp
snprintf(t_temp_path, sizeof(t_temp_path), "%s/trip_point_%d_temp", zone_path, t);
snprintf(t_type_path, sizeof(t_type_path), "%s/trip_point_%d_type", zone_path, t);
int trip_temp = read_sysfs_int(t_temp_path);
read_sysfs_string(t_type_path, t_type, sizeof(t_type));
// Converte os miligraus retornados pelo kernel de volta a graus Celsius convencionais
printf(" ↳ Trip Point %d: %s a %.1f °C\n", t, t_type, trip_temp / 1000.0);
}
4. Tomada de Decisão: Avaliando os Gatilhos Térmicos
A função de tomada de decisão é invocada a cada intervalo de amostragem. Ela compara a temperatura bruta em miligraus Celsius (temp_raw) contra os limites de segurança física lidos e simula o acionamento de ações preventivas:
// https://github.com/alvenan/thermal-monitor-c/blob/main/thermal_funcs.c#L108
// Lógica de avaliação de limites e tratamento de emergência
void check_and_handle_trips(int temp_raw, int trip_0_temp, int trip_1_temp) {
if (temp_raw >= trip_1_temp && trip_1_temp != -1) {
// Temperatura estourou o limite crítico de segurança!
printf(" -> [CRÍTICO] Temperatura de %.1f °C excedida! Executando SHUTDOWN!\n", trip_1_temp / 1000.0);
} else if (temp_raw >= trip_0_temp && trip_0_temp != -1) {
// Temperatura ultrapassou o limite de alerta preventivo!
printf(" -> [ALERTA] Temperatura de %.1f °C excedida! Ativando Resfriamento Passivo (Throttling)!\n", trip_0_temp / 1000.0);
} else {
printf(" -> [NORMAL]\n");
}
}
5. Loop de Amostragem e Pivoteamento Automático (`main`)
A função principal orquestra a lógica de monitoramento. Ela busca sensores físicos de hardware reais e, em caso de ausência de zonas ativas, aciona a inicialização do ambiente de simulação parametricamente:
// https://github.com/alvenan/thermal-monitor-c/blob/main/thermal_monitor.c#L7
int main() {
char search_path[128] = REAL_THERMAL_PATH;
ThermalZone zones[10];
// Tenta descobrir zonas térmicas ativas no sistema
int zone_count = discover_thermal_zones(zones, 10, search_path);
if (zone_count == 0) {
printf("[!] Nenhuma zona física encontrada. Inicializando simulação...\n");
setup_mock_environment(MOCK_BASE_PATH, "thermal_zone0", "CPU_Mock", 42000, 60000, "passive");
// Ajusta o caminho de varredura para apontar para a nossa pasta emulada
strncpy(search_path, MOCK_BASE_PATH, sizeof(search_path));
zone_count = discover_thermal_zones(zones, 10, search_path);
}
// Inicia o loop periódico de amostragem térmica a cada segundo
// ...
}
Validação Prática do Estudo
Esta seção apresenta os cenários reais observados durante a execução do programa em C, validando os conceitos de monitoramento térmico investigados neste artigo.
Cenário 1: Validando em Sensores Físicos Reais (Computador Host)
Computadores pessoais baseados em arquiteturas Intel ou AMD que executam Linux possuem sensores de temperatura ativos por padrão, expostos diretamente no subsistema sysfs.
É possível utilizar o mesmo programa de monitoramento compilando-o e executando-o na máquina host Linux para validar o subsistema. O utilitário detecta dinamicamente as zonas térmicas reais da CPU (como TCPU ou x86_pkg_temp), mapeia seus respectivos trip points de segurança física definidos de fábrica e inicia a leitura real da temperatura em tempo real.
#### Saída da Execução no Host:
========================================================
PROGRAMA DE DEMONSTRAÇÃO: LINUX THERMAL MONITOR
========================================================
[*] Zonas térmicas mapeadas:
[0] TCPU (REAL) - Path: /sys/class/thermal/thermal_zone2
↳ Trip Point 0: critical a 110.0 °C
↳ Trip Point 1: hot a 110.0 °C
↳ Trip Point 2: passive a 110.0 °C
[1] INT3400 Thermal (REAL) - Path: /sys/class/thermal/thermal_zone0
[2] iwlwifi_1 (REAL) - Path: /sys/class/thermal/thermal_zone7
↳ Trip Point 0: passive a -274.0 °C
[3] x86_pkg_temp (REAL) - Path: /sys/class/thermal/thermal_zone8
↳ Trip Point 0: passive a -274.0 °C
[*] Iniciando loop de monitoramento térmico...
[Tempo: 0s] [TCPU] Temperatura: 26.85 °C -> [NORMAL]
[Tempo: 1s] [TCPU] Temperatura: 26.85 °C -> [NORMAL]
[Tempo: 2s] [TCPU] Temperatura: 27.00 °C -> [NORMAL]
[Tempo: 3s] [TCPU] Temperatura: 26.85 °C -> [NORMAL]
Cenário 2: Validando no Fallback do Ambiente Emulado
Em plataformas com um kernel sem Device Tree de sensores ativo, o programa identifica a ausência de zonas físicas e inicializa o mock usando os argumentos fornecidos para simular os limites térmicos investigados no estudo interativo.
#### Saída da Programa:
========================================================
PROGRAMA DE DEMONSTRAÇÃO: LINUX THERMAL MONITOR
========================================================
[!] Nenhuma zona térmica física ativa encontrada em /sys/class/thermal.
[!] Inicializando ambiente térmico emulado para testes em /tmp/mock_thermal...
[*] Zonas térmicas mapeadas:
[0] CPU_Thermal_Mock (EMULADO) - Path: /tmp/mock_thermal/thermal_zone0
↳ Trip Point 0: passive a 60.0 °C
↳ Trip Point 1: critical a 80.0 °C
[*] Iniciando loop de monitoramento térmico...
[*] Pressione Ctrl+C para encerrar.
[Tempo: 0s] [CPU_Thermal_Mock] Temperatura: 45.50 °C -> [NORMAL]
[Tempo: 1s] [CPU_Thermal_Mock] Temperatura: 49.00 °C -> [NORMAL]
[Tempo: 2s] [CPU_Thermal_Mock] Temperatura: 52.50 °C -> [NORMAL]
[Tempo: 3s] [CPU_Thermal_Mock] Temperatura: 56.00 °C -> [NORMAL]
[Tempo: 4s] [CPU_Thermal_Mock] Temperatura: 59.50 °C -> [NORMAL]
[Tempo: 5s] [CPU_Thermal_Mock] Temperatura: 63.00 °C -> [ALERTA] Limite de 60.0 °C excedido! Ativando Resfriamento Passivo (Throttling)!
Compilação e Execução
Para compilar e executar o utilitário em C resultante do estudo térmico, siga os passos abaixo:
1. Obtendo o código-fonte e compilando
É possível clonar o repositório do GitHub diretamente na placa:
$ git clone https://github.com/alvenan/thermal-monitor-c
$ cd thermal-monitor-c
$ make
3. Rodando o monitor térmico
Execute o binário final:
$ ./thermal_monitor
Conclusão
O subsistema térmico do Linux provê uma padronização de interface que ocultar detalhes de hardware específicos, viabilizando o monitoramento e o controle de segurança a nível de espaço de usuário. Este estudo na placa PocketBeagle permitiu investigar a árvore de diretórios do /sys/class/thermal, realizar atuações manuais de redução de frequência e criar uma automação na linguagem C. Essa consolidação de conceitos demonstra como é possível proteger processadores contra sobrecarga térmica em sistemas embarcados.
Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.





