🐧 Entendendo chamadas de sistema
Entendendo o problema
Quando trocamos de sistema operacional é como se estivessemos trocando de casa, começar a utilizar o ferramentário GNU com kernel Linux demanda uma curva de aprendizado para quem vem do windows, com suas telas e interfaces bem únicas, digo únicas porque de todos os sistemas, só o mais popular para desktop não segue os padrões POSIX, se alguma vez você tentou utilizar o windows depois de um bom tempo estudando *nix deve ter se estranhado, o DOS segue um padrão bem diferente para atribuir funcionalidades em suas APIs, apenas recentemente o powershell recebeu alias que mimificam as apis do POSIX, mas são binários executados e compilados de forma diferente.
Mas não só os comandos são diferentes, a forma como compilamos e executamos programas em ambos os sistemas são diferentes, e aqui está a questão: A resolução de problemas, e aqui quero mostrar o básico para lidar com erros ou comportamentos indeterminados.
O que são chamadas de sistema?
São basicamente ligações que alguma aplicação em userland faz para o kernel, estas chamadas são conhecidas como funções necessárias para que os softwares possam funcionar. Um exemplo bem conhecido é o fork(), uma chamada responsável por criar um processo filho idêntico ao pai em uso de memória, mas a partir do fork, cada um segue seu caminho com suas atividades e atribuições dependendo do que é solicitado. Para demonstrar o uso de syscals vamos utilizar:
- strace - software para monitorar chamadas de sistema de um programa
- sh - shell básico que vem em toda distribuição linux
- um código em c
O código
Aqui segue um código em C, sem muitas enrolações, importamos a biblioteca padrão de i/o e a main é um printf com “ola”
Vamos utilizar o strace para ver as chamadas de sistema do comando “cat” ao concatenar este arquivo.
Algumas das principais chamadas de sistema, execve() que chama o binário e já faz o parser e o lexer do comando passado tokienizando o nosso pedido ao bash, brk(NULL) é o padrão para um enter, indicando que nossa ação para chamar o programa acabou, mmap() é a função para mapeamento de memória, e toda essa parte até o primeiro close é o pré carregamento para execução do programa, em seguida, a partir de openat() temos o carregamento das bibliotecas padrões do c, necessárias para o cat funcionar e só então o carregamento do binário do cat para execução a partir do segundo close(3), no final, o read e write onde read() é a leitura do arquivo em si (após alocação de memória e carga) e write() é a escrita no stdout.
Para fins de comparação, o strace do código compilado quando chamamos para execução:
Perceba, não chamamos “openat()” de locale-archive, porque o nosso arquivo compilado não precisa de coisas como localidade e região como o binário do cat.
E o strace em um programa com loop?
Aqui está a magia do nosso primeiro comando com cat, para ler os arquivos o shell faz um lexer e parser dos nossos comandos, e essa separação é feita porque o sh aceita como parametro de entrada tudo que colocamos no terminal, então é esperado que uma chamada de sistema fique aberta, esperando nosso input para só então processar e devolver o terminal para a gente, segue um exemplo de um “strace sh”.
Essa é uma forma bem intuitiva de observar o que os comandos estão chamando por baixo do capô, ou até mesmo, uma forma de fazer engenharia reversa dos programas e resolver erros, vejamos o que acontece se chamamos “ls” em um diretório com nosso arquivo do código c e o compilado.
Como pode ver , em “wait4(-1 “ temos os arquivos no nosso diretório atual, este seria o nosso stdout caso tivéssemos apenas chamando o ls.
Bônus: nodejs
Sabemos que o javascript é interpretado apenas em uma thread de execução, mas também possui uma boa capacidade de lidar com requisições, graças ao event loop e o i/o assincrono, e como isso é gerenciado pelo sistema? A resposta ja foi dita anteriormente, por meio de uma chamada de sistema chamada Epoll, veja o final do strace, quando chamo node no terminal.
Vale lembrar do nginx que também utiliza desse recurso para atender suas solicitações web.