Curso sistemas operacionais 2007 Programação aula a aula. 07/5 1 - 1.1 O que é um sistema operacional, 1.2 História dos sistemas operacionais 08/5 2 - Visao do hardware 1.3 conceitos de sistema operacional 14/5 3 - 1.3 conceitos de sistema operacional; 1.4 chamadas de sistema 15/5 4 - 1.4 chamadas de sistema 1.5 estrutra do sistema operacional. 21/5 5 => apresentação dos projetos (fase 1) 22/5 6 - 2.1 introdução aos processos 28/5 7 - 2.2 comunicação interprocesso 29/5 8 - 2.2 comunicação interprocesso/ - 2.3 problemas clássicos de CIP 04/6 9 - 2.3 problemas clássicos de CIP 05/6 10 - 2.4 agendamento de processo. 11/6 11 => Projetos 2.5 visão geral de processos em minix (fase 2) 12/6 12 - 3.1 Hardware Entrada e Saida 3.2 Software Entrada e Saida 18/6 prova 1 19/6 13 - 3.2 Software Entrada e Saida 25/6 14 - 3.3 impasses 26/6 16 - 4.1 gerenciamento básico de memória 4.2 troca (swap) 02/7 15 => Projetos 3.4 visão geral de E/S no minix (fase 3) 03/7 18 - 4.3 memória virtual, 4.4 algoritmos de substituição de página. 09/7 - FERIADO 10/7 19 - 4.4, 4.5 questões para sistemas de paginação. 16/7 20 - 4.6 segmentação 17/7 21 => Projetos 4.7 visão geral do gerenciamento de memória do minix (fase 4) 23/7 22 - 5.1 arquivos 5.2 diretórios 24/7 23 - 5.3 implementação do sistema de arquivos 30/7 24 - Minix filesystem <- (5.4 segurança, 5.5 mecanismos de proteção) 31/7 26 Prova 2. 06/8 27 topicos em SO (ex: Linux, Windows). 07/8 25 => Projetos 5.6 visão geral do sistema de arquivos minix (fase 5) Livro texto: Sistemas Operacionais - Projeto e Implementação ; Tanenbaum A.S. Woodhull A.S.; Bookman segunda edição Obs: Este livro contém o Minix que serviu de base para a criação do Linux Bons Livros de apoio: - Sistemas Operacionais Modernos 2a. edição; Tanenbaum A.S.; Prentice Hall Obs: Este livro é muito parecido com "Projeto e Implementação" mas não contém o Minix. Por outro lado é mais didático e contém mais informação que o outro. - Sistemas Operacionais com Java; Silberschatz, Galvin, Gane; Editora Campus Obs: Este livro apresenta os conceitos de forma mais clara que os livros do Tanenbaum. avaliação: 3 P1 + 4 P2 + E + 2 P E = exercícios feitos em aula / vale mais contar presença. Projeto 1. familiarização com o Minix: (todos) - instalação - sugestão: usar o Linux/ubuntu + (Boochs,qemu) (um por grupo) - criar aplicativos na linguagem C para rodar no minix utilizando as chamadas do sistema operacional. a- programa que concatena dois arquivos. Entrada: o nome dos dois arquivos. Saida: o arquivo concatenado b- programa que imprime os nomes e datas dos arquivos no diretório corrente. c- programa que cria um processo pai e outro filho. O pai escreve uma string e o filho outra string. d- troca o nome dos arquivos de um diretório colocando a string "L" na frente. e- troca o password de um usuário. f- programa que escreve "teclou ^C" toda vez que o usuário digitar control-C. O programa deve capturar o signal SIGINT. g- programa que imprime uma mensagem e depois de 1 segundo imprime outra mensagem. Para isso faz uso de um signal. 1.3 (Todos) - Escolha uma system call que foi chamada em seu programa. Altere a system call de forma a imprimir uma mensagem toda vez que ela for chamada. Entregar: Relatório com: - objetivo - programa explicado - cópias das telas do emulador mostrando o programa rodando. Apresentação com powepoint e telas da saída do emulador. Projeto 2 Processos. O código do minix 3 está alterado em relação ao minix 1 e 2. Portanto não vamos usar as questões do livro antigo do Tanenbaum sobre o minix 3. O objetivo desse trabalho é estudar o código fonte do minix 3. Estude o código do minix 3 (/usr/src/). Responde (geralmente observando /usr/src/kernel): 1 a1 - onde está declarada a tabela de processos? Quais são os campos para cada processo (ex: pid, etc.) ? a2 - onde está o código do minix que trata dos sinais (signals)? Caso um processo não tenha decladrado o signal handler para tratar SIGINT (control C) qual é o código executado pelo minix? dica: signal.c, SIG_DFL Resposta: http://www.pcs.usp.br/~jkinoshi/2007/r2-1.pdf 2 b1 - quando ocorre a system call, qual é o número de interrupção de software? Onde está o código que chama o serviço correspondente? (Exemplo: como a partir do registrador é feita a chamada de fork?). b2 - altere o número de interrupção relacionada à system call. dica: *** http://www.cis.syr.edu/~wedu/seed/Labs/Documentation/Minix3/System_call_sequence.pdf Este documento contém a sequencia para que uma system call seja realizada. O trap para o kernel ocorre em "int SYSVEC". Veja onde isso ocorre e explique o uso de sendrec. Use o código fonte do minix.iso (isto é, veja o minix que de fato roda no qemu, vmware, etc.) e não o código em minix_source_3_1_1.tar.bz2 (eles não estão compatíveis e o tar.bz2 não contém o código do sendrec). Resposta: >> Falta entregar 3- supondo que todos os processos estejam bloquedados, qual é o código sendo executado? dica: "idle" - table.c; localize o código dessa tarefa e explique. - se o comando passwd estiver com o setuid desligado ele funciona (chmod -s passwd)? Estudar o setuid e chmod +s. Resposta: http://www.pcs.usp.br/~jkinoshi/2007/r2-3.doc http://www.pcs.usp.br/~jkinoshi/2007/p2-3.ppt 4- onde está o código que faz o escalonamento dos processos? Explique este escalonamento. - altere o escalonador para ele trabalhe com o sorteio de tiquetes. Resposta: http://www.pcs.usp.br/~jkinoshi/2007/r2-4.pdf 5- o kernel do minix oferece uma base para que os procesos troquem mensagens. Quais são essas funções? Apresente exemplos de processos do minix (ex: file system server) usando essas funções de troca de mensagens. - altere o tempo de chaveamento entre processos. Resposta: >> Falta entregar 6- quais são os estados em que um processo do minix pode estar (rodando, pronto, bloqueado ...) ? Mostre onde o código do minix altera os estados dos processos. - onde o init (primeiro processo) é colocado para rodar? Onde o minix passa do modo kernel para o modo usuário? dica: kernel/table.c; kernel/main.c Resposta: http://www.pcs.usp.br/~jkinoshi/2007/r2-6.doc 7 g1 - Suponha que: . um processo P1 pede a execução da system call "read", P1 fica bloqueado . o processo P2 ganha a CPU e também pede a execução de "read". O pedido de P2 fica em alguma fila aguardando que P1 seja atendido? O que acontece com o pedido de P2? Onde está isso no código? dica: se o mesmo processo servidor (ex: "fs") receber duas mensagens (já que as system calls se transformam em mensagens) de processos diferentes, o que ocorre? Veja: http://www.cis.syr.edu/~wedu/seed/Labs/Documentation/Minix3/System_call_sequence.pdf g2 - onde está o código que faz o chaveamento do processo? Os registradores da CPU devem ser trocados para o novo processo que vai rodar. Onde os valores dos registradores são trocados? dica: arquivos .s em kernel. Resposta: >> Falta entregar >> O que entregar? Um relatório contendo: - objetivo do exercício. - uma visão geral dos fontes *.c utilizados. - uma visão mais detalhada observando o código do minix. Enviar este relatório .pdf para o meu email para ser publicado em www.pcs.usp.br/~jkinoshi Apresentação: usar powerpoint. Colocar o código relacionado com a pergunta nos slides. >> Dicas para analisar o fonte do minix 3. - Uma forma de se analisar o fonte do minix 3 é simplesmente ir em www.minix3.org e fazer o download de http://www.minix3.org/download/minix_source_3_1_1.tar.bz2 Se estiver no linux faça: bunzip2 minix_source_3_1_1.tar.bz2 e depois tar -xvf minix_source_3_1_1.tar Vejam os subdiretórios de src: boot/ - contém o init, primeiro processo a ser disparado. drivers/ - código dos drivers. include/ kernel/ - código do kernel que cuida do chaveamento de processos e fornece a base para a comunicação entre processos. tools/ - código de dois scripts que servem como ferramentas mkboot e tell_config. Se estiver no linux, um bom comando para se usar : grep -r "string"./ dentro de src/kernel pode fazer simplesmente: grep "string"*.c Exemplo em relação ao init, o primeiro processo a ser disparado. o código do processo está em: /src/servers/init/init.c e o resultado de sua compilação é o processo 'init' gerado em uma arquivo. Fazendo: grep '"init"'*.c encontramos: src/kernel/table.c Esse arquivo contém os processos que são disparados em main(). Alguns deles são tarefas do minix (ex: idle, fs, pm, etc.) e o init é o primeiro processo na fila de processos de usuário. Obs: a versão do código do minix3 é diferente da imagem iso; assim tome cuidado para não misturar fontes de versões diferentes. Projeto 3 1) RAM disk (dispositivo para blocos). O minix possui um driver para RAM disk associado a /dev/ram. - crie um disco em RAM no minix e execute operações como criar arquivo, listar diretórios, etc. nesse RAM disk. - O driver envia mensagens? Para quem? - altere o minix de forma a imprimir as mensagens (processo origem, tipo e parte do conteúdo) que o driver recebe. Relacione essas mensagens ao: - criar um arquivo. - escrever em uma arquivo. - fechar um arquivo. Resposta: >> Falta entregar 2) Porta Paralela (dispositivo para caracteres). - Estude o driver da porta paralela em /usr/src/drivers/printer - altere o minix de forma a imprimir as mensagens (processo origem, tipo e parte do conteúdo) que o driver recebe. Envie uma string para /dev/lp e veja o que ocorre (ex: cat "lixo" > /dev/lp). - altere o minix de forma a imprimir as mensagens que o driver envia para a SYSTEM_TASK. Observe que o minix usa uma biblioteca que contém funções como sys_outb que acabam enviando mensagens para a system_task quando se deseja fazer ler ou escrever nas portas de I/O. Altere a system task para imprimir uma mensagem caso tenha recebido uma mensagem do driver da porta paralela. Resposta: >> Falta entregar 3) Como funciona mknod? O que é o major number e minor number ao se criar um driver? Crie /dev/lpx com um major number diferente de /dev/lp. Recompile o driver da porta paralela para que ele fique associado ao major number dado por /dev/lpx. Sugestão: leia as apostilas do laboratório de microprocessadores, experiências 8 e 9. Resposta: >> Falta entregar 4) Crie um novo driver para a porta paralela associado a /dev/lpx (declare lpx através de mknod) que funcione assim: echo 1E > /dev/lpx deverá colocar o byte 1E (ou qualquer outro valor) nos pinos da porta 0x37a. Obs: o comando echo tentará escrever a string "1E\0" e não o byte 0x1E assim você deverá fazer uma rotina de conversão de valores. Sugestão: Verifique como o exercício 3) foi resolvido. Leia as apostilas do laboratório de microprocessadores, experiências 8 e 9. Resposta: >> Falta entregar 5) Porta Paralela O driver da porta paralela usa somente alguns endereços de I/O (usando a System Task). Altere o driver para que ele escreva em uma outra porta que não deveria, por exemplo: 0x3f9 (da serial). Ocorre um erro? Como o driver registra no kernel quais portas ele poderá usar? Resposta: http://www.pcs.usp.br/~jkinoshi/2007/r3-5.doc 6) Porta Paralela - Qual interrupção é associada a porta paralela? Quando ela ocorre? Veja HARD_INT em printer.c. Quem gera a mensagem do tipo HARD_INT? (ex: system task??) Quando ela é gerada? (Ex: quando a impressora acabou de imprimir o que devia, quando papel acabou ...). - Caso alguém estivesse criando um driver novo, como deveria fazer para associar uma interrupção de número N a esse driver, - Faça o driver imprimir uma mensagem toda vez que receber a mensagem HARD_INT. Resposta: http://www.pcs.usp.br/~jkinoshi/2007/r3-6.pdf 7) Crie um novo driver para a porta paralela associado a /dev/lpx (declare lpx através de mknod com um major number diferente) que funcione assim: echo 1E 378 > /dev/lpx deverá colocar o byte 1E (ou qualquer outro valor) nos pinos da porta 0x378. Obs: o comando echo tentará escrever a string "1E\0" e não o byte 0x1E assim você deverá fazer uma rotina de conversão de valores. (Exercício praticamente idêntico a 4, apenas a porta é opcional - 0x37A ou 0x378). Resposta: http://www.pcs.usp.br/~jkinoshi/2007/r3-7.pdf Projeto 4 (Memória) Todos os grupos: Observem que no minix3, ao se teclar F2 aparece uma relação de processos e de como a memória está alocada. Leiam também o livro do Tanenbaum sobre o gerenciamento de memória em minix - item 4.7. Vejam também a figura 4-33 que mostra como os endereços virtuais foram colocados na memória física. A memória do minix é medida em clicks e dividida em segmentos. 1. Mostrar através de um log como a memória foi alocada e desalocada a processos. Toda vez que um processo executar um fork, exec, exit afeta a alocação de memória e isso é registrado no log (em um deterinado arquivo). No log contém informações como: fork - processo /usr/bin/init + segmento 0x30 - 5 clicks. exec - processo /usr/bin/firefox + segmento 0x40 - 7 clicks. exit - processo /usr/bin/firefox - segmento 0x40 - 7 clicks. onde: + : significa que memória está sendo alocada ao processo da posição 0x00230 até 0x00340 - : significa que memória está sendo desalocada e devolvida para a área livre. Resposta: http://www.pcs.usp.br/~jkinoshi/2007/r4-1.pdf 2. O minix usa uma lista ligada para marcar onde estão as lacunas. Quando uma memória é alocada ou desalocada a processos, a lista de lacunas é alterada. Onde ocorre isso no código? Comente. Alterar o minix para que ao se teclar F8 ele apresente todas as posições da lacunas (relacione com segmentos e clicks). Resposta: http://www.pcs.usp.br/~jkinoshi/2007/r4-2.doc 3. Crie um programa em C que lê o teclado e se o usuário digitou 1 ele cria um processo filho que fica em loop contínuo imprimindo "filho" e se o usuário digitar 2 ele mata o processo filho. Faça experiências teclando F2 para observar o que ocorre com a memória quando o filho é criado ou morto. Resposta: http://www.pcs.usp.br/~jkinoshi/2007/r4-3.doc 4. Explique o formato do arquivo a.out. Onde está a informação do entrypoint (enderço da primeira instrução executável)? Olhando o código do minix, crie o aplicativo "vememoria programa_executavel" que informa o quanto de área de código, dados e pilha deveriam ser alocados ao programa_executavel; onde programa_executavel corresponde a um arquivo executavel. Experimente criar um arquivo executavel (ex: a.out) que imprime "hello world" e submeta ao vememoria. Verifique se o vemmoria funciona bem na prática teclando F2 (talvez seja interessante deixar o processo em um loop infinito para que sua memória não seja desalocada). Resposta: >> Falta entregar 5. Imagine que um programa queira invadir área de memória de outro programa. Será que o minix impede isso? Crie um programa em C que mexa em alguma área de dados (ex: uma variável global). Compile gerando o código em assembly (teste.s). Altere o teste.s para que ele leia algum dado de algum outro processo (por exemplo: fazendo com que ele referencie dados em um outro segmento que não pertence ao programa). O minix retorna erro? Ou seja: será que o minix está protegendo a área de memória de cada processo? Resposta: http://www.pcs.usp.br/~jkinoshi/2007/r4-5.doc 6. Ex: 4.36 - Na seção 4.7.5 do livro minix3, foi visto que a chamada exec busca primeiro uma lacuna na memória e depois libera a memória do processo. Melhore o algoritmo fazendo com que primeiro a memória do processo seja liberada para depois se buscar a lacuna na memória. Resposta: http://www.pcs.usp.br/~jkinoshi/2007/r4-6.pdf 7. Ex: 4.37 - Na seção 4.8.4 do livro minix3, foi visto que seria melhor procurar por lacunas para os segumentos de código e dados separadamente. Implemente esta melhora. Resposta: >> Falta entregar Projeto 5 (FileSystem). Para se entender o como file system é implementado no minix, leia o item 5.6 do livro do minix 3. Gostaria de passar o seguinte exercício para algum grupo: Criar o programa vemapa gera um mapa do disco. A saída é uma listagem contendo para cada bloco da partição minix o que ele contém (item 5.6.2; figura 5-34) Exemplo: vemapa 0: bloco de boot 1: superbloco ... 5: i-node livre 6: i-node diretório /usr 7: i-node arquivo /usr/bin/chdir ... 100: bloco 2 /usr/bin/chdir 101: bloco 3 /usr/bin/chdir ... Mas achei que o exercício ficaria pesado demais. Assim distribuí algumas tarefas desse exercício para alguns grupos. 1 - Como ocorre a system call read? (item 5.6.10 do livro do minix3). Crie a system call leia (uma cópia de read) que ao fazer a leitura, imprime os blocos do disco que foram lidos. Faça um programa em C que use "leia" e imprima quais blocos foram lidos. Informe se o bloco está sendo lido do cache ou do disco. Resposta: http://www.pcs.usp.br/~jkinoshi/2007/r5-1.pdf http://www.pcs.usp.br/~jkinoshi/2007/r5-1.ppt 2 - Implemente o comando i-nodes que apresenta para cada i-node informações se ele está livre ou a qual arquivo pertence. Exemplo: i-nodes ... 5: i-node livre 6: i-node diretório /usr 7: i-node arquivo /usr/bin/chdir ... Dica: Veja onde o i-node é utilizado e tente aproveitar as rotinas que lidam com o i-node. Resposta: http://www.pcs.usp.br/~jkinoshi/2007/r5-2.doc 3 - Implemente um programa que mostre para cada processo, todos os arquivos que foram abertos por ele. Inspire-se no comando lsof do linux que lista todos os processos e para cada processo, os arquivos por ele abertos. (item 5.6.7). Você deverá consultar a tabela de processos que está no processo fs. Para isso, você pode fazer com que o fs retorne uma mensagem com esses dados. Resposta: >> Falta entregar 4 - Dado um número de i-node, imprimir todos os blocos que fazem parte do arquivo. Para cada bloco especificar se é bloco de dados ou bloco indireto (de ponteiros). Resposta: >> Falta entregar 5 - Imprimir a tabela filp ao se teclar F7. (fig. 5-39). Faça a experiência. Um processo abre o arquivo "/tmp/lixo" e escreve "1". Ela "forka" e seu filho escreve "2" no mesmo arquivo. O filho "forka" escreve "3" no mesmo arquivo. Qual é a string que você lê em /tmp/lixo? Relacione isso com a tabela filp. Resposta: http://www.pcs.usp.br/~jkinoshi/2007/r5-5.doc 6 - Crie o vebloco que permita inspecionar um bloco/zona do disco. Passa o número do bloco e apresenta os bytes que estão nele. Inpire-se no comando xxd do linux. O xxd recebe um arquivo e apreseta os bytes. O vebloco recebe o número do bloco e apresenta os bytes nele contidos em um formato semelhante à saída de xxd. Usando vebloco pode-se inspecionar um i-node e os blocos que compõem um arquivo. Resposta: http://www.pcs.usp.br/~jkinoshi/2007/r5-6.doc 7 - Como funciona file lock? Estude: http://www.ecst.csuchico.edu/~beej/guide/ipc/flock.html Compile lockdemo.c no minix. Explique a diferença entre write lock (somente um pode escrever e ninguém ler) e read lock (vários podem ler e ninguém escrever). Rode várias instâncias de lockdemo fazendo os locks e observe o que ocorre. Resposta: >> Falta entregar Bibliografia O documento em: http://www.cs.vu.nl/~steen/courses/os-slides/notes.02.pdf contém slides sobre o minix e seu código. Pode ajudar alguns grupos a resolverem suas questões. Alguns grupos talvez se interessem em como o 386 (o minix é baseado no 386) lida com o vetor de interrupção e como ele transita do modo protegido para o real e vice-versa. Existem diversos documentos sobre isso na internet. Exemplo: http://www.x86.org/articles/pmbasics/tspec_a1_doc.htm http://my.execpc.com/~geezer/os/pm.htm http://eserver.bell.ac.uk/mirrors/asm/p386_2.htm O site: http://www.raspberryginger.com/jbailey/minix/html/files.html contém o código do minix apresentado como páginas HTML Em: http://www.os-forum.com/minix/boot/index.php existe o código comentado sobre o boot.