Fundamentos de SO e Ambiente Linux

Objetivos de Aprendizagem

Ao final deste módulo, o aluno será capaz de:

  • Explicar o papel do kernel e a diferença entre kernel space e user space
  • Descrever o ciclo de uma chamada de sistema (syscall)
  • Identificar as principais distribuições Linux e suas diferenças
  • Navegar pela hierarquia de diretórios FHS com fluência
  • Usar o shell Bash para executar comandos essenciais
  • Entender o que é um processo e como o kernel o gerencia
  • Ler e interpretar as páginas de manual (man)
  • Executar os dois laboratórios guiados com autonomia

Pré-Requisitos

Conhecimentos prévios

  • Noções básicas de computação (o que é CPU, memória, disco)
  • Experiência mínima com qualquer sistema operacional (Windows / macOS)
  • Conceito de arquivo e pasta/diretório

Ambiente necessário

  • VM com Ubuntu 22.04 LTS ou Debian 12 instalada
  • Acesso a um terminal (TTY ou emulador)
  • Usuário não-root criado e senha definida
  • Conexão com a internet (opcional, para apt)
Compatibilidade com o laboratório (container LXD não privilegiado)
  • Não funciona: modprobe (o container não carrega módulos), ls -l /dev/sda e fdisk -l (não há discos), dmesg (Operation not permitted).
  • Cuidado ao interpretar: lsmod lista os módulos do host, em modo leitura — não são "do seu sistema". lsblk mostra apenas um sr0 fantasma.
  • Instalar antes: sudo apt install build-essential — necessário para compilar o le_arquivo.c do Bloco 2.
  • Funciona normalmente: /proc, strace, uname, man/apropos, ps, pipes, redirecionamentos e os dois laboratórios.
Bloco 1 — O que é um Sistema Operacional

Conceitos-chave

Um Sistema Operacional (SO) é o software que atua como intermediário entre o hardware e os programas do usuário. Ele fornece abstrações (arquivos, processos, sockets) e garante isolamento, segurança e compartilhamento de recursos entre múltiplos programas simultâneos.

Segundo a LPI (Linux Essentials, Topic 4 — The Linux Operating System), o termo "Linux" refere-se tecnicamente apenas ao kernel. O que instalamos e usamos no dia a dia é uma distribuição: o kernel Linux somado a milhares de programas do projeto GNU, bibliotecas, um sistema de init, um gerenciador de pacotes e utilitários. Por isso a Free Software Foundation defende o nome GNU/Linux para o sistema completo.

As duas grandes responsabilidades do kernel

Todo SO existe para resolver dois problemas fundamentais que aparecem quando vários programas disputam um mesmo computador:

  • Abstração — transformar hardware complicado e heterogêneo em interfaces simples e uniformes. O programa lê um "arquivo" sem saber se ele está num SSD NVMe, num HD SATA ou num pen-drive USB; abre um "socket" sem conhecer o driver da placa de rede.
  • Arbitragem — decidir quem usa a CPU, a memória e os dispositivos, quando e por quanto tempo, impedindo que um programa interfira nos outros (isolamento) ou monopolize os recursos (escalonamento justo).

Abstrações fundamentais oferecidas pelo SO

Processo— um programa em execução, com sua própria memória virtual e contexto
Arquivo— fluxo de bytes nomeado; no Unix "tudo é arquivo" (discos, terminais, sockets)
Memória virtual— cada processo enxerga um espaço de endereços contínuo e privado
Sistema de arquivos— hierarquia de diretórios sobre blocos de disco brutos
Socket / pipe— canais de comunicação entre processos e pela rede
Usuário / permissão— identidade (UID/GID) que define o que cada um pode acessar

O princípio "tudo é um arquivo"

Uma das ideias centrais herdadas do Unix é que a maioria dos recursos é exposta como arquivos, manipuláveis com as mesmas syscalls (open, read, write, close). Isso dá uma coerência enorme ao sistema:

O mesmo verbo (ler/escrever) serve para tudo
# Um terminal é um arquivo — escrever nele mostra texto na tela de outro TTY
$ tty
/dev/pts/0
$ echo "olá" > /dev/pts/0     # aparece no próprio terminal

# Um disco é um arquivo de bloco
$ ls -l /dev/sda
brw-rw---- 1 root disk 8, 0 Jul 20 10:00 /dev/sda

# /dev/null descarta tudo; /dev/zero produz zeros infinitos
$ echo "isto some" > /dev/null
$ head -c 8 /dev/zero | xxd
00000000: 0000 0000 0000 0000                      ........

Multitarefa e multiusuário

Diferente de sistemas antigos, o Linux é multitarefa preemptiva (o kernel pode interromper um processo a qualquer momento para dar a vez a outro) e multiusuário (vários usuários com identidades e permissões distintas podem trabalhar simultaneamente). O escalonador (scheduler) cria a ilusão de que tudo roda ao mesmo tempo, alternando processos na CPU em fatias de milissegundos.

Monolítico vs. microkernel

O Linux é um kernel monolítico modular: drivers, sistema de arquivos e pilha de rede rodam todos em kernel space (desempenho alto), mas podem ser carregados e descarregados em tempo real como módulos. Isso o diferencia de microkernels (como o Minix), que mantêm o mínimo em kernel space e empurram serviços para user space (maior isolamento, menor desempenho).

Ver e gerenciar módulos do kernel
$ lsmod | head -5           # módulos carregados
Module                  Size  Used by
ext4                  980992  1
xhci_pci               24576  0
snd_hda_intel         57344  3

$ modinfo ext4 | head -3    # metadados de um módulo
# modprobe -r módulo        # descarrega (necessita root)
Gerenciamento de processos Gerenciamento de memória Sistema de arquivos Gerenciamento de I/O Segurança e permissões Comunicação entre processos (IPC)

Linha do tempo do Linux

