Curso sistemas operacionais 2015

prof. Jorge Kinoshita.

Aulas terça: 14:00-15:40H sexta: 8:20-10:00H

Table of Contents

1 Programação aula a aula.

1.1 1.1 O que é um sistema operacional, 1.2 História dos sistemas operacionais

2015-05-08

Apresentacao do curso: programacao aula a aula. Apresentacao do material didatico: livros do Tanenbaum e Silberzchatz. Criterio de avaliacao.

O site http://www.cs.vu.nl/~ast/ é do prof. Tanenbaum. Em seu site, ele deixou o conjunto de transparênicas: http://www.cs.vu.nl/~ast/books/mos2/mos2-ppt.zip que vamos utilizar no curso.

transparencia a ser usada: Chapter-01.ppt slides 1-8.

Pedir para os alunos se dividirem em grupos. Da proxima vez pedir grupos com o minimo de alunos e depois acrescenta. Extra: história do Minix, Linux e comentários sobre os projetos da fase 1.

1.2 Visao do hardware

2015-05-12
Chapter-01.ppt 9-14 - Computer Hardware Review - interrupcao. comentários sobre os projetos da fase 1. Alocacao das turmas. Extra: comentario sobre o minix - o microkernel, processos do SO e processos de usuario; o linux como sistema monolitico. Incentivar que as turmas comecem os trabalhos.

1.3 conceitos de sistema operacional; 1.4 chamadas de sistema

2015-05-15

transparencias Chapter-01.ppt 15-21 hardware da aula passada: memoria.

Codigo relativo: os labels ainda nao foram definidos pelo linker. Codigo absoluto: os lables foram definidos pelo linker. O programa em codigo absoluto ao ser colocado na memoria deve entrar de forma "relativa" a algum endereco (um endereco definido em um registrador base).

Quando se faz uma system call, no final a pilha deve ser limpa incrementando o SP. Explicar que tem 4 formas de se implementar push e pop em pilha.

Termina a aula procurando explicar o melhor possivel como funciona interrupcao no computador. Explicar interrupcao de software e de hardware. Relacionar com o projeto de SO. Bater a foto da losa.

1.4 1.4 chamadas de sistema 1.5 estrutra do sistema operacional.

2015-05-19
Finalizar Chapter-01,ppt 21-35 system calls comentar sobre máquinas virtuais. sistemas monolíticos (linux) x microkernel (minix). falar sobre o projeto: os alunos devem mostrar em que código (arquivo fonte) está a interrupcao de software quando ocorre a system call. Discutimos como ocorre a system call fork -> syscall -> sendrec para PM -> int // processo usuario fica bloqueado enquanto nao recebe retorno do PM. No linux, processo usuario nao eh debugado, mesmo se compilado com opcao -g; somente o kernel eh debugado.

1.5 => apresentação dos projetos (fase 1) : grupos ímpares

2015-05-22
TRAZER: apresentacao em powerpoint relatorio; enviar para mim via email no dia da apresentacao. relacionar a apresentacao com o codigo do linux e minix quando apropriado.

Se sobrar tempo: Filme: https://www.youtube.com/watch?v=iBVgcjhYV2A Revolution OS https://www.youtube.com/watch?v=xHu7qI1gDPA

1.6 - apresentação dos projetos (fase 1) : grupos pares

2015-05-26

1.7 2.1 introdução aos processos

2015-05-29
transparencias "Processes and Threads". 1-24. Se sobrar tempo falar sobre os exercicios que passei. resumir explicacao sobre a diferenca entre treads e processos: basta colocar as transparencias principais sobre thread de kernel e de usuário. Ao explicar sobre threads seja mais rápido em afirmar que existe uma parte que cuida da execucao (PC, registradores, ponteiro de pilha) e outra que cuida dos recursos (memoria, arquivos). process group - lidar com signals de processos em foreground e background. Serah que eh usado muito hoje em dia com o X-windows? group id. Coloquei tudo em um desenho: vetor de interrupcao e tabela de processos.

1.8 2.2 comunicação interprocesso até semaforos

2015-06-02
transparencias "interprocess communication", 1-10,11 Solucao de Peterson: 3 casos: 1- a regiao critica eh acessada em momentos diferentes - sem problema 2- a regiao critica serah acessada quase ao mesmo tempo, mas nao hah conflito em enterregion (o processo 0 ou 1 nao chaveia em enterregion) - sem problema. 3- a regiao critica serah acessada quase ao mesmo tempo e hah conflito em enterregion: o último a fazer turn=process eh o que fica em loop e nao entra na regiao critica.

Sleep and Wakeup Para pensar:

  • explique a perda de wakeup com o buffer cheio.
  • como corrigir o código adicionando uma flag informando que o sinal foi perdido?

Semáforos: Explicar como exclusao mutua pode ser feita usando semáforos. Mostrar o caso em rede de Petri.

1.9 de semaforos a 2.3 problemas clássicos de CIP

2015-06-09
A aula retoma o que seja o up e o down em semaforos. transparencias "interprocess communication", 11-25 explicar exclusao mutua com semaforos modelado em redes de Petri. explicar semaforos para resolver o problema do consumidor produtor.

static class: a declaracao permite que uma classe declarada dentro de outra seja visivel fora da classe-pai.

wait( ) tells the calling thread to give up the monitor and go to sleep until some other thread enters the same monitor and calls notify( ). notify( ) wakes up the first thread that called wait( ) on the same object. notifyAll( ) wakes up all the threads that called wait( ) on the same object. The highest priority thread will run first. Monitores, condition variables: http://en.wikipedia.org/wiki/Monitor_%28synchronization%29

1.10 2.4 agendamento de processo + problema reader/writer.

2015-06-12
Transparencias "scheduling - introduction to scheduling"

Explicar melhor o conflito no batch system entre turnround time e throuput. Ao colocar jobs mais curtos na frente diminuo o tempo de retorno medio (mean turnround time) pg 109 - minix3. Ao colocar jobs mais curto na frente aumento a vazao, pg 107; porem posso ter tempos de retorno terriveis para processos longos.

Expliquei micro kernel e semaforos no minix preparando para a prova.

1.11 => Projetos 2.5 visão geral de processos em minix (fase 2)

2015-06-16
equipes pares

1.12 => Projetos 2.5 visão geral de processos em minix (fase 2)

2015-06-19
equipes ímpares

1.13 prova 1

2015-06-23

1.14 3.1 Hardware Entrada e Saida 3.2 Software Entrada e Saida

2015-06-26
Transparencias do silberschatz capitulo 13. http://codex.cs.yale.edu/avi/os-book/OS7/os7c/slide-dir/ch13.ppt até 13.16

1.15 3.2 Software Entrada e Saida

2015-06-30
Transparencias do silberschatz capitulo 13. http://codex.cs.yale.edu/avi/os-book/OS7/os7c/slide-dir/ch13.ppt do slide 13.17 até o final. pula a parte de streams.

1.16 3.3 impasses

2015-07-03

1.17 => Projetos 3.4 visão geral de E/S no minix (fase 3)

2015-07-14
equipes ímpares

1.18 => Projetos 3.4 visão geral de E/S no minix (fase 3)

2015-07-17
equipes pares

1.19 4.1 gerenciamento básico de memória 4.2 troca (swap)

transparecias - chapter 4; 1-11 (mos2-ppt.zip) 2015-07-07
-> Como gerenciar memória no evaluator 7t que nao possui MMU?

  • para deixar a aula mais interessante deveria comentar como funcionamento o gerenciamento de memoria no minix sem usar a memoria virtual.

