EP01 – Mini-Shell - Rede Linux IME-USP
EP01 – Mini-Shell - Rede Linux IME-USP
EP01 – Mini-Shell - Rede Linux IME-USP
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
<strong>EP01</strong> <strong>–</strong> <strong>Mini</strong>-<strong>Shell</strong><br />
MAC0422 - Sistemas Operacionais <strong>–</strong> 2o. Sem./2006<br />
Carlos Duarte do Nascimento (Nº <strong>USP</strong> 3099351)<br />
Willian Gigliotti (Nº <strong>USP</strong> 4963454)<br />
Introdução<br />
Este documento descreve a implementação do <strong>EP01</strong> (“<strong>Mini</strong>-<strong>Shell</strong>”), que consiste na<br />
implementação de um interpretador simplificado de comandos simplificado, conforme enunciado<br />
disponibilizado no sistema Paca/Moodle, acrescido de dois comandos extras (por ser entregue em<br />
dupla) e da execução de processos em background (comando “&”).<br />
Metodologia<br />
Separamos o projeto em unidades funcionais, atribuindo cada uma a um código-fonte (e, a cada<br />
um deles, um arquivo de header de mesmo nome, além do arquivo comum comando.h). Estes<br />
arquivos são os seguintes:<br />
●<br />
●<br />
●<br />
●<br />
main.c: funcionamento central do shell (leitura da linha de comando, fork, etc.);<br />
interpretador.c: parsing da linha de comando;<br />
cst.c: interface (e tabela de símbolos) para os comandos customizados (internos);<br />
comandos.c: implementação dos comandos customizados.<br />
O mais importante foi separar o shell em si (main.c) do interpretador de comandos<br />
(interpretador.c). A codificação foi feita usando ferramentas tradicionais (vi, gcc, make), e a<br />
depuração foi feita inicialmente no interpretador, e para cada comando à medida em que era<br />
implementado.<br />
Sendo o EP em dupla, optamos por implementar os comandos ps e chmod. Este último foi feito<br />
através das chamadas stat e chmod, enquanto que o primeiro foi feito através da leitura do<br />
pseudo-sistema de arquivos /proc 1 , selecionando um subconjunto apropriado das informações, e<br />
listando todos os processos visíveis.<br />
Durante os testes, acabamos fazendo a execução de múltiplas tarefas em background (para<br />
observar o comportamento dos dados coletados por getrusage. Isto acabou nos levando a<br />
implementar, logo nos primeiros estágios, a opção “&”, que permite a execução de tarefas em<br />
background.<br />
1 Nossa preferência era por utilizar chamadas de sistema nesta implementação, tendo em vista o objetivo da atividade<br />
proposta. Entretanto, a única alternativa que encontramos neste sentido foi o uso de um driver de kernel como o devps,<br />
mas, por se tratar de uma alternativa não-padronizada (e possivelmente não disponível), optamos pelo parse do /proc.
Análise<br />
Os resultados obtidos (via getrusage) foram consistentes com o exposto em sala de aula, e o<br />
shell se mostrou capaz de executar comandos interativos e não-interativos como shells<br />
tradicionais.<br />
Dentre as facilidades que um shell mais completo possui, podemos citar:<br />
●<br />
●<br />
●<br />
●<br />
Expansão automática de wildcards em parâmetros (que permite, por exemplo, digitar vi *.txt e<br />
editar todos os arquivos .txt);<br />
Autocomplete (funcionlidade que, ao ser acionada por uma tecla, ex.: Tab, faz com que o shell<br />
procure um arquivo cujo nome se inicie pelo trecho que já foi digitado)<br />
Reconhecimento de uma linguagem script (através da implementação de conceitos como<br />
variáveis e estruturas de fluxo, e da possibilidade de receber como parâmetro um arquivo de<br />
comandos);<br />
Pipelines (que permitem a execução de múltiplos processos de forma a encadear a saída de um<br />
na entrada de outro <strong>–</strong> boa parte da operação de sistemas Unix-like consiste neste tipo de<br />
agregação, normalmente suportada por um shell e sua linguagem script).<br />
As informações que getrusage oferece (na struct rusage) são interessantes para um<br />
diagnóstico pontual do processo, mas seria útil obter, por exemplo, dados históricos de utilização<br />
dos recursos (ex.: “picos” das informações de memória nos campos ru_i?rss) 2 .<br />
Quando encontradas, as discrepâncias entre os tempos medidos por getrusage e gettimeofday<br />
se dão pelo fato de que o uso da primeira acaba mensurando o tempo total decorrido durante a<br />
execução do processo (incluindo aí o tempo gasto por outros processos em execução), enquanto<br />
que a segunda usa a “contabilidade” interna do kernel para obter apenas o tempo gasto com o<br />
processo executado 3 .<br />
Sobre o comando “&”, este foi efetivamente implementado. A maior mudança foi capacitar o<br />
parser a interpretá-lo, além de fazer a “espera” pelo processo-filho ser condicional à execução em<br />
foreground ou background. Vale lembrar que as estatísticas foram omitidas para processos em<br />
background.<br />
2 Por outro lado, este tipo de bookkeeping pode comprometer a performance. De qualquer forma, bibliotecas como<br />
PerfSuite (http://perfsuite.ncsa.uiuc.edu/) oferecem a funcionalidade desejada.<br />
3 Podem haver outras discrepâncias causadas pela “resolução” com que cada uma das informações é capturada pelas<br />
respectivas implementações destas funções no S.O. em questão, mas julgamos esta causa menos relevantes em um<br />
sistema multitarefa típico do que a causa efetivamente relatada.
Conclusão<br />
Em resumo, implementamos um shell com as características pedidas, e, como exercício extra, a<br />
execução de comandos em background (“&”), o que possibilitou fixar o conceito de fork, as<br />
chamadas de sistema apresentadas e a visão geral do agendamento de processos e outros detalhes<br />
interessantes do funcionamento de um S.O. baseado em Unix como o <strong>Linux</strong>.<br />
Um dos maiores limitantes ao uso do shell é, de fato, a já mencionada ausência da expansão de<br />
wildcards nos parämetros (indispensável já que, sob o <strong>Linux</strong>, as aplicações não tomam para si<br />
esta responsabilidade, como ocorre me outros sistemas) e também a inexistência de pipelining.<br />
Havendo mais tempo, poderíamos trabalhar o aspecto acima, e a expansão de parâmetros para os<br />
comandos em si também deveria ser melhorada. A implementação de processos em background<br />
(&) poderia também se beneficiar da exibição de dados getrusage (de forma que eles não<br />
atrapalhassem a execução e medição de outros comandos <strong>–</strong> razão que nos levou a suspender a<br />
exibição da estatística neste caso). O I/O para processos em background também deve ser<br />
cuidado, particularmente se um processo interativo for (acidentalmente) lançado em background.<br />
A proposta do projeto é bastante válida para um primeiro EP, pois é um meio-termo interessante<br />
entre “baixo nível” (manipulação de processos, chamadas do sistema, etc.) e a segurança e<br />
praticidade de uma aplicação rodando em user-mode. Desta forma, tanto alunos com mais<br />
experiência em programação quanto iniciantes conseguem se beneficiar.