# Marcos históricos relevantes
1969  → Unix (Bell Labs — Thompson, Ritchie)
1983  → Projeto GNU (Richard Stallman)
1991  → Linux Kernel 0.01 (Linus Torvalds)
1992  → GPL + GNU + Linux = GNU/Linux
1993  → Slackware (1ª distro popular)
1994  → Red Hat Linux
2004  → Ubuntu (Canonical)
Hoje  → +600 distribuições ativas
LPI Reference: Linux Essentials — Topic 1: The Linux Community and a Career in Open Source; LPIC-1 Objective 101.1 — Determine and configure hardware settings.
Bloco 2 — Kernel, User Space e Syscalls

Arquitetura em camadas

USER SPACE
Aplicações: bash, vim, Python, nginx, Firefox…
Bibliotecas: glibc, libpthread…
↕   System Call Interface   ↕
(open, read, write, fork, exec, mmap…)
KERNEL SPACE
Scheduler · Memory Manager · VFS · Drivers · Network Stack
HARDWARE — CPU · RAM · Disco · NIC · GPU…

Modos de operação da CPU

A separação entre kernel e aplicações não é apenas uma convenção de software: ela é imposta pelo hardware. A CPU possui pelo menos dois níveis de privilégio (rings ou protection rings):

  • Ring 0 (Kernel Mode / modo supervisor) — acesso irrestrito a hardware, a todas as instruções da CPU e a toda a memória física; código do kernel roda aqui.
  • Ring 3 (User Mode) — acesso restrito; instruções privilegiadas (acessar diretamente disco, configurar a MMU, mascarar interrupções) são proibidas. Todo código de aplicação roda aqui.

Se um programa em Ring 3 tenta executar uma instrução privilegiada ou acessar memória que não é sua, a CPU dispara uma exceção (fault) e o kernel assume o controle — tipicamente enviando o sinal SIGSEGV (o clássico "Segmentation fault"). É esse mecanismo que garante o isolamento: um bug ou um programa malicioso não consegue derrubar o sistema inteiro nem espionar a memória de outro processo.

Por que precisamos de syscalls?

Como o código de usuário não pode tocar o hardware diretamente, ele precisa pedir ao kernel que faça a operação em seu nome. Esse pedido é a chamada de sistema (system call) — a única porta de entrada controlada do user space para o kernel space. Abrir um arquivo, criar um processo, enviar um pacote de rede, alocar memória: tudo passa por uma syscall.

Na prática, o programador raramente invoca a syscall "crua". A glibc (biblioteca C padrão do GNU) oferece funções wrapper com o mesmo nome (open(), read(), fork()…) que preparam os argumentos, disparam a instrução syscall e traduzem erros para a variável global errno. A LPI (LPIC-1 101.1) trata justamente dessa fronteira entre aplicação, biblioteca e kernel.

Ciclo de uma Syscall

Programa em user space chama a função open("/etc/passwd", O_RDONLY) da glibc
glibc coloca o número da syscall em rax (2 = open no x86-64) e os argumentos em rdi, rsi, rdx…
glibc executa a instrução syscall; a CPU muda para Ring 0 e salta para o entry point do kernel
Kernel valida os parâmetros (o ponteiro é válido? o usuário tem permissão?), executa a operação e coloca o retorno em rax
CPU volta para Ring 3; a glibc converte retornos negativos em errno e devolve o descritor de arquivo ao programa

A syscall vista do código C

O exemplo abaixo abre um arquivo e lê seus primeiros bytes usando apenas syscalls (via wrappers da glibc) — sem fopen/printf de alto nível. Note o padrão universal do Unix: retorno < 0 indica erro, e o motivo fica em errno.

le_arquivo.c — syscalls open / read / write / close
#include <fcntl.h>      // open, O_RDONLY
#include <unistd.h>     // read, write, close
#include <stdio.h>      // perror

int main(void) {
    int fd = open("/etc/hostname", O_RDONLY);   // syscall open()
    if (fd < 0) { perror("open"); return 1; }    // erro -> errno

    char buf[128];
    ssize_t n = read(fd, buf, sizeof buf);       // syscall read()
    if (n < 0) { perror("read"); return 1; }

    write(1, buf, n);   // syscall write() no fd 1 = stdout
    close(fd);          // syscall close()
    return 0;
}
Compilar, executar e observar as syscalls reais
$ gcc -Wall le_arquivo.c -o le_arquivo
$ ./le_arquivo
ubuntu-lab

# strace mostra EXATAMENTE as syscalls que o programa fez
$ strace -e trace=open,openat,read,write,close ./le_arquivo
openat(AT_FDCWD, "/etc/hostname", O_RDONLY) = 3
read(3, "ubuntu-lab\n", 128)                = 11
write(1, "ubuntu-lab\n", 11)               = 11
close(3)                                    = 0
Descritores de arquivo (file descriptors): todo processo começa com três FDs abertos — 0 = stdin, 1 = stdout, 2 = stderr. Por isso write(1, …) escreve na tela. Novos open() recebem o menor FD livre (por isso o arquivo acima virou o descritor 3).

Categorias de syscalls (Linux tem ~350)

Arquivos— open, read, write, close, lseek, stat, unlink
Processos— fork, execve, wait4, exit, getpid, clone
Memória— mmap, munmap, brk, mprotect
Sinais— kill, sigaction, rt_sigprocmask
Rede— socket, bind, listen, accept, connect, sendto
Tempo / info— clock_gettime, uname, gettimeofday
Consultar o manual de uma syscall (seção 2 do man)
$ man 2 read        # documentação da syscall read()
$ man 2 syscalls    # lista todas as syscalls do Linux
$ man 2 open        # flags: O_RDONLY, O_CREAT, O_APPEND…
Demonstração ao vivo — strace
$ strace -e trace=openat ls /etc 2>&1 | head -20
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/etc", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
Ver informações do kernel em execução
$ uname -r
6.8.0-51-generic

$ uname -a
Linux hostname 6.8.0-51-generic #52-Ubuntu SMP Wed Jan 15 2025 x86_64 GNU/Linux

$ cat /proc/version
Linux version 6.8.0-51-generic (buildd@...) (gcc version 13.3.0)
LPI Reference: LPIC-1 Objective 101.1 — Determine and configure hardware settings; Linux Essentials Topic 4: The Linux Operating System.
Bloco 3 — Shell, Terminal e Bash