-> dar a aula rapidamente e depois comentar o que eh cada exercicio da fase 4 no final da aula; enfatizando principalmente os exercicios que envolvem o minix.

1.20 4.3 memória virtual, 4.4 algoritmos de substituição de página.

2015-07-21
transparencias - chapter 04 (mos2-ppt.zip); 12-20 (troca otimo), 32 (comparar FIFO com otimo). Inverted page tables http://www.cs.nmsu.edu/~pfeiffer/classes/573/notes/ipt.html geralmente a tabela de páginas é uma por processo, mas no caso da inverted page table, não. Nesse caso, a memória RAM está dividida em páginas sendo algumas para um processo, outras para outro processo, etc. A inverted page table mapea essa RAM atribuida a vários processos. Funciona graças aa TLB que armazena as entradas da tabela de paginas. No maximo ateh algoritmo de troca otimo.

Eh possivel dar a anomalia de Belady usando o algoritmo otimo? Fazer uma simulacao.

1.21 4.4, 4.5 questões para sistemas de paginação.

2015-07-24
termina algoritmos de troca tanenbaum transparencias vitural memory (2) 21-31 exercicio 4.12 pg 442

Comentar sobre o algorimto worst e como ele pode ser usado para avaliar outros algoritmos pois dah uma piso minimo.

1.22 4.6 segmentação

2015-07-28

  • De final de working set ateh segmentacao.
  • memória Linux.

http://www.youtube.com/watch?v=NtKAG46_3Vg - memoria linux http://kerneltrap.org/node/2450/ memoria linux http://www.youtube.com/watch?v=L2SED6sewRw - desenvolvimento do kernel Item 21.6.2 do Silberschatz

Fazer um grande desenho procurando resumir tudo o que foi ensinado ateh agora em SO.

  • colocar um mapa geral de um SO - hw e sw.

– hw - MMU, TBL, e page fault . – sw. - interrupcoes em geral, mas acrescentando com as page faults, colocar a transparencia da interrupcao de page fault e relacionar na figura com os algoritmos de troca de paginas..

1.23 => Projetos 4.7 visão geral do gerenciamento de memória do minix (fase 4)

2015-08-07
equipes pares

1.24 => Projetos 4.7 visão geral do gerenciamento de memória do minix (fase 4)

2015-08-14
equipes impares.

1.25 5.1 arquivos 5.2 diretórios 5.3 implementação do sistema de arquivos

2015-07-31
ateh inodes. transparencias Chapter06 - 1-21 Finalizar com: Qual o tamanho maximo do arquivo? transparencia de i-node no unix.

1.26 5.3 implementação do sistema de arquivos

2015-08-04
terminar sistemas de arquivos

  • discutir o gerenciador de arquivos no minix. (cap 5 do projeto e implementacao).

1.27 => Projetos 5.6 visão geral do sistema de arquivos minix (fase 5)

equipes impares

1.28 => Projetos 5.6 visão geral do sistema de arquivos minix (fase 5)

equipes pares

1.29 prova 2

2015-08-11

1.30 revisao p2.

2015-08-18
revisao p2

2 Livro texto:

Sistemas Operacionais - Projeto e Implementação ; Tanenbaum A.S. Woodhull A.S.; Bookman terceira edição Obs: Este livro contém o Minix que serviu de base para a criação do Linux, mas a versão atual é a 3.0.

Bons Livros de apoio:

  • Sistemas Operacionais Modernos 3a. 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, porém não usa um sistema operacional próximo da realidade, usa apenas pequenos exemplos em java; e provavelmente o aluno perde a noção do sistema operacional como um todo.

Sobre Linux: Robert Love, Linux Kernel Development Understanding the Linux Kernel – Publisher: O'REILLY http://www.google.com/books?q=isbn%3A978-0-596-00565-8 Linux Kernel in a Nutshell – Publisher: O'REILLY: http://www.kroah.com/lkn/ UNIX Internals: The New Frontiers – Author: Uresh Vahalia http://www.google.com/books?q=isbn%3A9780131019089 Design of The Unix Operating system – Author: Maurice J.Bach http://www.google.com/books?q=isbn%3A9780132017992 Professional Linux Kernel Architecture [Paperback] Wolfgang Mauerer (Author)

Cursos http://www.cs.berkeley.edu/~kubitron/courses/cs162-F10/

3 Criterio de Avaliação:

O aluno deve ter mais que media 5 nas provas e nos trabalhos.

Nota final = (3 P1 + 4 P2 + 3 P)/10

Caso nao tenha, a nota a ser lançada eh a menor delas. Exemplo: se o aluno tirar como notas de prova, 3 e 5 entao terah como media de nota de prova (3*3 +4*5)/7 = 4,1 que serah a media a ser lancada como nota final independentemente de ter tirado 10 nos trabalhos.

Nota final = (3 P1 + 4 P2)/7

4 Grupos para os projetos.

  1. Isabel, André Amaral, Pedro Santana, Rafael Ring
  2. Felipe Cardoso, Felipe Jun, Joao Batista, Rafael Freitas.
  3. Cesar Rodrigues, Filipe Arena, Pedro Martinez, Saulo de Tarso

-> 4. Ivan Diego, Vinicius, Felipe Paiva -> saiu o Felipe Paiva.

  1. Alan Raso, Caio Felipe, Eduardo Levy, Mayer Levy
  2. Fabio Chu, Marcos Teruaki, Matheus Yukio
  3. David Wen, Jean Luc, Jonathan
  4. Filipe Koji, Tiago Ryu, Guilherme Job.

5 Criterios de avaliacao.

  • tempo: 20 minutos por equipe, com 5 minutos para perguntas.
  • usar powerpoint para explicar o que foi feito.
  • apresentar o sistema rodando ao vivo (muito importante!!!) (caso contrário 1 ponto a menos no mínimo na nota).
  • entregar um relatorio em pdf no dia da apresentacao. Serah descontado um ponto por dia de atraso na entrega do relatorio.

O relatório e apresentacao em powerpoint devem conter: a. todos os passos para desempenhar a tarefa com referencias caso houver (a sites, livros, etc.). b. print screens da tela - geralmente da maquina virtual. A nota costuma ser dividida entre os alunos que apresentarem o trabalho em pesos iguais; porém os pesos podem ser alterados a critério dos alunos. 8 - bom; o aluno fez o esperado. 10 - melhor que o esperado. cada equipe deve entregar o relatorio no dia da apresentacao via email; cada dia de atraso corresponde a um ponto a menos.

6 Fase 1:

Objetivos gerais: . existem dois grandes tipos de sistemas operacionais: microkernel (minix) e monolítico (linux). Algumas equipes trabalharao com o minix e outras com o linux, de tal forma que os alunos possam comparar ambos. . criar processos de usuários que facam chamadas de sistema e observar como elas se comportam. . system call faz com que o processador passe do modo usuário para o modo kernel. Como isso ocorre? É possível visualizar isso? . dados do kernel sao mais difíceis de serem visualizados por processos comuns. Como o "ps" e "top" visualizam dados do kernel? Através de /proc. . fazer pequenas alteracoes no kernel. Exemplo: fazer o kernel imprimir uma mensagem em um dado momento.

Tarefas:

8 equipes: 4 minix e 4 linux.

-> Linux 4 equipes farão testes baseados em

http://balau82.wordpress.com/2010/03/22/compiling-linux-kernel-for-qemu-arm-emulator/

