Skip to content
Manoel E. S. S. edited this page Sep 1, 2026 · 1 revision

Implementação e Foco Filosófico

1. Princípio do projeto

O CPU Reader parte de uma ideia simples:

Observar o sistema diretamente, compreender os dados e construir a abstração somente quando ela for necessária.

O projeto não busca esconder o funcionamento do sistema operacional atrás de uma camada excessivamente complexa. Pelo contrário, procura manter visível a relação entre o programa, o kernel Linux e o hardware.

A implementação utiliza interfaces como /proc e sysfs para acessar informações disponibilizadas pelo sistema.

A biblioteca funciona, portanto, como uma ponte:

Hardware
   ↓
Kernel Linux
   ↓
/proc + sysfs
   ↓
CPU Reader
   ↓
API C
   ↓
Aplicação

2. C como instrumento

A escolha da linguagem C não é apenas uma decisão técnica.

C permite trabalhar em uma camada suficientemente próxima do sistema para observar aspectos que linguagens de mais alto nível normalmente abstraem.

No CPU Reader isso envolve diretamente:

  • ponteiros;
  • estruturas;
  • alocação e liberação de memória;
  • arquivos;
  • parsing;
  • tipos numéricos;
  • representação de dados;
  • chamadas relacionadas ao ambiente do sistema;
  • organização modular;
  • comportamento dependente de arquitetura.

A linguagem passa a ser parte do próprio objeto de estudo.

O objetivo é compreender o que acontece entre a informação fornecida pelo sistema e a informação finalmente apresentada ao usuário.


3. Menos abstração, mais compreensão

Uma das decisões fundamentais é evitar abstrações que não tragam benefício real.

Em vez de construir uma grande camada intermediária, o projeto procura manter o caminho dos dados relativamente curto:

/proc/stat
    ↓
leitura
    ↓
parsing
    ↓
cálculo
    ↓
float
    ↓
API

Isso torna o código mais fácil de estudar, testar e modificar.

A abstração existe, mas possui uma função clara: organizar o acesso aos dados sem ocultar desnecessariamente sua origem.


4. O sistema operacional como fonte de dados

O CPU Reader não tenta descobrir informações do hardware de maneira independente quando o sistema operacional já fornece essas informações.

O Linux expõe diversas métricas através de interfaces padronizadas ou específicas do ambiente, incluindo /proc/cpuinfo, /proc/stat, /proc/loadavg e interfaces do sysfs.

O projeto aproveita essas interfaces como uma forma de observar o estado do sistema.

Isso produz uma relação conceitual importante:

CPU Reader
não "inventa" os dados.

CPU Reader
observa → interpreta → organiza → disponibiliza.

5. Implementação incremental

A biblioteca deve evoluir a partir de componentes pequenos.

A organização atual já separa responsabilidades entre módulos como:

src/cpu.c
     ↓
fachada da biblioteca

src/cpu_info.c
     ↓
informações da CPU

src/cpu_usage.c
     ↓
uso da CPU

Além disso, existem componentes separados para monitor, testes e documentação.

Essa estrutura permite adicionar novas capacidades sem transformar um único arquivo em um ponto central excessivamente complexo.


6. Dados antes da interface

Uma preocupação importante do projeto é separar coleta de apresentação.

A biblioteca não deve depender do monitor de terminal.

O fluxo ideal é:

                  CPU Reader
                      │
               coleta os dados
                      │
                      ↓
                  API C
                 /      \
                /        \
               ↓          ↓
          aplicação     monitor

O cpu-monitor é apenas um consumidor da biblioteca.

Isso significa que a mesma API pode futuramente ser utilizada por:

  • ferramentas CLI;
  • aplicações gráficas;
  • serviços;
  • scripts através de bindings;
  • sistemas embarcados;
  • ferramentas de diagnóstico;
  • outras bibliotecas.

7. O conceito de observação

Existe também um aspecto filosófico no próprio nome CPU Reader.

A biblioteca não pretende controlar a CPU.

Ela pretende ler.

Essa distinção é importante.

O projeto começa com uma postura de observação:

não modificar
não interferir
não controlar

observar
medir
interpretar

A ferramenta procura transformar o estado do sistema em informação compreensível sem alterar o objeto observado.

Isso torna o projeto especialmente adequado para estudo de sistemas, diagnóstico e monitoramento.


8. Medir não é apenas ler

Uma das partes mais interessantes da implementação é o cálculo de utilização da CPU.

O percentual de uso não é simplesmente encontrado como um número pronto em /proc/stat.

É necessário observar a evolução dos contadores:

t0
│
├── estado inicial
│
│     intervalo
│
t1
│
└── estado seguinte

A partir da diferença entre as leituras, a biblioteca calcula a utilização.

Conceitualmente:

estado anterior
       ↓
     Δ tempo
       ↓
estado atual
       ↓
   interpretação
       ↓
   utilização %

Essa característica representa uma ideia central da engenharia de sistemas:

Uma métrica pode ser uma propriedade calculada a partir da evolução do estado, e não um valor diretamente armazenado.


9. Precisão e simplicidade

O projeto procura evitar uma falsa escolha entre simplicidade e rigor.

Código simples não significa código superficial.

Uma implementação pequena pode exigir decisões importantes sobre:

  • overflow;
  • tipos numéricos;
  • precisão;
  • valores inválidos;
  • arquivos ausentes;
  • sensores inexistentes;
  • diferenças entre arquiteturas;
  • gerenciamento de memória.

O objetivo é alcançar uma implementação simples na interface e rigorosa internamente.


10. Falhas fazem parte do sistema

O CPU Reader assume que o ambiente pode falhar.

Um sensor pode não existir.

Um arquivo pode não estar disponível.

Uma interface pode mudar.

Um valor pode estar malformado.

Uma arquitetura pode não fornecer determinada informação.

Por isso, a biblioteca possui mecanismos explícitos de erro, incluindo códigos para argumentos inválidos, falhas de abertura, parsing, memória e funcionalidades não suportadas.

A filosofia é:

informação indisponível
        ≠
programa quebrado

Uma biblioteca de sistemas deve saber distinguir uma falha da própria biblioteca de uma característica inexistente no ambiente onde está sendo executada.


11. Portabilidade como consequência

A portabilidade não deve ser tratada apenas como adicionar vários #ifdef.

O objetivo é separar aquilo que é conceitualmente comum daquilo que é específico de uma plataforma.

Por exemplo:

              API
               │
        conceito abstrato
               │
       ┌───────┴───────┐
       ↓               ↓
     Linux           outra plataforma
       │               │
    /proc/sysfs     backend específico

A implementação atual já possui fallback em C para determinadas operações que utilizam assembly inline em x86_64 com GCC ou Clang.

Isso aponta para uma filosofia maior:

O comportamento da biblioteca deve ser definido pela API; a implementação pode variar conforme a máquina.


12. Assembly como camada de experimentação

O uso de assembly inline no projeto também possui uma função experimental.

Em x86_64, GCC e Clang podem utilizar assembly inline para determinadas operações de soma dos contadores de utilização, enquanto outras plataformas utilizam o fallback em C.

Isso permite explorar uma questão fundamental da programação de sistemas:

Algoritmo
   ↓
C
   ↓
compilador
   ↓
assembly
   ↓
CPU

O programador pode estudar como uma operação aparentemente simples em C pode chegar ao nível das instruções executadas pelo processador.


13. Biblioteca como laboratório

O CPU Reader pode ser entendido como um pequeno laboratório.

Cada componente abre uma porta para uma área diferente:

/proc
  → kernel e processos

sysfs
  → dispositivos e hardware

C
  → memória e representação

Make
  → construção do software

Testes
  → verificação

Assembly
  → arquitetura

ncurses
  → interface de terminal

Por isso, o valor do projeto não está somente no resultado final.

Está também no conhecimento produzido durante sua construção.


14. Filosofia de engenharia

O desenvolvimento deve seguir alguns princípios:

Clareza
   ↓
Modularidade
   ↓
Testabilidade
   ↓
Robustez
   ↓
Portabilidade
   ↓
Extensibilidade

Novas funcionalidades devem ser adicionadas somente quando houver uma necessidade clara ou um objetivo técnico/educacional definido.

A complexidade deve ser introduzida de maneira deliberada.


15. Filosofia de software

O CPU Reader pode ser resumido por cinco ideias:

Observar

Ler o estado fornecido pelo sistema.

Compreender

Interpretar corretamente os dados antes de transformá-los em métricas.

Abstrair

Criar uma API simples sem esconder a natureza do problema.

Verificar

Testar entradas, resultados e situações de falha.

Evoluir

Adicionar capacidades sem abandonar a simplicidade estrutural.


16. Direção conceitual

O objetivo final não é criar uma biblioteca gigantesca.

É construir uma biblioteca pequena o suficiente para ser compreendida e suficientemente bem projetada para crescer.

                CPU Reader

             pequeno núcleo
                   │
        ┌──────────┼──────────┐
        ↓          ↓          ↓
     estudo      uso real   extensão
        │          │          │
        └──────────┼──────────┘
                   ↓
          programação de sistemas

O projeto deve permanecer próximo do problema original:

ler o sistema, compreender o que está sendo lido e transformar essa informação em uma interface útil para outros programas.

Essa é a principal orientação filosófica do CPU Reader: simplicidade não como ausência de engenharia, mas como resultado de engenharia bem direcionada.