O que é o Shell?

O shell é um interpretador de comandos — um programa em user space que lê linhas de texto, interpreta-as e instrui o kernel (via syscalls) a executar as ações desejadas. O Bash (Bourne Again SHell) é o shell padrão na grande maioria das distribuições Linux.

Shells mais comuns

bash (padrão) zsh (macOS default) fish (user-friendly) dash (POSIX, scripts) ksh (Korn Shell)

Anatomia de um comando

# comando  [opções]  [argumentos]
ls      -lah      /var/log

# ls   → nome do programa (executável em /bin/ls)
# -lah → flags: long format, all files, human-readable sizes
# /var/log → argumento: diretório alvo

Quando você tecla Enter, o Bash faz muito mais do que "rodar o programa". Ele percorre um pipeline de etapas: expansões (curinga, variáveis, aritmética), tokenização, resolve se a palavra é um builtin, alias, função ou executável no PATH, e então usa as syscalls fork() + execve() para criar o processo. Entender essas etapas é o que separa "decorar comandos" de realmente dominar a linha de comando (LPI, Linux Essentials Topic 3; LPIC-1 103.1).

Builtin, alias ou executável?

Nem todo comando é um arquivo no disco. Alguns são builtins — implementados dentro do próprio Bash (como cd, que precisa ser builtin para mudar o diretório do próprio shell). Use type para descobrir a natureza de qualquer comando:

$ type cd echo ls ll
cd is a shell builtin
echo is a shell builtin
ls is aliased to `ls --color=auto'
ll is aliased to `ls -alF'

$ type -a echo     # mostra TODAS as formas de echo (builtin + /usr/bin/echo)
echo is a shell builtin
echo is /usr/bin/echo

Variáveis: do shell e de ambiente

Uma variável de shell existe só na sessão atual. Ao usar export, ela vira uma variável de ambiente, herdada por todos os processos-filho. Não use espaços ao redor do =.

$ nome="Marco"          # variável de shell (local)
$ echo "Olá, $nome"
Olá, Marco

$ export EDITOR=vim     # vira variável de ambiente
$ env | grep EDITOR     # aparece no ambiente
EDITOR=vim

# Variáveis de ambiente importantes
$ echo $HOME $USER $SHELL $PATH
/home/marco marco /usr/bin/bash /usr/local/bin:/usr/bin:/bin
O PATH: ao digitar ls, o shell procura um executável chamado ls percorrendo os diretórios de $PATH na ordem, e usa o primeiro que encontrar. Por isso which comando mostra qual arquivo será executado.

Expansões do shell

Antes de executar, o Bash reescreve a linha de comando. As expansões mais usadas:

# Curinga (globbing): * ? [ ]
$ ls *.txt              # todos que terminam em .txt
$ ls arquivo?.log       # ? = exatamente 1 caractere
$ ls foto[1-3].png      # foto1, foto2 ou foto3

# Expansão de chaves (brace) — gera sequências
$ echo arq_{a,b,c}.txt
arq_a.txt arq_b.txt arq_c.txt
$ mkdir -p projeto/{src,bin,docs}   # cria 3 subpastas de uma vez

# Til (~) = home; e substituição de comando $( )
$ echo ~                /home/marco
$ echo "Hoje é $(date +%A)"
Hoje é Monday

# Expansão aritmética $(( ))
$ echo $((2 + 3 * 4))   14

Quoting: aspas simples × duplas × escape

Controlar quando o shell expande é essencial. Aspas duplas preservam espaços mas ainda expandem $variáveis; aspas simples preservam tudo literalmente.

$ preco=50
$ echo "Custa $preco reais"     Custa 50 reais
$ echo 'Custa $preco reais'     Custa $preco reais
$ echo "Aspas: \" e cifrão: \$"  Aspas: " e cifrão: $

Comandos essenciais — prática imediata

Identidade e localização
$ whoami            # nome do usuário atual
marcos

$ id               # UID, GID e grupos
uid=1000(marcos) gid=1000(marcos) groups=1000(marcos),27(sudo)

$ pwd              # diretório atual
/home/marcos

$ hostname         # nome da máquina
ubuntu-lab
Navegação
$ cd /             # vai para a raiz
$ ls               # lista o conteúdo
bin  boot  dev  etc  home  lib  media  mnt  opt  proc  root  run  srv  sys  tmp  usr  var

$ cd ~             # vai para o home do usuário
$ ls -lah          # lista com detalhes
Ajuda e documentação
$ man ls           # manual completo
$ ls --help        # ajuda rápida
$ type ls          # é builtin, alias ou executável?
ls is /usr/bin/ls

$ which bash       # localiza o executável
/usr/bin/bash

Redirecionamentos e pipes — o coração do Unix

A filosofia Unix diz: "faça programas pequenos que façam uma coisa bem, e que trabalhem juntos". Isso só é possível porque cada processo tem três canais padrão — os descritores 0 (stdin), 1 (stdout) e 2 (stderr) vistos no Bloco 2 — e o shell permite redirecioná-los para arquivos ou conectá-los entre processos com pipes.

# >  redireciona stdout para arquivo (SOBRESCREVE)
$ ls /etc > lista.txt

# >> ANEXA ao final do arquivo (não apaga)
$ date >> lista.txt

# <  lê stdin de um arquivo
$ wc -l < lista.txt
142

# 2>  redireciona apenas stderr (erros)
$ ls /naoexiste 2> erros.txt
# 2>/dev/null → descarta mensagens de erro
$ find / -name "*.conf" 2>/dev/null | head

# &>  redireciona stdout E stderr juntos para o mesmo lugar
$ comando &> saida_completa.log
Pipes ( | ) — a saída de um vira a entrada do outro
# Encadeie filtros para construir consultas poderosas
$ cat /etc/passwd | grep "/bin/bash" | wc -l
3   # quantos usuários têm o bash como shell de login

# Os 5 comandos mais usados no seu histórico
$ history | awk '{print $2}' | sort | uniq -c | sort -rn | head -5
   87 git
   64 ls
   41 cd
   30 vim
   22 cat