A idéia é criar um programa bem simples rodando como o init (primeiro processo rodando em cima do sistema operacional) em um linux rodando na máquina virtual. Esse processo pode disparar system calls. Cada uma das equipes testará uma system call diferente. O grande objetivo é observar o código do kernel sendo executado logo após a system call.

-> Minix Instalem o minix 3.1 em uma máquina virtual pois é a versão compatível com o livro e portanto com mais documentação. A imagem iso (ex: minix-3.1.0-book.iso na internet) deve ser bootada pela maquina virtual (ex: virtual box). Uma vez que ela logou entre com: root, e siga http://wiki.minix3.org/en/UsersGuide/DoingInstallation isto é: setup e vai seguindo praticamente só dando enter. Não se esqueca de usar a rede. Usei AMD Lance. Ao terminar o setup, faca: shutdown

Desligar e comecar novamente a maquina virtual MINIX3 mas com a imagem iso fora (remova da maquina virtual a imagem iso do disco para ver bootando pelo HD).

Observando https://groups.google.com/forum/#!topic/minix3/tSvzp81M8_o Ativando a rede: teste ifconfig - vc. pode observar /dev/ip /bin/service up /usr/sbin/inet

O minix 3.1 dentro da máquina virtual pode se comunicar via tcp/ip com o host - windows ou linux. É possível abrir um servidor de FTP de forma que o host enxergue todo o filesystem do minix. Isso possibilita navegar pelo código fonte do minix, bem como fazer alterações no código através do seu editor de texto preferido dentro do host.

6.1 1 - Linux, system call: read

Altere o boot do linux apresentado em http://www.pcs.usp.br/~jkinoshi/2012/linux-qemu-gdb.org de forma a se ter um processo (correspondente ao init) executando a system call read. Para isso altere o rootfs e crie arquivo lá. O boot lerá a primeira linha do arquivo e ficará em loop imprindo-a. Quando a system call read é chamada no linux, a funcao doread é executada dentro do kernel. Explique como isso ocorre, observando o código fonte do linux e o tutorial em http://www.pcs.usp.br/~jkinoshi/2012/linux-qemu-gdb.org . Localize no código do linux onde é feito o SWI - software interrupt. Dica: use o grep. Da forma como estamos debugando o código podemos apenas observar código em modo kernel e não em modo usuário. Procure colocar o breakpoint o mais perto possível da instrucao SWI; se possível logo na primeira instrucao após o SWI. Relacione o endereco dessa primeira instrucao com o vetor de interrupcao. Gere um relatório anexando apenas as partes de código mais relevantes e relacionadas com o SWI, bem como print screens da tela do qemu.

10 > boa apresentacao e bom trabalho. Observaram em entry-common.c o registrador r7 escolhendo a rotina a ser chamada; bem como todas as system calls com seus numeros em calls.s

6.2 2 - Linux, system call: fork

Altere o boot do linux apresentado em http://www.pcs.usp.br/~jkinoshi/2012/linux-qemu-gdb.org de forma que: O processo pai (correspondente ao init) fica imprindo "sou processo 1" e o processo filho imprime "filho imprimindo". Quando a system call fork (veja o código que implementa fork) é chamada no linux, a funcao dofork é executada dentro do kernel. Explique como isso ocorre, observando o código fonte do linux e o tutorial em http://www.pcs.usp.br/~jkinoshi/2012/linux-qemu-gdb.org . Localize no código do linux onde é feito o SWI - software interrupt. Da forma como estamos debugando o código podemos apenas observar código em modo kernel e não em modo usuário. Procure colocar o breakpoint o mais perto possível da instrucao SWI; se possível logo na primeira instrucao após o SWI. Relacione o endereco dessa primeira instrucao com o vetor de interrupcao. Gere um relatório anexando apenas as partes de código mais relevantes e relacionadas com o SWI, bem como print screens da tela do qemu.

10 > boa apresentacao e bom trabalho. Observaram em entry-common.c o registrador r7 escolhendo a rotina a ser chamada. Mostraram a instrucao LDR que altera o PC para a chamada da funcao com base em R7

6.3 3 - Linux, system call: execve (ou exec)

Altere o boot do linux apresentado em http://www.pcs.usp.br/~jkinoshi/2012/linux-qemu-gdb.org de forma que: O processo pai correspondente ao init faz fork e fica imprindo "sou processo 1". O processo filho faz execve e executa o código do filho. O filho imprime "filho imprimindo". O programa correpondente ao processo pai deve estar em pai.c e o correspondente ao filho em filho.c. Os programas pai e filho devem ser previamente armazenados em rootfs através de execve. Quando a system call exec é chamada no linux, a funcao doexec é executada dentro do kernel. Explique como isso ocorre, observando o código fonte do linux e o tutorial em http://www.pcs.usp.br/~jkinoshi/2012/linux-qemu-gdb.org. Localize no código do linux onde é feito o SWI - software interrupt. Da forma como estamos debugando o código podemos apenas observar código em modo kernel e não em modo usuário. Procure colocar o breakpoint o mais perto possível da instrucao SWI; se possível logo na primeira instrucao após o SWI. Relacione o endereco dessa primeira instrucao com o vetor de interrupcao. Gere um relatório anexando apenas as partes de código mais relevantes e relacionadas com o SWI, bem como print screens da tela do qemu.

5> Cesar estava doente, 0. Nao conseguiram, mas apresentaram a ideia de como deveria ter funcionado.

6.4 4 - Linux, system call: write

Altere o boot do linux apresentado em http://www.pcs.usp.br/~jkinoshi/2012/linux-qemu-gdb.org de forma que ele faca um "write" em algum arquivo no rootfs. Quando a system call fork (veja o código que implementa write) é chamada no linux, a funcao dowrite é executada dentro do kernel. Explique como isso ocorre, observando o código fonte do linux e o tutorial em http://www.pcs.usp.br/~jkinoshi/2012/linux-qemu-gdb.org . Localize no código do linux onde é feito o SWI - software interrupt. Da forma como estamos debugando o código podemos apenas observar código em modo kernel e não em modo usuário. Procure colocar o breakpoint o mais perto possível da instrucao SWI; se possível logo na primeira instrucao após o SWI. Relacione o endereco dessa primeira instrucao com o vetor de interrupcao. Gere um relatório anexando apenas as partes de código mais relevantes e relacionadas com o SWI, bem como print screens da tela do qemu.

10> Ivan, 5 - nao apresentou. Relacionaram como os registradores foram renomeados no codigo como o R7 sendo chamado de scno.

6.5 5 - minix, system call read

Altere o minix de forma que:

  • o init execute a system call read. Imprima uma mensagem na console quando isso ocorre.
  • o servidor deve imprimir uma mensagem assim que executar tal system call.

7> nao mostraram adequadamente como o servidor FS atua quando ocorre a system call read.

6.6 6 - minix, system call fork.

Altere o minix de forma que:

  • o init execute a system call fork. Imprima uma mensagem na console quando isso ocorre. Faca o processo pai imprimir uma mensagem e o processo filho imprimir outra mensagem.
  • o servidor deve imprimir uma mensagem assim que executar tal system call.

7.5> Fizeram alguns testes basicos para conhecerem melhor o minix, como criando um forktest.c que compilaram a parte e viram rodando. Talvez eu devesse pedir algo mais nessa linha para o ano que vem.

6.7 7 - minix, system call execve

