Nascido para desenvolver 🧐 Sobre o meu trabalho

Devopers.

🐧 Entendendo chamadas de sistema

Cover Image for 🐧 Entendendo chamadas de sistema
Iago Silva Ambrosio
Iago Silva Ambrosio

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”

Untitled

Vamos utilizar o strace para ver as chamadas de sistema do comando “cat” ao concatenar este arquivo.

Untitled

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:

Untitled

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”.

Untitled

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.

Untitled

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.

Untitled

Vale lembrar do nginx que também utiliza desse recurso para atender suas solicitações web.