Diferença crucial: > conecta um processo a um arquivo; o pipe | conecta dois processos diretamente na memória, sem passar por disco — muito mais rápido e a base da composição de comandos.
LPI Reference: Linux Essentials Topic 3: The Power of the Command Line; LPIC-1 Objective 103.1 — Work on the command line; 103.4 — Streams, pipes and redirects.
Bloco 4 — Distribuições Linux e o FHS

O que é (e o que não é) uma distribuição

Como visto no Bloco 1, o kernel Linux sozinho não faz nada de útil para o usuário final. Uma distribuição (distro) é a montagem de um sistema completo e instalável: kernel + utilitários GNU + bibliotecas + sistema de init + gerenciador de pacotes + instalador + política de atualizações. A LPI (Linux Essentials Topic 1) destaca que a principal diferença prática entre distros para o administrador está em três eixos:

  • Gerenciador de pacotes e formato (.deb via apt/dpkg × .rpm via dnf/rpm).
  • Modelo de lançamento: fixed release (versões estáveis periódicas, ex.: Debian, Ubuntu LTS) × rolling release (atualização contínua, ex.: Arch).
  • Filosofia e público: estabilidade corporativa (RHEL), facilidade (Ubuntu), minimalismo/containers (Alpine), controle total (Arch).

Principais famílias de distribuições

Debian / Ubuntu
Gerenciador apt · pacotes .deb · foco em estabilidade e uso em desktop/servidor
Red Hat / Fedora / Rocky
Gerenciador dnf/yum · pacotes .rpm · padrão em ambiente corporativo
openSUSE
Gerenciador zypper · pacotes .rpm · ferramenta YaST para administração
Arch Linux
Gerenciador pacman · rolling release · alta personalização, curva íngreme
Alpine Linux
Gerenciador apk · ~5 MB base · padrão em containers Docker
Slackware
A mais antiga ainda mantida · sem gerenciador de dependências automático · purismo Unix

Gerenciadores de pacotes — comandos equivalentes

Saber "traduzir" a mesma operação entre famílias é uma habilidade cobrada na LPIC-1 (Objectives 102.4 e 102.5). Todos resolvem o mesmo problema — instalar software e suas dependências — com sintaxes diferentes:

Operação Debian / Ubuntu (apt) Red Hat / Fedora (dnf) Arch (pacman)
Atualizar índiceapt updatednf check-updatepacman -Sy
Instalar pacoteapt install nginxdnf install nginxpacman -S nginx
Remover pacoteapt remove nginxdnf remove nginxpacman -R nginx
Atualizar tudoapt upgradednf upgradepacman -Su
Buscar pacoteapt search termodnf search termopacman -Ss termo
Que pacote tem o arquivo?dpkg -S /caminhorpm -qf /caminhopacman -Qo /caminho
Identificar qual distribuição você está usando
# O arquivo padronizado /etc/os-release funciona em QUALQUER distro moderna
$ cat /etc/os-release
PRETTY_NAME="Ubuntu 22.04.4 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
ID=ubuntu
ID_LIKE=debian

$ lsb_release -a 2>/dev/null   # alternativa (nem sempre instalada)

Hierarquia do Sistema de Arquivos (FHS)

O Filesystem Hierarchy Standard é uma especificação que define onde cada tipo de arquivo deve ficar, garantindo que um administrador saiba encontrar as coisas em qualquer distribuição. Duas ideias organizam a hierarquia (LPIC-1 104.7):

  • Estático × variável: /usr e /bin quase não mudam (podem ser read-only); /var e /tmp mudam o tempo todo.
  • Compartilhável × local: /usr pode ser compartilhado por rede entre máquinas; /etc e /boot são específicos de cada host.
/— raiz; tudo começa aqui
/bin— binários essenciais para todos os usuários (ls, cp, mv…)
/sbin— binários de administração do sistema (fdisk, ifconfig…)
/etc— arquivos de configuração do sistema e serviços
/home— diretórios pessoais dos usuários
/root— home do superusuário root
/lib— bibliotecas compartilhadas (.so) usadas por /bin e /sbin
/usr— programas instalados pelo sistema (multi-usuário, read-only)
/usr/bin— maioria dos executáveis de usuário
/usr/local— software compilado/instalado manualmente pelo admin
/var— dados variáveis: logs (/var/log), spool, cache
/tmp— arquivos temporários (apagados no boot)
/proc— pseudo-FS com info do kernel e processos em tempo real
/sys— pseudo-FS com informações de hardware e drivers (sysfs)
/dev— arquivos de dispositivo (disco, terminal, zero, null…)
/mnt— ponto de montagem temporário convencional
/media— mídia removível montada automaticamente (pen-drive, CD)
/opt— software de terceiros auto-contido (Oracle, VSCode…)
/boot— arquivos de inicialização: kernel, initrd, grub
O "/usr merge": em distros modernas /bin, /sbin e /lib são apenas links simbólicos para /usr/bin, /usr/sbin e /usr/lib. Confirme com ls -ld /bin — você verá algo como /bin -> usr/bin. A separação histórica existia porque /usr podia estar em outro disco montado depois do boot.

Caminho absoluto × relativo

Um caminho absoluto começa em / (a raiz) e é sempre o mesmo, independente de onde você esteja. Um caminho relativo parte do diretório atual. . é o diretório atual, .. é o pai e ~ é o home.