Altere o minix de forma que:

  • o init execute a system call fork e depois o processo filho executa o "execve". Crie o codigo do processo filho no sistema de arquivos de tal forma que ele imprima uma mensagem.
  • o servidor deve imprimir uma mensagem assim que executar tal system call.

6+1 = 7> Infelizmente, nao conseguiram rodar bem… Talvez se tivessem criado um teste a parte do init… Conseguiram rodar depois.

6.8 8 - minix, system call write

Altere o minix de forma que:

  • o init execute a system call write.
  • o servidor deve imprimir uma mensagem assim que executar tal system call.

7> faltou mensagem de dentro do servidor FS.

7 Fase 2

4 experiencias envolvendo Linux e 4 Minix.

Objetivos gerais: observar topicos do cap. 2 do livro do minix tanto no linux quanto no minix.

Linux

7.1 1 `- semáforo.

Em http://www.linuxdevcenter.com/lpt/a/7029 temo a apresentacao de threads em modo usuario usando semaforos; porem versoes de semaforos para threads sem fazer chamadas de sistema. Em http://www.cis.upenn.edu/~lee/07cis505/Lec/SemaphoreOperations.pdf temos o uso de semaforos fazendo chamadas de sistema - semop.

Altere o init para fazer algo como:

if (fork() ) {
   while (1) {
      print "1"
      down(S) 
      print 2
      up(S)
      print 3
   }


} else {
  while (1) {
      print "A"
      down(S)
      print X 
      print B
      up(S)
      print C
   }
}

trocando up e down pelo semop. O valor do semáforo é gerenciado pelo kernel porque duas ou mais threads podem estar alterando o seu valor e o kernel deve evitar condicoes de corrida nessas alteracoes. Coloque um breakpoint para observar como o kernel altera o valor do semáforo e retire print screens. Vamos supor que uma thread A fique bloqueada aguardando o incremento do semáforo por outra thread B. No momento em que a outra thread B pedir ao kernel para incrementar o semáforo, o kernel deve desbloquear a thread A. Analise o código do kernel do linux e descubra onde isso ocorre. Coloque um breakpoint nessa posicao, rode o gdb até essa posicao, retire um printscreen. Analise a fila de execucao dos processos. Para isso será necessário estudar http://isis.poly.edu/kulesh/stuff/src/klist/ para entender como o kernel do linux gerencia listas. Motre o processo bloqueado no down e sendo desbloqueado pelo up. Verifique que no "up", o processo bloqueado é retirado da fila do semáforo e vai para a fila dos processos prontos. Ver o codigo do spin lock no kernel no up e no down. Encontre o código onde o processo desbloqueado é colocado na fila do escalonador.

10 > boa apresentacao e bom trabalho, viram o valor do semaforos sendo modificado dando break; entretanto eh possivel visualizar a fila do semaforo e a runqueue?

7.2 2 - signal

Entenda o seguinte código:

#include<stdio.h>
#include<signal.h>
void bypass_sigint(int sig_no)
{
  printf("dividi por zero\n");
}
int main()
{
  int a,b,c;
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = &bypass_sigint;
    sigaction(SIGFPE, &sa,NULL);
    while (1) {
      sleep(1);
        printf("do nothing \n ");
    }
    return 0;
}

Esse código ativa a funcao sigint toda vez que houver uma divisão por zero. Mas um outro processo pode enviar um signal, dizendo que houve uma divisão por zero. Experimente em uma outra shell fazer: kill -8 #pidprocesso

onde -8 se refere a SIGPFE, divisão por zero. Para você realmente observar que houve uma divisão por zero, experimente colocar dentro do código, após sigaction:

a = 1; b= 0; c = a/b;

e veja que a rotina imprime "dividi por zero".

Experimente em uma outra shell fazer: kill -8 #pidprocesso

Como o linux trata a divisão por zero? Explique o código. É de se esperar que o linux envie um signal para o processo que fez a divisão por zero. Faça um programa executável que faz a divisão por zero no linux rodando no qemu. Rode o programa e capture o signal imprimindo na tela uma mensagem toda vez que for feita a divisão por zero. O kernel contém uma estrutura de dados guarda o signal handler do processo. Observem a estrutura de dados dentro do kernel que mostra a que sinais estao associados quais handlers.

Estude o código que trata sigaction(SIGFPE, &sa,NULL); e observe qual é essa estrutura de dados. Quando ocorrer a divisão por zero, essa estrutura de dados será usada para ativar o signal handler ( bypasssigint) adequado. Faça um print screen do qemu logo ao entrar na rotina que faz o tratamento da divisão por zero (observando qual é o endereco da rotina a ser executada dada pelo vetor de interrupcao do ARM - pesqui sobre isso). Realmente eh possivel que um processo A envie um signal a um outro processo B (através do kill), fazendo com que B ache que houve uma divisão por zero dentro do linux? O que acontece desde a interrupcao gerada pela divisao por zero ateh a chamada da rotina bypasssigint (signal handler)? Como o SO fica sabendo qual é o signal handler que deve ser chamado?

Observe o seguinte: quando existe a divisao por zero no programa, ou seja, quando o codigo a = 1; b= 0; c = a/b; eh executado, o signal handler eh executado mas retorna para antes da divisao ser feita. Isso faz com que c = a/b seja executado infinitamente pois a instrucao a/b eh sempre colocada novamente para rodar após o signal handler ser executado. Uma forma de resolver isso eh criar um signal handler que retorna para a instrucao posterior no caso de SIGFPE acessando a pilha em assembly (Ver 'man 2 signal').

8> bom, mas tem que localizar no codigo onde o kernel associa o signal handler ao processo.

7.3 3 - escalonador diferente

Objetivo: No projeto anterior, a equipe 3 alterou o init e criou o processo pai e filho que ficaram imprimindo mensagens; porém ele ficava um tempo imprimindo mensagens do pai e um tempo imprimindo mensagens do filho. O printf faz uso da system call write; porém quando o write é chamado o processo não é chaveado (isto é, por exemplo, após a syscall write, o processo pai volta ao processo pai). Altere o kernel do linux 2.6.39 de forma que o escalonador troque de processo na chamada da system call write. Para isso:

7.3.1 Com funciona o escalonador

http://www.ibm.com/developerworks/library/l-completely-fair-scheduler/

Antes de alterar o escalonador, faca o seguinte e apresente ao professor:

7.3.2 listas no kernel

Estude como funciona as listas no kernel do linux. Elas fazem uso de: struct listhead Veja: http://isis.poly.edu/kulesh/stuff/src/klist/ . Estude essa pagina, compile e debugue testlists.c para observar como os itens sao adicionados e removidos na lista; ou ainda, como a lista pode ser percorrida. Dentro de testlists.c existe o comentário:

/* at this point: pos->next points to the next item's 'list' variable and 
 * pos->prev points to the previous item's 'list' variable. Here item is 
 * of type struct kool_list. But we need to access the item itself not the 
 * variable 'list' in the item! macro list_entry() does just that. See "How
 * does this work?" below for an explanation of how this is done.
 */

Rode o código passo a passo no gdb e observe a estrutura mylist através de comandos como: p mylist->list->next->next->next Após isso, explique com suas palavras o significado do comentário acima.

Em particular observe:

Dentro do kernel, em fork.c existe: struct taskstruct *p; que contém a informacao sobre o processo sendo criado.

Essa estrutura é preenchida e depois é colocada em uma runqueue (fila de execucao) (em sched.c). Onde isso ocorre no código? Procure rodar o código até que o linux faca um listadd colocando o processo uma runqueue. Retire printscreens da tela. Explique as filas de execucao do linux e porque escolheu uma determinada fila para colocar o processo para rodar.

Podemos imprimir mensagens de dentro do linux kernel em um log. Veja: http://www.ibm.com/developerworks/linux/library/l-kernel-logging-apis/index.html

7.3.3 Altere o kernel

No minimo, faca uma alteracao em picknexttaskfair de forma a retirar sempre o processo que estah rodando da fila de execucao. Eh uma modificacao muito simples que nao funciona a ponto de estar sempre chaveando os processos pai e filho a cada impressao.

6.5 > infelizmente nao conseguiram fazer o escalonador alternar. Pedi para apresentar como a red black tree estah sendo usada dentro do codigo, mas a apresentacao tambem nao entrou bem no codigo…

7.4 4 - chaveamento dos processos.

Usando qemu rodando o linux compilado para o Versatile, faca com que o linux rode apenas um processo: o processo que continuamente le caracteres do teclado (usando getchar() e os imprime na tela. Coloque um breakpoint na interrupção de teclado. Faça um print screen do qemu mostrando a primeira instrução logo ao entrar no tratamento de interrupção do teclado. Relacione o valor do endereço que você vê, com o manual do ARM7 (consulte na internet como o ARM trata interrupcoes de hardware; veja tambem a apostila usada no laboratorio de microprocessadores). Onde (em qual arquivo fonte do linux) o estado do processo é armazenado? Relacione isso com o código do linux e explique. Ao sair da rotina de interrupção, um outro processo foi escalonado para rodar? Qual processo? Apresente um print screen dos registradores antes de sair da interrupção. Como ao sair da interrupção, o novo processo passa a rodar? Com que Program Counter? Explique. Após a syscall getchar, o processo é bloqueado enquanto nada é teclado. Mostre como o processo é bloqueado (retirado da fila de execucao e colocado em uma outra fila para esperar o caracter). Após o caracter ser teclado, ocorre a SWI, e o processo é então desbloqueado. Mostre como isso ocorre. Retire os printscreens mostrando isso ocorrendo e anexe no relatório.

8> bom trabalho, seria bom observar o processo sainda da runqueue e entrando na fila de processos bloqueados por causa do teclado.

7.5 5 - semáforo.

Implementar semáforos no minix. Será necessário estudar o kernel do minix, observando como manter o processo em estado bloqueado ao fazer uma operação de down. Implemente as seguintes system calls:

int inicia(int valor); exemplo: S = inicia(3); # inica um semáforo com 3 e retorna o número do semáforo em S. O número zero é reservado; se S == 0 então deu erro em inicia.

int down(int S); faz a operação de down no semáforo S; se der problema retorna -1.

int up(int S); faz a operação de up no semáforo S

int status(int S, int *valor, int *procbloqueados); coloca em valor, o valor do semáforo S e em procbloqueados, o número de processos bloqueados no semáforo.

Essas system calls devem ser implementadas pelo processo PM (antigo MM).

Dica: dado que existe apenas um processo PM, é fácil pensar que up e down serão mutualmente exclusivos pois o PM estará tratando a mensagem up ou a mensagem down não podendo tratar as duas ao mesmo tempo. Isto é: não será necessário desabilitar as interrupções para se implementar o up e o down. Como o processo usuário vai enviar uma mensagem ao PM então o estado de bloqueado pode ser conseguido, simplesmente se o PM não responder ao processo enquanto o semáforo não subir.

Declare dentro de PM uma tabela que contenha 20 linhas, uma para cada semáforo; isto é, o minix terá no máximo 20 semáforos. Em cada linha existem duas informacoes: 1. o valor de semaforo e a fila de processos bloqueados esperando o incremento do semaforo.

Para comecar a mexer com o minix, entenda como um processo usuário fica bloqueado ao executar uma system call. Primeiro o processo usuário envia uma mensagem ao servidor. Exemplo: quando o processo faz signal; uma mensagem é enviada ao PM. O processo usuário fica bloqueado enquanto o PM não responder que a system call foi completada. Portanto, a falta de resposta leva um processo de usuário a ficar bloqueado. É justamente essa característica que vamos utilizar para bloquear um processo de usuário. Para isso, como sugestão: replique uma sistem call do PM; por exemplo, o signal. Crie o signal1, cópia do signal. Retire tudo de signal1 e estude apenas como o processo PM retorna uma mensagem ao processo que solicitou o signal desbloqueando-o. Agora crie um "bloqueia" que é igual ao signal1 e não envia a mensagem de retorno e o desbloqueia que apenas envia uma mensagem ao processo que fez o bloqueio como o signal1 enviaria. Use os semáforos no programa produtor-reprodutor.

9> Conseguiram rodar, deveriam ter explicado melhor que o PM fica em loop infinito e como ele nao retornou a mensagem - ficou obscuro na apresentacao.

7.6 6 - signal

Entenda o seguinte código:

#include<stdio.h>
#include<signal.h>
void bypass_sigint(int sig_no)
{
  printf("dividi por zero\n");
}
int main()
{
  int a,b,c;
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = &bypass_sigint;
    sigaction(SIGFPE, &sa,NULL);
    while (1) {
      sleep(1);
        printf("do nothing \n ");
    }
    return 0;
}

Esse código ativa a funcao sigint toda vez que houver uma divisão por zero. Mas um outro processo pode enviar um signal, dizendo que houve uma divisão por zero. Experimente em uma outra shell fazer: kill -8 #pidprocesso

onde -8 se refere a SIGPFE, divisão por zero. Para você realmente observar que houve uma divisão por zero, experimente colocar dentro do código, após sigaction:

a = 1; b= 0; c = a/b;

e veja que a rotina imprime "dividi por zero".

Experimente em uma outra shell fazer: kill -8 #pidprocesso

Como o minix trata a divisão por zero? Explique o código. É de se esperar que o minix envie um signal para o processo que fez a divisão por zero. Se o minix não fizer isso, implemente. Faça um programa executável que faz a divisão por zero no minix rodando no bochs (http://pdos.csail.mit.edu/6.828/2006/tools.html). Rode o programa e capture o signal imprimindo na tela uma mensagem toda vez que for feita a divisão por zero. Faça um print screen do bochs logo ao entrar na rotina que faz o tratamento da divisão por zero (observando qual é o endereco da rotina a ser executada dada pelo vetor de interrupcao). Observem o codigo fonte do minix e localizem onde o endereco da funcao, o signal handler do processo do usuario, eh armazenado no PM.

Realmente eh possivel que um processo A envie um signal a um outro processo B (através do kill), fazendo com que B ache que houve uma divisão por zero dentro do minix? E no linux? O que acontece desde a interrupcao gerada pela divisao por zero ateh a chamada da rotina? Como o SO fica sabendo qual é o signal handler que deve ser chamado?

8> O signal handler eh chamado varias vezes por que ele retorna para antes da divisao por zero e nao depois. Fizeram testes no linux e observaram a mesma coisa. Conseguiram colocar o bochs para rodar no ubuntu14.4

7.7 7 - escalonador diferente

Modifique o escalonador do Minix3 para monitorar quanto tempo da CPU cada processo de usuário recebeu recentemente. Quando nenhuma tarefa ou servidor quiser executar, escolha o processo de usuário que recebeu a menor fatia de CPU.

Obs: exercicio retirado do livro do minix.

Façam testes disparando processos praticamente ao mesmo tempo ou em tempos diferentes e observem como eles se acomodam nas filas de prioridade.

7> Fizeram o trabalho acrescentando um campo sobre o tempo rodado. Seria interessante que tivessem comparado com o escalanodor normal do minix. Alias, faltou comentarios sobre o escalonador normal usando as filas de prioridades.

7.8 8 - chaveamento dos processos.

As equipes de linux estão vendo o ARM, porém o minix roda no pentium. O pentium é bem mais complexo que o ARM e o objetivo desse trabalho é estudar o chaveamento de processos no minix e sua interface com o pentium. Através da máquina virtual bochs, será possível ver o assembly do minix rodando nesse chavemento. Isso porque o bochs emula as instrucoes ao invés de executar direto no processador. Use o bochs em modo debug (deve ser compilado para isso de acordo com o lab1 do MIT http://pdos.csail.mit.edu/6.828/2006/tools.html) para estudar o minix. Veja:

  • Manuais da intel (na internet) como por exemplo: Pentium® Processor Family, Developer's Manual Volume 3: Architecture and Programming Manual.

Após a inicialização do minix, pare o minix dentro do bochs e coloque um breakpoint na interrupção de teclado. Faça um print screen do bochs mostrando a primeira instrução logo ao entrar no tratamento de interrupção do teclado. Relacione o valor do endereço que você vê, com o declarado na IDT, GDT e LDT. O minix guardará os registradores. Como o hardware e o código do minix fazem isso? Em particular, como é armazendo o Program Counter (ou Instruction Pointer, EIP)? Onde o estado do processo é armazenado? Relacione isso com o código do minix e explique. Ao sair da rotina de interrupção, um outro processo foi escalonado para rodar? Qual processo? Apresente um print screen dos registradores antes de sair da interrupção. Como ao sair da interrupção, o novo processo passa a rodar? Com que Program Counter (EIP)? Explique. Explique a funcao save chamada logo na entrada da rotina de interrupcao (rastreie usando o bochs). Como é guardado o endereco de retorno de save? Como a funcao "save" retorna? Rastreie usando o bochs. Pesquisem na internet sobre o TSS (além do IDT, GDT, LDT). Como o TSS é usado no chaveamento de processos? Expliquem as estruturas GDT e LDT. Como o EIP (program counter) eh armazenado na pilha (teriam que ver como a pilha eh setada antes do chaveamento). Rastree o retorno de save no bochs.

8 -2 (2 dias de atraso) = 6> Bom, explicaram as estruturas da intel, mas nao entraram bem no codigo. Por exemplo, mostrarm o codigo dos pushes e pops mas nao explicaram bem o que acontece por trás (o ponteiro de pilha nesse caso era extremamente importante).

8 Fase 3

Todas as turmas: apresentem rodando ao vivo.

8.1 1 Linux - dtrace, driver de video.

O dtrace é uma modificacao no kernel do linux feita orignalmente pela Sun (vendida para a Oracle) com o objetivo de facilitar o debug de aplicativos observando dados do kernel. A idéia é colocar probes (como pontas de prova) dentro do kernel e apresentar os resultados dependendo de certas circunstancias (para nao poluir a saida).

Instale o dtrace no ubuntu 14.4: https://github.com/dtrace4linux/linux

Usando o dtrace podemos monitorar as leituras e escritas em um driver. Use o dtrace para monitorar o driver de uma webcam: quantos bytes sao repassados da camera por segundo?

Explique para a classe como funciona o dtrace; aprensente scripts bem simples (por exemplo que monitora certas system calls dependendo de certas condicoes) para a classe entender. Explique o monitoramento do driver da webcam com dtrace interecptando a leitura de um frame da webcam. Retire printscreens e apresente ao vivo em sala de aula.

Sugestao: Instale o dtrace em um ubuntu 14.4 e apresente o cheese fazendo leituras da webcam. Mostre o numero de bytes que estao sendo lidos.

9> Funcionou bem, bem apresentado; o unico porem eh que nao foi explicado se havia problema no ubuntu 14.4. Fizeram no 12.4

8.2 2 Linux - construir o driver padrao no arm linux.

A partir de: http://www.pcs.usp.br/~jkinoshi/2008/Exp8_revisada_13_08_07.doc: 1 - crie um driver simples no linux normal (ex: ubuntu). 2 - crie o driver padrao e teste a leitura e escrita no driver usando "echo" na maquina virtual. O passo 1 é muito simples, porém existem diversas dificuldades para fazer o mesmo na maquina virtual/ARM:

  • como criar uma entrada no rootfs para o driver padrao? Deve ser através de system calls para se fazer o mknod. Assim, crie um init que somente irá criar uma entrada em /dev em rootfs para o driver da entrada padrao.
  • a compilacao do driver padrao para o ARM pode apresentar dificuldades. Existem duas formas de se fazer o driver padrao para o ARM - como um modulo a ser carregado ou já compilado no kernel. Experimentem recompilar o kernel com o driver padrao jah inserido no kernel. Observem algumas system calls a serem chamadas pelo init como makedev e mknod. Alterarem o Makefile em /driver para criar o driver no kernel.

10>

8.3 3 Linux - teclado

Escreva um programa que continuamente lê um caracter do teclado. Altere o driver de teclado colocando printk's toda vez que as funcoes do teclado forem chamadas; imprimindo o nome da funcao e os parametros que considerar relevantes (ex: no read, o buffer com o resultado da leitura). Anexe no relatório os printscreens do qemu. Coloque um breakpoint na funcao read do driver do teclado. Verifique através do bt (backtrace) como o driver do teclado foi chamado. Busque na internet ou em algum livro sobre linux, informacoes sobre as funcoes encontradas no backtrace.

7.5> apresentacao sofrivel, mas conseguiram colocar um breakpoint quando o usuario tecla algo. Seria interessante no futuro desenvolver mais sobre a struct serio.

8.4 4 Linux - escalonador de I/O

Para treinar, faca um processo que fique num loop lendo e escrevendo os caracteres que se digita. Veja se isso funciona no versatile emulado. Crie um init que crie 3 processos e cada processo faz um getchar. Os 3 processos ficam bloqueados esperando com que o usuario tecle algo. Quando o usuario teclar, um dos processos eh desbloqueado pois recebe o caracter digitado. A escolha desse processo eh feita por um escalonador. Existem diversos tipos (4 tipos) de I/O schedulers. Faca um explicacao sobre os I/O schedulers para a classe. Localize no codigo do kernel que I/O scheduler eh chamado para decidir qual dos 3 processos eh colocado no estado de pronto quando o usuario tecla algo (sai de uma fila e vai para outra), coloque breakpoints e apresente para a classe.

Vinicius 10, Ivan nao apresentou 0> Os I/O schedulers servem para dispositivos de bloco como o disco. Altermaos o projeto para observar quando se colocar e retira da fila do I/O - teclado serial - observando add.wait.queue e remove. wait.queue. Um dos parametros dessas rotinas eh a propria queue que poderia ter sido analisada melhor.

8.5 5 MINIX: porta paralela.

Em uma experiência de laboratório trata do driver da porta paralela: http://www.pcs.usp.br/~jkinoshi/2007/2031e9.doc Através dessa experiência podíamos escrever caracteres no display da ALFACOM. Vamos criar /dev/pp e associar um driver do minix, baseado em driver padrão adaptado para o minix a partir de http://www.pcs.usp.br/~jkinoshi/2005/Exp8_revisada_13_08_04.doc que faça: echo "AB" > /dev/pp faz o caracter hexa "AB" ser colocado nos pinos da paralela. Já fizemos trabalhos com essa idéia. Use relatório antigos apenas como base apenas para adaptar ao minix novo. Dependendo da maquina virtual, voce terah que fazer uma adaptcao (talvez um script monitorando um arquivo onde a maquina virtual coloca a saida da impressora) para observar a saida da porta paralela.

Obs: Trate o valor do caracter hexadecimal para colocar nos pinos da impressora. Isto é: "AB" deve significar que o binário 0b10101011 será enviado para a paralela.

8> nao entenderam bem o protocolo da porta paralela diferenciando em dados e controle. Conseguiram no vmware, mas nao foi bem no virtual box.

8.6 6 MINIX: Driver de teclado

O objetivo é estudar o driver de teclado e como ele se comunica com o restante do kernel do minix. Para isso responda:

  • quais sao as mensagens que o driver de teclado trata?
  • como o driver de teclado lida com a interrupcao de teclado (recebe uma mensagem quando ocorre uma interrupcao - explique como a mensagem é gerada e como é tratada)?
  • como o driver notifica o microkernel de que deverá receber uma mensagem a cada interrupcao de teclado?
  • como o driver repassa o código teclado para cima? Qual é o processo que le dados do teclado?

Faca uma alteracao no minix de forma a imprimir mensagens toda vez que o driver do teclado receber uma mensagem e toda vez que o driver enviar uma mensagem. Imprima qual é o processo com que a mensagem é trocada (enviada ou recebida). Com base nisso, coloque no relatorio como funciona o getch() no minix.

7.5> usaram a ttytask (e nao o driver do teclado diretamente). Imprimiram muitas mensagens mas elas ficaram embaralhadas e deveriam ter filtrado observando as mensagens (processos origem e destino).

8.7 7 MINIX: Levante as mensagens trocadas entre o FS e o driver do disco, desde a inicializacao, durante a leitura de um determiado arquivo.

Escolha um arquivo pequeno e bem simples. Você pode se basear no trabalho do grupo do Pedro, Wilson, Hélio ( http://www.pcs.usp.br/~jkinoshi/2008/projs/r5-pedrodaquino.zip) para levantar as mensagens trocadas entre FS e driver. Como o FS mapeia um arquivo no disco? Certifique-se de observar as mensagens que o FS (VFS) envia e recebe do driver e as mensagens que o driver envia e recebe do FS. O trabalho de 2008 usou um kernel extremamente diferente do kernel atual. Tomem cuidado para imprimir todas as mensagens correspondentes ao trabalho de 2008 (mostrando as mensagens trocadas entre o FS/VFS e o driver). Através desse trabalho vamos entender melhor como o driver se comunica com o resto do sistema operacional. Obs: Nao esqueca de monitorar a comunicacao com o driver do HD.

4> nao funcionou! a monitoracao do driver nao ficou boa…

8.8 8 MINIX: driver padrão.

A experiência 8 do lab. de microprocessadores: http://www.pcs.usp.br/~jkinoshi/2005/Exp8_revisada_13_08_04.doc tem como objetivo apresentar o que é um driver em linux. Em linux, um driver é um conjunto de rotinas que implentam funções padronizadas como "read" e "write". No caso do minix, um driver é um processo que responde a mensagens padronizadas. Crie um driver muito simples em minix que apenas imprime mensagens quando recebe mensagens padronizadas de outro processo. O driver pode ser associado a /dev/teste. Declare /dev/teste associando um major e minor number e o código do processo associado ao driver. Use "service" para rodar o driver. Gere um relatório sobre isso. As mensagens que o driver deve responder são as mesmas que o driver da impressora respondem, ou seja:

*    m_type      TTY_LINE   PROC_NR    COUNT    ADDRESS
* |-------------+---------+---------+---------+---------|
* | DEV_OPEN    |         |         |         |         |
* |-------------+---------+---------+---------+---------|
* | DEV_CLOSE   |         | proc nr |         |         |
* -------------------------------------------------------
* | HARD_INT    |         |         |         |         |
* |-------------+---------+---------+---------+---------|
* | SYS_EVENT   |         |         |         |         |
* |-------------+---------+---------+---------+---------|
* | DEV_WRITE   |minor dev| proc nr |  count  | buf ptr |
* |-------------+---------+---------+---------+---------|
* | CANCEL      |minor dev| proc nr |         |         |
* -------------------------------------------------------

0

Envie mensagens a /dev/teste como em:

echo "lixo" >  /dev/teste

e veja a mensagem que é impressa pelo seu driver. Faça o driver imprimir a string que recebeu ("lixo"). Em 2008, tivemos a seguinte resposta para o problema acima: http://www.pcs.usp.br/~jkinoshi/2008/projs/r3-pedrodaquino-Relatorio3.pdf. Vamos chamar esse driver de driver-padrão e foi feito para uma versão antiga do minix. Refaça o driver teste para o minix atual. Dado que esse trabalho não é complexo, por favor use de fato o minix atual e nao versoes antigas.

8> o projeto em si nao era complexo, mas nao conseguiram apresentar bem e funcionar bem.

9 Fase 4

9.1 1 linux - page fault.

Existem formas de se ver processos gerando page faults no linux. Exemplo: http://www.ewhathow.com/2013/09/how-to-identify-page-faults-on-linux/ Crie um programa em C que gere muitas page faults em um linux normal (idéia: que esteja continuamente alocando muito memória para si). Monitore esse programa para observar se de fato tem gerado muitas page faults. (http://www.linuxjournal.com/article/8178) No linux/arm/qemu coloque o mesmo programa para rodar como init. Coloque um breakpoint no tratamento da page fault. Veja como uma pagina é colocada na tabela de páginas, procure entender o código e explique. A tabela de páginas depende da MMU do ARM. Por isso, a parte do kernel que lida com a MMU tem que estar em assembly. Localize e apresente isso no kernel do linux. Usando a opcao "x" do arm-elf tentem observar a struct page.

8> tentaram bem observar major page faults criando matrizes gigantescas, mas nao o programa nao rodou por usar muita memoria. Seria bom analisar estruturas dentro do kernel referentes aa tabela de paginas.

9.2 2. LINUX/ARM - memória compartilhada.

Em um linux normal (ex: ubuntu), crie uma area de memoria compartilhada por dois processos diferentes no linux (veja mmap) e transfira dados usando essa área de memória. O endereco virtual onde estah essa area compartilhada eh o mesmo para os dois processos? Estude como voce pode verificar isso no linux. Usando ferramentas do linux, visualize essa área de memória compartilhada (veja /proc). Faca testes para verificar qual o maximo de área de memória possível compartilhada entre ambos os processos.

No Linux/Versatile faca com que o init crie dois processos com área de memória compartilhada. Coloque um breakpoint na entrada dessa system call, bem como em outras posicoes. Retire uns printscreens do bt (backtrace); isto é, para descobrir que funçoes do kernel sao chamadas para executar essa system call. Busque referencias na internet e livros para explicar como o kernel do linux faz a memória compartilhada.

9.5-1 = 8.5> usaram shmget (versao mais antiga) .

9.3 3. LINUX DLL

Crie uma funcao que apenas soma dois numeros quando chamada e coloque essa funcao numa Dynamically Linked "Shared Object" Libraries: (.so). Crie dois processos que utilizam essa mesma funcao. Descubra uma ferramenta no linux que permite visualizar quais sao as DLLs carregadas no linux. Ative os dois processos e observe se a DLL está carregada. Voce pode rodar cada programa em uma shell diferente. Descubra em que parte da memória foi carregada a DLL (dica: veja /proc). Esses enderecos virtuais de memoria onde a DLL foi carregada sao os mesmos para os dois processos que compartilham a DLL? Agora altere a funcao para que ela tenha um estado interno; ou seja, ao inves de somar dois numeros; faca com que a funcao apenas incremente alguma variavel interna a ela. Rode os dois processos fazendo com que um numero seja incrementado a cada "enter" do usuário. Isso funciona? É possivel que a DLL guarde valores proprios? Talvez não seja possível, procure comprovar isso. Observe que existem dois tipos de bibliotecas : dinamicas e carregáveis (as dinamicas precisam do comando ldd para carregar primeiro a biblioteca e depois executar o codigo). As loadble verificam se estah na memoria, se não estiver jah sai carregando. Experimente usar os dois tipos de biblioteca. Nao eh necessario colocar no arm+qemu pois eh muito mais facil fazer testes direto no ubuntu.

7-3=4> nao apresentaram os dois tipos de bibliotecas - dinamicas e carregaveis.

9.4 4. LINUX slab/slub allocator

Procure na internet e livros sobre o alocador slab/slub; uma referência é: http://www.secretmango.com/jimb/Whitepapers/slabs/slab.html Entenda e explique no relatório para que serve esse alocador, como a memória é alocada e desalocada para uso do kernel. Quando um arquivo é aberto, o kernel aloca memória para o seu inode (uma estrutura de dados contendo ponteiros para blocos, data da criação, permissões, etc.). Crie um programa bem simples (o correspondente ao init) para rodar no Linux/Versatile para observarmos como isso funciona. O programa deve abrir um arquivo, escrever algo nesse arquivo e fechar o arquivo. Quando o arquivo é aberto, o kernel aloca memória para o inode. Quando o arquivo é fechado, a área para o inode deve ser desalocada. Usando o gdb rode até que a system call execve ative este programa (para garantir que as estruturas do kernel já estão prontas). Coloque breakpoints quando a área de memória para o inode é criada e liberada. Coloque os printscreens da tela no relatório. Apresente ao vivo para a classe. Rode no linux/arm no qemu. Verifique que memória eh alocada para o inode quando o open eh feito pela primeira vez. Jah na segunda vez, a memoria eh reutilizada.

10>

9.5 5 MINIX alocacao e desalocacao de memória

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.

dica: http://www.pcs.usp.br/~jkinoshi/2007/r4-1.pdf

Adicione ao log a informação de qual tipo de segmento (código ou dados) está sendo alocado ou desalocado. A resposta dada pela turma (com uma versao antiga do minix; e portanto atualize para o minix novo) está em: resp: http://www.pcs.usp.br/~jkinoshi/2008/projs/r4_brunogrisi.zip Faça com que a informação sobre o tipo de segmento (código/dado) esteja na mesma linha onde está "fork", "exec", etc.

Faça um programa que fique em loop executando o fork e veja o que ocorre no log. O processo deverá fazer algo como: while (1) { fork(); } Esse tipo de processo vai travar o sistema porque vai consumir toda a memória; ou vai acabar com todas as entradas na tabela de processos. O que acontece no minix? Crie uma forma de monitorar o número de processos que rodam na máquina. Tire printscreens da tela enquanto o processo que gera processos roda.

9> observaram que o fork acaba primeiro com o numero de entradas na tabela de paginas.

9.6 6 MINIX precisamemoria.c

Quando o minix faz exec ele deve desalocar a memoria da imagem do processo pai e alocar memoria (dados, código, pilha) referente ao codigo executavel, como ele faz isso? Localize isso no código do minix; mas basicamente ele deve ler o arquivo executável e retirar essa informacao. Localize no código do minix onde isso ocorre. Com base nesse código crie um programa no minix que tem como entrada um arquivo executável do minix (vc. pode criar um arquivo executável qualquer) e mostre o quanto o programa precisa de área de memória (dados, codigo/texto, pilha). Exemplo: precisamemoria arquivoexecutavel retorna o entrypoint e o quanto precisa de área de dados, código e pilha. Uma forma de resolver o problema é criar uma system call que colhe esses dados do PM. Entretanto, deve ser possível realizar a mesma coisa usando system calls normais (sem criar nenhuma sytem call para o minix), de forma a ler o código do arquivo exectável e com base no formato do arquivo, extrair essas informações. Para isso é necessário estudar o código do minix (quase que replicando código do PM) no precisamemoria.c. Escreva o código de precisamemoria.c e apresente para a classe ao vivo. Retire printscreens da máquina virtual e anexe no relatório. Modifique o exec no PM para mostrar como ficam os enderecos virtuais e fisicos no minix.

7.5 > Seria muito simples criar essa system call no PM, mas tentaram sem sucesso no FS.

9.7 7 MINIX invasao de memoria / usar bochs

Como o minix protege a área do kernel? Se algum processo tentar invadir a área do kernel ele é realmente barrado? Crie um processo que tenta invadir uma área a que nao tem acesso. Uma forma de fazer isso é criar um ponteiro que varre a memória, lendo e escrevendo dados. Ao fazer isso no minix que erro você observa? Localize o tratamento desse erro no código fonte do minix. Apresente uma mensagem diferente quando ocorrer esse erro. Qual a participacao do pentium nessa excessão? Como o pentium é informado da área de memória do processo? Localize isso no código do minix. Rode esse programa no bochs para observar a interrupcao de invasao de memória. Relacione com o sinal SIGSEV. Retire printscreens e anexe no relatório. Observem que o limite de memoria para o processo já é definido ao se programar a LDT.

5-1 = 4> infelizmente nao souberam colocar o breakpoint na entrada da rotina de interrupcao. Mas apesar disso, compartilharam a maquina virtual bochs+minix que poderah ser usada no futuro.

9.8 8 MINIX - estouro de pilha.

Estouro de pilha (stack overflow): monitorar quando ocorre estouro de pilha. Você pode criar uma rotina recursiva que chama ela mesma indefinidamente no minix - sendo que ela deve passar como parametro i+1 e imprimir esse valor; de forma que podemos identificar o numero maximo de chamadas recursivas que foi possivel antes de se ter o estouro de pilha. Rode o minix no bochs e intercepte a excessao de estouro de pilha. Coloque o printscreen no relatório. Altere a área de memória RAM da máquina virtual onde roda o minix; verifique se o número máximo de chamadas recursivas varia. Localize no código do minix, qual o tamanho máximo que uma pilha de processo pode ter. A equipe do ano passado usou o minix2 pois tiveram problemas no minix3 que usa memoria virtual e portanto demorava muito (o processo tinha muita memoria) para dar o estouro de pilha. Tentem usar o proprio minix3. Para agilizar o estouro de pilha basta empilhar mais coisas. Por exemplo, a cada chamada recursiva, alocar memoria usando malloc e colocar essa memoria alocada na pilha (uma ideia eh colocar um vetor como parametro de uma funcao e passah-lo como dado e nao como endereco). No minix 3.1.0 é possível observar a excessao de stack overflow - int 12 enquanto que no minix 3.1.5 já não foi possível por trabalhar com memória virtual.

9> Filipe Koji e Thiago, 0> Guilherme Job Conseguiram com sucesso, - embora tenham apresentado os screenshots.

Date: 2015-08-21 13:22:16 BRT

Author: jk

Org version 7.8.02 with Emacs version 23

Validate XHTML 1.0