Introdução ao Ambiente UNIX II


1. Utilização do manual

  1. Pode aceder aos manuais de uma ferramenta utilizando o comando man. Por exemplo, para se informarem sobre o uso do próprio comando man:
    $ man man
    
    Para navegarem nas páginas do manual, podem utilizar as setas do teclado. Para saírem, basta pressionar a tecla q.
  2. Os manuais estão distribuidos por secções. Para a cadeira Sistemas Operativos, as secções mais relevantes são: 1 (comandos/utilidades), 2 (chamadas de sistema), 3 (funções de biblioteca). Isto é necessário porque há coisas com o mesmo nome que têm propósitos muito diferentes. Por exemplo: o comando free que está na secção 1, e a função free que está na secção 3. Podem especificar que secção querem, especificando o número antes do nome:
    $ man 1 free
    $ man 3 free
    
  3. Quando querem obter informação sobre uma ferramenta podem consultar as páginas do manual. Por exemplo, podem utilizar o comando man para consultar a página sobre o make.
  4. Outra maneira de saber mais sobre uma ferramenta é utilizando a opção --help ou -h. É de notar que nem todas as ferramentas suportam estas opções -- na dúvida, consultem o manual. Por exemplo:
    $ make --help
    
  5. Em vez de procurarem na internet sobre o uso de funções do C, ou se já sabem as que querem mas não sabem como utilizar, há também páginas no manual que descrevem as funções da biblioteca do C e as chamadas de sistema. Por exemplo, podem consultar as funções malloc/free/fopen/fprintf/fscanf/printf, da biblioteca do C, e as funções open/read/write/kill, do sistema operativo.
  6. Reparem que nos manuais das funções há uma secção RETURN VALUES. É altamente recomendado que leiam esta secção. Como exemplo, verifiquem o valor de retorno da função sleep.

2. Utilização da ferramenta make (slide)

Neste laboratório vamos fazer uso da ferramenta make (documentação completa). O make pega num ficheiro, habitualmente chamado Makefile, que descreve alvos, normalmente ficheiros, e respectivas dependências, também frequentemente ficheiros. (Um alvo também pode ser uma dependência de outro alvo.) O make é frequentemente utilizado para construir software, pois permite-nos especificar coisas como "os ficheiros objecto dependem dos respectivos ficheiros-fonte", e "um executável depende dos respectivos ficheiros objecto e bibliotecas".

Quando as dependências são mais antigas do que os alvos, ou quando os alvos não existem, o make volta a executar as receitas. Deste modo, quando um ficheiro-fonte é actualizado, basta executar uma vez make para que todos os passos necessários até à geração do executável sejam realizados.

  1. Recupere o trabalho da aula anterior ou, caso não o tenha, descarregue os ficheiros da aula anterior.
  2. Copie o ficheiro Makefile para a sua área de trabalho e execute make. O que aconteceu?
  3. Apague o ficheiro list.o com o comando rm. Verifique se o ficheiro foi eliminado com o comando ls. Re-execute make. Interprete o sucedido.
  4. Utilize o comando ls com a flag -l para verificar a data do ficheiro main.c. (Pode ver exactamente o que a flag faz no manual!) Simule uma alteração ao ficheiro main.c com o comando touch e verifique de novo a data. Re-execute make e compreenda o resultado.
    $ touch main.c
    
  5. Simule a alteração do ficheiro list.h e execute make. Porque razão todos os ficheiros foram gerados?
  6. Simule a alteração do ficheiro list.o. O que acontece quando faz make list.o? E se agora fizer make?
  7. Retire a dependência do ficheiro list.h da regra list.o da makefile.
  8. Repita o procedimento das alíneas 4 a 6. Explique a diferença no resultado.
  9. Adicione a regra seguinte no final do ficheiro.
    clean:
    	rm -f *.o main
    
    O que descreve esta regra? Identifique: o alvo, as dependências e o comando. Tenha em atenção que os espaços iniciais em cada linha são tabs. A indentação numa makefile tem que ser feita com tabs!
  10. Execute make clean. O que aconteceu? Porque razão o comando é executado sempre que esta regra é invocada explicitamente?
  11. Reparem que na vossa makefile, muitas das flags encontram-se repetidas. No entanto, é possível factorizar as flags utilizando variáveis. Por exemplo, reparem nas flags -Wall e -g, que são ambas utilizadas para compilar os ficheiros objecto. Para evitar repetições e facilitar manutenção, podemos factorizar as flags para uma variável CFLAGS. Exemplo:
    CFLAGS = -Wall -g
    
    list.o: list.c list.h
    	gcc $(CFLAGS) -c list.c 
    
    Altere o resto da makefile de acordo com o exemplo.

3. Exercícios

Comece por rever os slides de IAED do semestre passado. Recomenda-se também que consulte as funções fopen/fread/fgets/fwrite/fclose pois são bastante úteis para lidar com ficheiros.

  1. Implemente uma versão simplificada do comando cat chamada mycat. Este comando imprime no ecrã o conteúdo de zero ou mais ficheiros passados como argumento. Por exemplo, para listar os utilizadores do sistema:
    $ cat /etc/passwd
    
    O comando deve aceitar uma lista de ficheiros e escrever o seu conteúdo, por ordem, para o standard output. Exemplo de uso:
    $ echo "dling" > ficheiro1
    $ echo "dlao" > ficheiro2
    $ mycat ficheiro2 ficheiro1
    dlao
    dling
    
  2. Escreva uma função que lê uma linha completa do standard input. Não há restrições em relação ao tamanho da linha. Escreva um programa que exemplifique a utilização desta função. Uma possível assinatura para a função é char *le_linha().