$ cd /var/log
$ cat syslog          # relativo → /var/log/syslog
$ cat /etc/hostname   # absoluto → sempre o mesmo
$ cd ../..            # sobe dois níveis → /
$ cd -                # volta ao diretório anterior
Explorar o FHS no terminal
$ ls -ld /bin /sbin /lib   # veja os symlinks do /usr merge
$ ls -lah /
$ du -sh /var/log/*  2>/dev/null | sort -rh | head -10
$ file /dev/null /dev/zero /dev/random
/dev/null:   character special (1/3)
/dev/zero:   character special (1/5)
/dev/random: character special (1/8)
LPI Reference: Linux Essentials Topic 4.2 — Understanding Computer Hardware; LPIC-1 Objective 104.7 — Find system files and place files in the correct location (FHS).
Bloco 5 — O Processo e sua Gestão pelo Kernel

O que é, afinal, um processo?

No Bloco 1 vimos o processo como uma das grandes abstrações do SO. Agora vamos abrir a caixa. Um processo é um programa em execução: não é o arquivo no disco (isso é o programa), mas a instância viva dele — código carregado na memória, mais todo o estado que o kernel mantém para acompanhá-lo. O mesmo programa (/usr/bin/vim) pode originar dezenas de processos simultâneos e independentes.

A imagem de um processo na memória

Cada processo enxerga seu próprio espaço de endereços virtual (Bloco 2), organizado em regiões bem definidas:

text (código)— as instruções da CPU; read-only e compartilhável entre processos do mesmo binário
data / bss— variáveis globais/estáticas (inicializadas e não inicializadas)
heap— memória dinâmica (malloc/brk/mmap); cresce "para cima"
stack— variáveis locais e quadros de chamada de função; cresce "para baixo"

Além da memória, o kernel guarda para cada processo um bloco de controle (o PCB, no Linux a estrutura task_struct) com sua identidade e contexto:

PID — identificador único PPID — PID do processo pai UID/GID — dono e grupo tabela de descritores (0,1,2…) estado + prioridade (nice) registradores salvos (contexto)

Como um processo nasce: fork() + execve()

No Unix, um processo não é criado do nada — ele é sempre clonado de um pai. O par de syscalls fork() + execve() é o coração do modelo:

fork() — o processo pai se duplica; o kernel cria um filho com uma cópia do espaço de endereços (via copy-on-write, sem copiar de fato até haver escrita). O filho recebe um novo PID.
fork() retorna duas vezes: 0 no filho e o PID do filho no pai — é assim que cada um sabe quem é.
O filho geralmente chama execve("/bin/ls", …), que substitui sua imagem de memória pelo novo programa, mantendo o mesmo PID e os descritores herdados.
O pai chama wait()/waitpid() para aguardar o término do filho e coletar seu código de saída (reaping).
É esse o mecanismo do shell: quando você digita ls, o Bash faz fork() de si mesmo e o filho faz execve() do ls. Por isso o filho herda o stdout (fd 1) do terminal — e por isso o resultado aparece na sua tela. O PID 1 (systemd/init) é o ancestral de todos: veja com pstree.

Estados de um processo

O kernel move cada processo entre estados conforme ele disputa a CPU ou espera por I/O. A coluna STAT de ps aux mostra a letra do estado:

CódigoEstadoSignificado
RRunning / RunnableExecutando na CPU ou na fila pronto para executar
SSleeping (interruptível)Aguardando um evento (teclado, rede, timer); pode ser acordado por sinal
DUninterruptible sleepBloqueado em I/O de disco; não pode ser interrompido (nem por kill -9)
TStoppedSuspenso por Ctrl+Z ou sinal SIGSTOP
ZZombieJá terminou, mas o pai ainda não coletou seu código de saída

Um zumbi (Z) é normal e efêmero — some assim que o pai faz wait(). Vira problema só quando o pai esquece de coletar e acumula zumbis. Um órfão (pai morreu antes do filho) é adotado pelo PID 1, que faz o wait() por ele.

Como o kernel decide quem roda: o escalonador

Há sempre mais processos prontos (R) do que núcleos de CPU. O escalonador (scheduler, no Linux o CFS — Completely Fair Scheduler) reparte a CPU em fatias de tempo de milissegundos e alterna os processos tão rápido que criam a ilusão de simultaneidade (multitarefa preemptiva, Bloco 1). Trocar de processo exige um context switch: salvar os registradores do atual e carregar os do próximo — barato, mas não gratuito.

A prioridade influencia quanto tempo cada um recebe. O valor nice vai de -20 (mais prioritário) a +19 (mais "gentil", cede a CPU). Usuários comuns só conseguem aumentar o nice (baixar a prioridade); baixá-lo exige root.

Observar e controlar processos e prioridades
$ ps -o pid,ppid,stat,ni,comm -p $$   # dados do próprio shell ($$ = PID atual)
    PID    PPID STAT  NI COMMAND
   2841    2833 Ss     0 bash

# Iniciar um processo com prioridade reduzida
$ nice -n 10 sleep 100 &
$ renice -n 15 -p 4567   # mudar a prioridade de um processo já rodando

# O kernel expõe TUDO sobre um processo em /proc/PID
$ cat /proc/$$/status | grep -E "State|Pid|PPid|Uid"
State:  S (sleeping)
Pid:    2841
PPid:   2833
Uid:    1000    1000    1000    1000

$ ls /proc/$$/fd     # descritores de arquivo abertos pelo shell
0  1  2  255

Sinais: conversando com processos

O kernel entrega sinais — interrupções assíncronas — para pedir que um processo pare, recarregue ou termine. Você os dispara com Ctrl+C, Ctrl+Z ou o comando kill (que, apesar do nome, apenas envia um sinal):

SIGINT (2) — Ctrl+C, interromper SIGTSTP (20) — Ctrl+Z, suspender SIGTERM (15) — término educado (padrão) SIGKILL (9) — mata na hora, não capturável SIGHUP (1) — recarregar config
LPI Reference: LPIC-1 Objective 103.5 — Create, monitor and kill processes; 103.6 — Modify process execution priorities.
Bloco 6 — Páginas de Manual e Documentação

Por que aprender a ler o man vale mais que decorar comandos

Ninguém memoriza todas as flags de todos os comandos — nem precisa. Um administrador proficiente sabe encontrar a resposta na documentação que já vem instalada na própria máquina, offline. A porta de entrada é o man (manual): cada comando, syscall, arquivo de configuração e função de biblioteca tem sua página. Saber navegá-las é objetivo explícito da LPI (LPIC-1 103.1).

As seções do manual

O manual é dividido em seções numeradas. Isso importa porque o mesmo nome pode existir em várias — por exemplo, existe o comando printf (seção 1) e a função C printf (seção 3):

SeçãoConteúdoExemplo
1Comandos de usuárioman 1 ls
2Chamadas de sistema (syscalls)man 2 read
3Funções de biblioteca (glibc)man 3 printf
4Arquivos de dispositivo (/dev)man 4 null
5Formatos de arquivo e configman 5 passwd
6Jogos e diversõesman 6 fortune
7Miscelânea (convenções, protocolos)man 7 signal
8Comandos de administração (root)man 8 mount
Note a diferença: man passwd abre a seção 1 (o comando que troca a senha); man 5 passwd abre a seção 5 (o formato do arquivo /etc/passwd). Quando há ambiguidade, o número da seção é obrigatório.

Anatomia de uma página de manual

Toda página segue a mesma estrutura padronizada — aprenda a "saltar" direto para a parte que interessa:

NAME— nome do comando e resumo de uma linha
SYNOPSIS— forma de uso; [ ] = opcional, ... = repetível
DESCRIPTION— explicação detalhada do comportamento
OPTIONS— cada flag e o que faz
EXAMPLES— usos práticos (nem toda página tem)
EXIT STATUS— códigos de retorno (0 = sucesso)
SEE ALSO— páginas relacionadas — o fio para continuar aprendendo

Navegando dentro do man

O man usa o paginador less. As teclas essenciais para não ficar perdido:

TeclaAção
Espaço / bAvançar / voltar uma tela
Rolar linha a linha
/padrão EnterBuscar "padrão" para frente
n / NPróxima / anterior ocorrência da busca
g / GIr ao início / fim da página
qSair

Quando você não sabe o nome do comando

O maior valor do sistema de manuais aparece quando você sabe o que quer fazer, mas não qual comando usar. É aí que entram a busca por palavra-chave e o resumo:

Descobrir comandos e consultar rápido
# Buscar por palavra-chave em TODAS as descrições (NAME) das páginas
$ apropos "copy files"      # idêntico a: man -k "copy files"
cp (1)               - copy files and directories
install (1)          - copy files and set attributes
scp (1)              - secure copy (remote file copy program)

# Resumo de uma linha de um comando (a seção NAME)
$ whatis ls             # idêntico a: man -f ls
ls (1)               - list directory contents

# Em quais seções existe uma página com esse nome?
$ man -f printf
printf (1)           - format and print data
printf (3)           - formatted output conversion

Além do man: outras fontes na máquina

$ ls --help            # ajuda rápida embutida no próprio programa (builtins e GNU)
$ help cd              # ajuda de um BUILTIN do Bash (cd não tem man próprio)
$ info coreutils       # manual hipertexto do GNU, mais extenso que o man
$ ls /usr/share/doc/   # READMEs, changelogs e exemplos dos pacotes instalados
Regra prática: use --help para lembrar rápido uma flag, man para entender um comando a fundo, apropos quando não sabe o nome, e sempre siga o SEE ALSO — é como um comando "puxa" o próximo.
LPI Reference: LPIC-1 Objective 103.1 — Work on the command line (uso de man, info, /usr/share/doc).

Laboratórios Guiados

01

Exploração do Sistema de Arquivos e do /proc

Navegação FHS, leitura de arquivos do kernel e coleta de informações do sistema

40 min Individual Sem root necessário

Objetivos do Lab 1

  • Navegar pela hierarquia FHS com cd e ls
  • Ler informações do kernel via /proc
  • Entender o que são arquivos de dispositivo em /dev
  • Usar find para localizar arquivos

Parte A — Explorando a raiz e /proc

Comandos e resultados esperados
# 1. Ver informações do processador
$ cat /proc/cpuinfo | grep "model name" | head -1
model name  : Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz

# 2. Ver informações de memória RAM
$ cat /proc/meminfo | head -5
MemTotal:       16384000 kB
MemFree:         8192000 kB
MemAvailable:   10240000 kB
Buffers:          512000 kB
Cached:          2048000 kB

# 3. Ver tempo ligado (uptime do kernel)
$ cat /proc/uptime
3600.12 7120.45
# 1o campo: segundos ligado | 2o: soma do tempo idle de todos os CPUs

# 4. Ver sistemas de arquivos suportados pelo kernel
$ cat /proc/filesystems
nodev   sysfs
nodev   tmpfs
nodev   bdev
        ext3
        ext4
        xfs
nodev   proc

# 5. Informações do PID 1 (init/systemd)
$ cat /proc/1/cmdline | tr '\0' ' '
/sbin/init splash

$ ls -la /proc/1/
# Explore: fd/, maps, status, environ…

Parte B — Dispositivos e Filesystem

# 6. Ver dispositivos de bloco montados
$ lsblk
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
sda      8:0    0    20G  0 disk
├─sda1   8:1    0   512M  0 part /boot/efi
├─sda2   8:2    0     1G  0 part /boot
└─sda3   8:3    0  18.5G  0 part /

# 7. Ver sistemas de arquivos montados
$ df -hT
Filesystem     Type      Size  Used Avail Use% Mounted on
/dev/sda3      ext4       19G  5.2G   13G  29% /
tmpfs          tmpfs     7.9G     0  7.9G   0% /dev/shm

# 8. Procurar arquivos de configuração modificados recentemente
$ find /etc -name "*.conf" -mtime -7 -ls 2>/dev/null | head -10

# 9. Contar linhas em /var/log/syslog
$ wc -l /var/log/syslog 2>/dev/null || wc -l /var/log/kern.log
8472 /var/log/syslog

# 10. Ver últimas 5 linhas do log do sistema
$ tail -5 /var/log/syslog
Jun  7 10:00:01 ubuntu CRON[1234]: (root) CMD (command -v debian-sa1 > /dev/null && debian-sa1 1 1)

Parte C — Redirecionamentos e pipes

# 11. Redirecionar saída para arquivo
$ uname -a > /tmp/sysinfo.txt
$ cat /proc/cpuinfo >> /tmp/sysinfo.txt
$ wc -l /tmp/sysinfo.txt

# 12. Filtrar com grep e contar
$ grep -c "processor" /proc/cpuinfo
8    # número de CPUs lógicas

# 13. Pipeline: listar arquivos maiores em /usr/bin
$ ls -lhS /usr/bin | head -10
Ponto de verificação: O aluno deve conseguir responder: Quantos processadores lógicos o sistema tem? Quanta RAM total disponível? Qual filesystem está em /? Quando o sistema foi iniciado?
02

Processos, Permissões e Scripts Básicos

Gerenciamento de processos, modelo de permissões Unix e criação do primeiro script

40 min Individual Requer sudo em alguns passos

Parte A — Processos

# 1. Listar todos os processos
$ ps aux | head -15
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.1 169460 13520 ?        Ss   09:00   0:02 /sbin/init splash
root           2  0.0  0.0      0     0 ?        S    09:00   0:00 [kthreadd]

# 2. Árvore de processos
$ pstree -p | head -20

# 3. Ver processos em tempo real
$ top      # pressione 'q' para sair
$ htop     # versão melhorada (instalar se necessário)

# 4. Executar processo em background
$ sleep 300 &
[1] 4567

$ jobs
[1]+  Running    sleep 300 &

$ ps -p 4567
  PID TTY          TIME CMD
 4567 pts/0    00:00:00 sleep

# 5. Matar o processo
$ kill 4567
[1]+  Terminated   sleep 300

# 6. Ver sinais disponíveis
$ kill -l | head -5
 1) SIGHUP   2) SIGINT   3) SIGQUIT  4) SIGILL   5) SIGTRAP

Parte B — Modelo de Permissões Unix

# 7. Criar arquivo e ver permissões
$ touch /tmp/teste.txt
$ ls -l /tmp/teste.txt
-rw-r--r-- 1 marcos marcos 0 Jun  7 10:15 /tmp/teste.txt

#  _ rw- r-- r--
#  │  │   │   └── outros:   leitura
#  │  │   └────── grupo:    leitura
#  │  └────────── dono:     leitura + escrita
#  └───────────── tipo: '-' arquivo, 'd' dir, 'l' symlink

# 8. Chmod em notação octal e simbólica
$ chmod 755 /tmp/teste.txt
$ ls -l /tmp/teste.txt
-rwxr-xr-x 1 marcos marcos 0 Jun  7 10:15 /tmp/teste.txt

$ chmod u-x,o-r /tmp/teste.txt
-rw-r-x--- ...

# 9. Criar diretório e ver herança
$ mkdir -p /tmp/lab2/subdir
$ ls -la /tmp/lab2/

# 10. Verificar identidade de um arquivo
$ stat /tmp/teste.txt
  File: /tmp/teste.txt
  Size: 0          Blocks: 0       IO Block: 4096  regular empty file
Device: 8,3     Inode: 131073     Links: 1
Access: (0640/-rw-r-----)  Uid: (1000/marcos)  Gid: (1000/marcos)

Parte C — Primeiro Script Bash

# 11. Criar o script
$ cat > ~/sysreport.sh <<'EOF'
#!/usr/bin/env bash
echo "=== Relatório do Sistema ==="
echo "Data/Hora : $(date)"
echo "Hostname  : $(hostname)"
echo "Usuário   : $(whoami)"
echo "Kernel    : $(uname -r)"
echo "Uptime    : $(uptime -p)"
echo ""
echo "--- CPU ---"
grep "model name" /proc/cpuinfo | head -1 | cut -d: -f2
echo ""
echo "--- Memória ---"
free -h
echo ""
echo "--- Disco ---"
df -h /
EOF

# 12. Tornar executável e rodar
$ chmod +x ~/sysreport.sh
$ ~/sysreport.sh
=== Relatório do Sistema ===
Data/Hora : Sat Jun  7 10:20:00 UTC 2026
Hostname  : ubuntu-lab
Usuário   : marcos
Kernel    : 6.8.0-51-generic
Uptime    : up 1 hour, 20 minutes

--- CPU ---
 Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz

--- Memória ---
               total        used        free
Mem:            16Gi        5.2Gi       8.1Gi
Swap:          2.0Gi          0B        2.0Gi

--- Disco ---
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda3        19G  5.2G   13G  29% /
Ponto de verificação: O script deve executar sem erros, mostrar todas as seções e o aluno deve conseguir explicar cada linha do código.

Desafio Prático Individual

⚡ Desafio — "Investigador de Sistema"

Duração: 25 minutos  |  Formato: Individual  |  Entregável: Arquivo /tmp/relatorio_individual.txt

Missão

Você recebeu acesso a um servidor Linux desconhecido. Produza um relatório de reconhecimento do sistema respondendo às perguntas abaixo usando apenas a linha de comando. Todos os comandos devem ser registrados no arquivo de relatório.

Perguntas a responder

# Crie o arquivo de relatório
$ exec > >(tee /tmp/relatorio_individual.txt) 2>&1
$ echo "Aluno: [Seu Nome] — $(date)"

# Q1: Qual versão exata do kernel está em uso?
$ uname -r

# Q2: Quantos usuários existem no sistema (linhas em /etc/passwd)?
$ wc -l /etc/passwd

# Q3: Qual é o shell padrão do usuário atual?
$ echo $SHELL

# Q4: Quais shells estão disponíveis no sistema?
$ cat /etc/shells

# Q5: Qual é o maior arquivo em /usr/bin? (nome e tamanho)
$ ls -lhS /usr/bin | head -3

# Q6: Quantos processos estão rodando agora?
$ ps aux | wc -l

# Q7: Qual processo consome mais CPU no momento?
$ ps aux --sort=-%cpu | head -3

# Q8: Qual é o inode do arquivo /etc/passwd?
$ stat /etc/passwd | grep Inode

# Q9: Crie um arquivo em /tmp com seu nome e exiba suas permissões em octal
$ touch /tmp/prova.txt
$ stat -c "%a %n" /tmp/prova.txt

# Q10: Escreva uma linha de comando ONE-LINER que mostre
#      apenas o nome dos 5 processos que mais consomem memória
$ ps aux --sort=-%mem | awk 'NR>1{print $11}' | head -5

Bônus (para alunos avançados)

# Crie um script que monitora o uso de CPU a cada 2 segundos por 10 vezes
$ for i in $(seq 1 10); do
    echo -n "$(date +%T) CPU: "
    top -bn1 | grep "Cpu(s)" | awk '{print $2}' | tr -d '%us,'
    sleep 2
  done

Referência Rápida de Comandos

Navegação

pwd    → diretório atual
cd     → mudar diretório
ls -la → listar com detalhes
tree   → árvore visual
find   → buscar arquivos

Arquivos

cat / less / more → ler
head / tail       → início/fim
cp / mv / rm      → copiar/mover/apagar
touch             → criar/atualizar timestamp
stat / file       → metadados

Sistema

uname -a  → info do kernel
uptime    → tempo ligado
free -h   → memória
df -h     → disco
lsblk     → dispositivos

Processos

ps aux    → listar processos
top/htop  → monitor interativo
kill PID  → encerrar processo
jobs/bg/fg → controle de jobs
pstree    → árvore de processos

Permissões

chmod 755 → alterar permissões
chown     → mudar dono
chgrp     → mudar grupo
umask     → máscara padrão
id / whoami → identidade

Texto / Filtros

grep      → buscar padrões
wc -l     → contar linhas
sort      → ordenar
cut       → extrair campos
awk       → processamento avançado

Checklist de Avaliação Prática

Critério Iniciante Intermediário Avançado
Kernel e Syscall Sabe dizer o que é o kernel e ler uname -r Explica a diferença entre kernel/user space e o papel das syscalls Usa strace e interpreta as chamadas de sistema de um processo
Navegação FHS Navega entre diretórios com cd e lista com ls Sabe o propósito de cada diretório raiz e usa find Localiza arquivos de configuração, logs e explica a hierarquia sem ajuda
Shell / Bash Executa comandos básicos com opções simples Usa pipes, redirecionamentos e variáveis de ambiente Escreve scripts com loops, condicionais e tratamento de saída
Processos Lista processos com ps e usa top Envia sinais, controla jobs em background e usa pstree Analisa /proc/PID, explica o scheduler e estados de processo
Permissões Lê a saída de ls -l e entende rwx Usa chmod em notação octal e simbólica; entende dono/grupo Configura permissões especiais (SUID, SGID, sticky) e usa umask
Distribuições Nomeia pelo menos 3 distribuições conhecidas Diferencia famílias (Debian, Red Hat, Arch) e gerenciadores de pacotes Explica o modelo de desenvolvimento, ciclos de release e filosofia de cada família
Documentação Usa --help para ver opções Navega no man e busca seções específicas Usa info, apropos e a documentação LPI online como referência

Pontuação Sugerida

Iniciante — 0 a 5 pts

Executa comandos básicos com orientação; precisa de ajuda para navegar; entende conceitualmente o que é um SO mas não sabe explorar autonomamente.

Intermediário — 6 a 8 pts

Navega e usa filtros sem ajuda; escreve scripts simples; explica syscalls e FHS; resolve o desafio com referência à documentação.

Avançado — 9 a 10 pts

Resolve o desafio completo com bônus; usa strace e /proc proficientemente; explica trade-offs entre distribuições; scripts robustos.

Tarefa de Fixação (para casa)

Entrega: próxima aula

A tarefa deve ser entregue como um arquivo tarefa01.sh — um script Bash executável que, quando rodado, exibe todos os resultados abaixo.

Requisitos do script

  • Exibir nome, versão do kernel e distribuição (leia /etc/os-release)
  • Listar os 5 maiores arquivos em /var/log com tamanhos legíveis
  • Mostrar quantos processos cada usuário tem rodando (dica: ps aux | awk)
  • Exibir as 3 partições com maior uso percentual de disco
  • Criar um diretório ~/lab01 com 3 subdiretórios e permissões diferentes
  • Escrever um here-document com um mini-relatório em ~/lab01/relatorio.txt
  • Usar pelo menos 1 loop, 1 condicional e 1 pipe no script
  • Bônus: Detectar se systemd é o init e listar os 5 serviços ativos
Esqueleto inicial (modifique e expanda)
#!/usr/bin/env bash
set -euo pipefail

echo "=== Tarefa 01 — Fundamentos de SO e Linux ==="
echo "Aluno: SEU NOME AQUI"
echo "Data:  $(date '+%Y-%m-%d %H:%M:%S')"
echo ""

# 1. Informações do sistema
echo "--- Sistema ---"
source /etc/os-release
echo "Distro  : $PRETTY_NAME"
echo "Kernel  : $(uname -r)"
echo "Arch    : $(uname -m)"
echo ""

# 2. Maiores arquivos em /var/log
echo "--- Maiores arquivos em /var/log ---"
# ... seu código aqui ...
echo ""

# 3. Processos por usuário
echo "--- Processos por usuário ---"
# ... seu código aqui ...
echo ""

# 4–8: complete os demais requisitos...

Recursos e Referências

Orientações Gerais

Como aproveitar melhor este módulo

  • Rode o strace em um simples ls para ver, ao vivo, quantas chamadas de sistema um comando trivial dispara — é o que torna o conceito de syscall concreto
  • Não apenas execute os comandos: procure explicar em voz alta a saída de cada um antes de seguir para o próximo
  • Sempre que possível, relacione cada comando ao objetivo LPI correspondente — isso constrói consciência do caminho de certificação
  • Refaça os dois laboratórios sem olhar o passo a passo; a autonomia é o objetivo final
  • Tente o bônus do desafio: é onde os conceitos de processo, filtro e script se juntam
  • Mantenha o man aberto ao lado — consultar a documentação é uma habilidade tão importante quanto memorizar comandos

Erros comuns a evitar

  • Confundir / (raiz) com ~ (home) ao copiar caminhos
  • Esquecer o espaço entre o comando e as opções (ls-la vs ls -la)
  • Usar rm sem cuidado — lembre-se de que não há lixeira no terminal
  • Interpretar mal a saída de ps aux: ela mostra os processos de todos os usuários, não apenas os seus