Relatório TP2 - Fundamentos de Sistemas Operativos - 27-12-2024 - PDF

Document Details

AwesomeSerpentine7902

Uploaded by AwesomeSerpentine7902

ISEL, Instituto Superior de Engenharia de Lisboa

2024

Pedro Grilo, Fernando Prates, Ana Silva

Tags

sistemas operativos engenharia informática programação relatorio

Summary

Relatório sobre Fundamentos de Sistemas Operativos. Inclui as aulas práticas e o desenvolvimento. O documento foi realizado por Pedro Grilo, Fernando Prates e Ana Silva.

Full Transcript

LEIM – Licenciatura em Engenharia Informática e Multimédia Fundamentos de Sistemas Operativos Relatório TP2 - 32D - G05 Pedro Grilo | A51319 Fernando Prates | A51635 Ana Silva | A50247 27-12-2024 ...

LEIM – Licenciatura em Engenharia Informática e Multimédia Fundamentos de Sistemas Operativos Relatório TP2 - 32D - G05 Pedro Grilo | A51319 Fernando Prates | A51635 Ana Silva | A50247 27-12-2024 Índice Índice................................................................................................................2 Introdução........................................................................................................ 4 Desenvolvimento............................................................................................... 5 Aula prática 1.........................................................................................................5 Aula prática 2.........................................................................................................9 Aula prática 3....................................................................................................... 17 Aula prática 4....................................................................................................... 20 Aula prática 5....................................................................................................... 23 Aula prática 6....................................................................................................... 26 Conclusão....................................................................................................... 33 Código............................................................................................................37 Comunicação.................................................................................................................37 CanalComunicacao.java...................................................................................... 37 CanalComunicacaoConsistente.java.................................................................... 39 Mensagem.java.................................................................................................... 42 Gravador.java.......................................................................................................43 IG................................................................................................................................... 45 App................................................................................................................................ 45 Application.java................................................................................................... 45 BD.java................................................................................................................ 46 GUI.java............................................................................................................... 51 Tarefas........................................................................................................................... 64 Gravar.java........................................................................................................... 64 Imitar.java............................................................................................................ 67 ITarefas.java.........................................................................................................70 Reproduzir.java.................................................................................................... 70 Tarefas.java.......................................................................................................... 71 TP1................................................................................................................................. 73 2 App................................................................................................................................ 73 Application.java................................................................................................... 73 BD.java................................................................................................................ 74 GUI.java............................................................................................................... 78 Tarefas........................................................................................................................... 92 Evitar.java............................................................................................................ 92 Fugir.java............................................................................................................. 94 ITarefas.java.........................................................................................................95 Tarefa.java........................................................................................................... 96 Vaguear.java........................................................................................................ 97 Índice Imagens Fig.1 - Aula prática 1 | GUI TP1............................................................................ 6 Fig.2 - Aula prática 1 | GUI IG.............................................................................. 8 Fig.3 – Aula Prática 2|UML TP2 Completo........................................................... 10 Fig.4 – Aula Prática 2|UML TP2 – TP1 e Comunicação......................................... 11 Fig.5 – Aula Prática 2|UML TP2 – IG e Comunicação........................................... 15 Fig.6 – Diagrama de estados da classe Gravar do projeto IG................................23 Fig.7– Excerto de código da classe Gravar – código que engloba os estados DORMIR e GRAVAR.......................................................................................... 24 Fig.8 – Excerto de código da classe Gravar – código que engloba o estado REPRODUZIR e regresso a DORMIR................................................................... 25 Fig.9 – GUI TP1 – Finalizada............................................................................... 26 Fig.10 – Diagrama de Estados| TP1 Evitar........................................................... 27 Fig.11 – Diagrama de Estados| TP1 Vaguear e Fugir............................................. 28 Fig.12 – Diagrama de Estados| IG Imitar............................................................. 28 Fig.13 – Diagrama de Estados| IG Gravar e Reproduzir........................................ 29 Fig.14 – UML final | IG e Comunicacao.............................................................. 34 Fig.15 – UML final TP2...................................................................................... 35 3 Introdução Este trabalho tem como objetivo a implementação de uma interface gráfica intuitiva, utilizando a biblioteca Swing, e o desenvolvimento de uma aplicação multiprocesso que irá permitir a gestão e comunicação entre dois processos JAVA com memória partilhada suportada pela classe JAVA MappedByteBuffer. Um dos processos é aproveitado do primeiro trabalho prático (TP1), que já tem a comunicação com o robot sólida e estabelecida, o segundo processo será chamado IG em concordância com os comportamentos que irá adotar que serão o Imitar e o Gravar. Esta introdução prática à criação de GUIs e ao desenvolvimento de múltiplas aplicações multitarefa e a comunicação entre processos estabelece a base para a criação de sistemas mais complexos e eficientes, explorando aspetos fundamentais da comunicação e sincronização entre tarefas e processos em Java. O estabelecimento do modelo Produtor-Consumidor (TP1-IG) será dado pelo processo Comunicacao que proverá um desafio interessante para melhor compreensão de gestão entre processos e indispensável para entender e criar um sistema ainda mais intrincado e como os processos podem comunicar diretamente entre si e, neste caso, comandar os robôs a comportarem-se de forma síncrona. 4 Desenvolvimento Aula prática 1 Nesta aula estivemos a desenvolver a GUI para os nossos processos. Aproveitando a GUI do primeiro trabalho TP1 tivemos de realizar algumas alterações (diagrama final na aula prática 6). Estas alterações consistiram:  Na criação de um botão “Lançar IG” que lançará a GUI do processo de IG.  Um campo e um botão para procurar um ficheiro onde aparecerá no campo do texto o nome do ficheiro escolhido  Um botão radial para realizar o Debug, caso algo corra mal  Um espaço para colocar o Nº de mensagens permitido sendo que o seu máximo será de 16  E claro, o botão radial de Abrir/Fechar Canal de comunicação entre este processo e o de IG que estará disponível após o carregar do botão de lançar IG. 5 Fig.1 - Aula prática 1 | GUI TP1 6 Seguidamente, preparámos a GUI do processo IG. Muito semelhante à GUI do TP1, sendo que as diferenças são:  Campo Imitar: o Botão radial para Abrir o canal de comunicação o Botão checkbox para Ativar ou Desativar  Campo Gravar: o Um campo e um botão para procurar um ficheiro onde aparecerá no campo do texto o nome do ficheiro escolhido o Um botão para Gravar o Um botão para Reproduzir o Um campo para escrever o Um botão para Limpar o Um botão checkbox para Imprimir o que foi escrito 7 Fig.2 - Aula prática 1 | GUI IG 8 Aula prática 2 A aula de hoje consistiu no mapeamento do nosso, até agora, código em UML com recurso à ferramenta MagicDraw. UML - Unified Modeling Language - trata-se de uma linguagem gráfica standard, estruturada e útil para uma melhor compreensão dos requisitos, arquitectura e design de software criado. Funciona quase que como um mapa com o objectivo de guiar os programadores, ou neste caso, nós, os alunos, a olhar para o nosso código e descobrir potenciais problemas e soluções. 9 Fig.3 – Aula Prática 2|UML TP2 Completo 10 Fig.4 – Aula Prática 2|UML TP2 – TP1 e Comunicação 11 TP1 Tarefas 1. Interface ITarefas  Define os métodos que as classes Fugir, Vaguear e Evitar implementam, como executar() e bloquear(). Esta interface garante que todas as tarefas do robot seguem uma estrutura comum, facilitando a sua implementação. 2. Classes de Comportamento: Fugir, Vaguear, Evitar  Estas classes implementam a interface ITarefas e contêm a lógica específica para cada comportamento do robot. Atributos:  robot: Referência ao objeto do tipo RobotLegoEV3, que representa o robot controlado.  gui: Um objeto GUI associado.  ESTADO, distancia, angulo, etc., que ajudam a controlar o estado e o comportamento específico do robot. Operações:  Cada classe tem métodos como run() e executar(), onde a lógica do comportamento específico é implementada. 12  O método bloquear(boolean bloquear) está relacionado com a sincronização ou gestão de bloqueios durante a execução das tarefas. App 1. Classe BD  A classe BD (Base de Dados) armazena informações sobre o robot, como o seu estado (onOff, terminar, vaguear, evitar, fugir), bem como métodos para definir e obter esses valores.  Esta classe também inclui métodos para manipular o estado e informações do robot, como setDistancia(), setAngulo(), setRobot(), entre outros. 2. Classe GUI  Esta classe representa a interface gráfica do utilizador. Contém diversos componentes gráficos (ex.: JLabel, JTextField, JButton, JCheckBox), como elementos de interface que permitem a interação com o utilizador. Operações:  Métodos como initGUI(), getEngineBD(), enableButtons(), e outros, indicam a configuração e manipulação da interface gráfica. 3. Classe Application Esta é a classe principal que inicia o sistema. Ela configura a interface (gui) e tem o método main() que executa o programa. 13 Relações entre as Classes  As classes Fugir, Vaguear, e Evitar implementam a interface ITarefas, o que é mostrado pelas setas de herança. Estas classes encontram-se ligadas à classe Tarefa onde se encontram os métodos e atributos em comum dessas classes.  A classe GUI usa a classe BD e mantém referências a instâncias das classes Fugir, Vaguear, e Evitar.  A classe Application usa a classe GUI, demonstrando que esta é responsável por configurar e executar a interface gráfica. Comunicação 1.Classe Mensagem  Será a classe responsável pela mensagem passar entre os processos. 2.Classe CanalDeComunicacao  Classe que irá criar um canal de comunicação entre processos. 3.Classe CanalDeComunicacaoConsistente  Classe de comunicação entre processos estável. Relações entre as classes 14  A classe Mensagem encontra-se ligada à classe Application tanto do processo TP1 como do processo IG. A classe de CanalDeComunicacaoConsistente herdará da classe CanalDeComunicacao e ligar-se-á à classe BD do processo TP1 e à classe Application do processo IG. Fig.5 – Aula Prática 2|UML TP2 – IG e Comunicação 15 IG O processo IG é uma cópia das Classes dos mesmos nomes de TP1 mas apenas com algumas alterações na GUI. Assim: 1. Classe BD  A classe BD (Base de Dados) armazena informações sobre o robot, como o seu estado (onOff, terminar, vaguear, evitar, fugir), bem como métodos para definir e obter esses valores.  Esta classe também inclui métodos para manipular o estado e informações do robot, como setDistancia(), setAngulo(), setRobot(), entre outros. 2. Classe GUI  Esta classe representa a interface gráfica do utilizador. Contém diversos componentes gráficos (ex.: JLabel, JTextField, JButton, JCheckBox), como elementos de interface que permitem a interação com o utilizador. A diferença entre este processo e o TP1, é que são adicionados campos para Imitar e Gravar com tudo o que os involve. Operações:  Métodos como initGUI(), getEngineBD(), enableButtons(), e outros, indicam a configuração e manipulação da interface gráfica. 3. Classe Application  Esta é a classe principal que inicia o sistema. Ela configura a interface (gui) e tem o método main() que executa o programa. 16 Aula prática 3 A aula de hoje consistiu na elaboração das classes CanalComunicacao e CanalComunicacaoConsistente. Estas classes têm de existir para permitir a comunicação entre os processos TP1 e o IG de forma a possibilitar futuramente o caminhar sincronizado entre os robôs. CanalComunicacao Esta classe vai ser responsável por possuir métodos que permitem não só a abertura e fecho do canal de comunicação como também os métodos de receber e enviar mensagem.  Começamos por criar o construtor, CanalComunicacao(), que inicializa a classe, definindo a variável indiceMensagens como 0, e deixando as variáveis de ficheiro, canal e buffer como null, preparando o objeto para ser usado.  Para tal, o método de abertura do canal, abrirCanal(), vai criar um ficheiro com o nome “comunicacao.dat”. Seguidamente cria um canal de comunicação de leitura e escrita e finalmente mapeia o conteúdo do ficheiro para memória.  O método receberMensagem(), como o nome indica, recebe uma mensagem e vai buscar quatro campos int (index, comando, argumento1 e argumento2) para depois convertere-la em objecto do tipo Mensagem(index, comando, argumento1, argumento2).  O método enviarMensagem(Mensagem msg) que vai enviar um objecto Mensagem como uma mensagem recorrendo ao método putInt() de MappedByteBuffer para colocar a informação nos campos index, comando, argumento1 e argumento2 no buffer de forma sequencial. Depois de a informação estar armazenada, o índice de mensagens é incrementado para não haver sobreposição. 17  O método de fecho do canal, fecharCanal(), de forma aos recursos serem liberados após a finalização da sua utilização.  O método getIndex() que, como o nome indica, vai buscar o indíce da mensagem. CanalComunicacaoConsistente Esta classe vai herdar da classe anterior e expandir sobre ela para implementar novos métodos:  O método construtor CanalComunicacaoConsistente() que vai buscar o construtor da classe anterior pela implementação de super().  CanalLock(FileChannel canal) que recorrendo à utilização de FileLock, bloqueia o canal de maneira que apenas um processo (TP1 ou IG) esteja a utilizá-lo de cada vez sem interferências.  CanalRelease(FileLock fl) liberta o canal assim que a sua utilização já não for necessária pelo processo que possui o seu acesso de momento.  O método enviarMensagem(Mensagem msg) aproveitado da classe CanalComunicacao mas implementando os métodos de FileLock descritos anteriormente para garantir o acesso exclusivo do processo.  receberMensagem(), tal como anterior é aproveitado de CanalComunicacao mas estabilizado com o uso de FileLock para garantir o acesso exclusivo do canal. 18  getAndSetConsumidor(Mensagem m), booleano, em que recebe a mensagem do Consumidor (IG), e se o comando da mensagem for equivalente a 0, o método envia a mensagem recebida “m” de volta para o canal, retornando true o que indica que foi bem sucedida. Senão retornará false o que indica que a operação não foi bem sucedida.  E finalmente o booleano getAndSetProdutor(Mensagem m) que é idêntico ao método anterior, mas agora da parte do Produtor (TP1). 19 Aula prática 4 A aula de hoje consistiu na elaboração do código e implementação da sincronização de movimento dos dois robôs. 1. Para isso, para além dos canais de CanalComunicacao e CanalComunicacaoConsistente, foi criada a classe Mensagem, responsável por obter e tornar um objecto Mensagem (Mensagem (index, comando, argumento1, argumento2)) numa mensagem em formato String através de gets para cada campo da mensagem e pela aplicação do método toString(): public String toString() { return "indice: " + this.index +"\n" + "comando: " + this.comando +"\n" + "arg1: " + this.arg1 +"\n" + "arg2: " + this.arg2 +"\n"+ "FIM MENSAGEM"+"\n"; } 2. Foi alterada a classe BD do processo IG de forma a acomodar o canal de comunicação, nomeadamente de métodos get e setFile() de forma a obter e processar a informação do ficheiro, get e setCanalCom() para obter e definir informação do canal de comunicação e getTamanhoMensagem() para obter a informação do tamanho da mensagem. 3. Para além disto, foi adicionada na classe Application do processo IG métodos para a tarefa Imitar que permitirá o segundo robô “copiar” as acções do primeiro. 20 4. Criação da classe Imitar, responsável pela imitação de acções/comandos do primeiro robô pelo segundo robô. De maneira a conseguir fazer isto, a classe vai herdar da classe Tarefa e implementar os métodos de ITarefas. Assim ela vai buscar o canal, cria um ArrayList para a mensagem. O seu construtor vai buscar informação de GUI, adicionar mensagem se null e vai buscar informação sobre o canal. O processo run() consiste num while, que quando true, vai ter dois estados:  O de BLOQUEADO onde liberta a Thread através do Thread.yield(), e uma condição onde se o estado for diferente de BLOQUEADO é lançado um print na consola da GUI "Tarefa vaguear iniciada" mudando seguidamente para o estado de EXECUTAR.  O de EXECUTAR onde terá duas condições. Uma é que se o getAndSetConsumidor encontrar um objecto mensagem com todos os seus parâmetros a 0, aparecerá na consola da GUI um print da última mensagem em String existente no canal e irá adicionar uma mensagem. A segunda condição é que caso o estado seja o de BLOQUEADO, o estado actual torna-se BLOQUEADO. Na interface ITarefas foi adicionada a variável Random r que invocará o método Random() que randomizará uma acção dentro dos limites estipulados.  As tarefas de TP1 Vaguear e Fugir vão receber r para randomizar os parâmetros de andamento do primeiro robô. No caso de Vaguear, r estará em distância onde, até ao limite de 90 escolherá um número inteiro ao acaso (this.distancia = r.nextInt(90); ), seguidamente será o ângulo onde também 21  escolherá um número inteiro ao acaso no mesmo limite (this.angulo = r.nextInt(90); ) e finalmente a acção que será escolhida aleatoriamente até limite de 3 (this.acao = r.nextInt(3); ). No Fugir, r irá escolher aleatoriamente na condição o próximo booleano que irá desencadear uma série de acções. 22 Aula prática 5 A aula de hoje consistiu na elaboração de UML, um diagrama de estados de forma a orientar a construção de código seguinte. Fig.6 – Diagrama de estados da classe Gravar do projeto IG 23 Explicando sucintamente o diagrama acima:  Iniciando, o sistema encontra-se no estado DORMIR. O sistema sairá do estado DORMIR pela intervenção do utilizador em que poderá decidir entre os estados GRAVAR e REPRODUZIR.  Supondo que o GRAVAR é ativado, ativará a parte do código gui.getBD().getGravar() que iniciará a gravação. Após a gravação de todas as mensagens do robô, ativa-se a parte do código gui.getBD().getMensagensGravar().isEmpty() e o estado do robô volta para o DORMIR. Fig.7– Excerto de código da classe Gravar – código que engloba os estados DORMIR e GRAVAR  Para iniciar o estado de REPRODUZIR, será ativado a sequência de código de gui.getBD().getReproduzir(). Quando a 24 sequência está terminada, ou por ter reproduzido todas as mensagens ou por ordem do utilizador, é ativado pela negação do código anterior !gui.getBD().getReproduzir() como é denotado pelo ponto de exclamação “!” e o sistema volta ao estado DORMIR. Fig.8 – Excerto de código da classe Gravar – código que engloba o estado REPRODUZIR e regresso a DORMIR  Quando o sistema está no estado DORMIR poder-se-á terminar o sistema assim que existir ordem para tal por parte do utilizador. 25 Aula prática 6 Nesta aula, foi necessário “limar algumas arestas” para que tudo corresse bem a nível de programa, GUI e de sincronização dos robôs.  Foi adicionado um campo na GUI do TP1 para procura de ficheiros nomeadamente Ficheiro IG onde poderemos colocar o ficheiro adquirido após gravação para depois poder reproduzir o mesmo. Efectivamente o que irá acontecer é que o segundo robô irá reproduzir os comandos que foram gravados na execução do primeiro robô. Fig.9 – GUI TP1 – Finalizada 26 Quando experimentámos o robô ao lado do professor reparámos em alguns problemas nomeadamente:  o segundo robô não voltava a imitar o primeiro quando parado por alguns minutos e voltar a ser activado.  O primeiro robô (projecto TP1) apagava e reescrevia os campos do buffer sem intervenção da limpeza de mensagens por parte do processo IG do segundo robô.  O botão do processo IG não tinha o comando associado. Todos estes pontos foram corrigidos de forma a conseguirmos validar positivamente o trabalho. Foram criados também diagramas de estados para melhor percebermos como seguir: Fig.10 – Diagrama de Estados| TP1 Evitar 27 Fig.11 – Diagrama de Estados| TP1 Vaguear e Fugir Fig.12 – Diagrama de Estados| IG Imitar 28 Fig.13 – Diagrama de Estados| IG Gravar e Reproduzir Contudo, para melhorar a experiência do trabalho, os docentes acrescentaram um requisito a mais, de modo a criar um canal mais consistente e estável. Assim foi alterado o código para acomodar a nova exigência: No canal de comunicação foram adicionadas as variáveis protected int OFFSET_IDXPUT e OFFSET_IDXGET na classe CanalComunicacao de forma a controlar os índices de escrita e de leitura no buffer, optimizando a manipulação de mensagens, evitando colisões. No método de abrirCanal presente no CanalComunicacao: OFFSET_IDXPUT representa a posição onde o índice de escrita será armazenado garantindo que o programa saiba onde começar a escrever a próxima mensagem no buffer. OFFSET_IDXGET representa a posição no buffer onde o índice de leitura será armazenado. Assim o programa saberá onde deve procurar para começar a ler a próxima mensagem. 29 @SuppressWarnings("resource") public boolean abrirCanal(String ficheiro, int n_mensagens) { try { canal = new RandomAccessFile(new File(ficheiro), "rw").getChannel(); } catch (FileNotFoundException e) { System.out.println("Ficheiro não encontrado");return false;} try { buffer = canal.map(FileChannel.MapMode.READ_WRITE, 0, n_mensagens * TAMANHO_MENSAGEM + 8); this.n_mensagens = n_mensagens; index = this.loadFromBuffer(OFFSET_IDXPUT); this.storeInBuffer(OFFSET_IDXGET, index); this.OFFSET_IDXPUT = n_mensagens * TAMANHO_MENSAGEM; this.OFFSET_IDXGET = n_mensagens * TAMANHO_MENSAGEM + 4; this.limparCanal(n_mensagens); } catch (IOException e) { return false;} return true; } Temos a carga e armazenamento dos índices em: index = this.loadFromBuffer(OFFSET_IDXPUT); this.storeInBuffer(OFFSET_IDXGET, index); onde loadFromBuffer recupera o índice de escrita armazenado previamente no buffer para continuar as operações de escrita do ponto onde pararam através do método: protected int loadFromBuffer(int offset) { FileLock fl = canalLock(); 30 int posInit = buffer.position(); buffer.position(offset); int value = buffer.getInt(); buffer.position(posInit); canalRelease(fl); return value; } E storeInBuffer vai armazenar o índice de leitura inicial no buffer sincronizando o estado de leitura através do seu método: protected void storeInBuffer(int offset, int value) { FileLock fl = canalLock(); int posInit = buffer.position(); buffer.position(offset); buffer.putInt(value); buffer.position(posInit); canalRelease(fl); Thread.yield(); } Os Offsets são iniciados em: this.OFFSET_IDXPUT = n_mensagens * TAMANHO_MENSAGEM; this.OFFSET_IDXGET = n_mensagens * TAMANHO_MENSAGEM + 4; sendo que OFFSET_IDXPUT aqui é definido para ocupar 4 bytes (igual a um inteiro ((int))) logo após a última mensagem. E OFFSET_IDXGET ocupa os 4 bytes seguintes. Depois dos offsets serem definidos, o canal é limpo com: this.limparCanal(n_mensagens); 31 garantindo assim que o buffer fique pronto para uso sendo que as mensagens antigas são eliminadas e os índices voltam a sofrer sincronização. Deste modo, o canal de comunicação consegue atingir um maior nível de consistência pois os offsets garantem que o rastreio das operações de leitura e escrita no buffer circular sejam independentes, evitando que existam interferências e que as mensagens não sejam acidentalmente subscritas ou ignoradas. 32 Conclusão O desenvolvimento deste projecto permitiu a consolidação de conhecimentos sobre a criação de diferentes processos e a comunicação entre si recorrendo a memória partilhada. A construção de um sistema multi-tarefa com sincronização e interação entre processos foi desafiante a nível prático e teórico mas permitiram a compreensão de conceitos como o modelo Produtor-Consumidor e o uso de buffers mapeados em memória. A implementação de classes para formar um canal de comunicação consistente foram desafiantes mas permitiu um melhor entendimento do que é necessário para troca de mensagens entre os diferentes processos, nomeadamente um canalComunicacao e canalComunicacaoConsistente que garantam estabilidade e possibilidade de manipulação/controlo necessários para a troca de mensagens. Assim sendo fomos introduzidos aos offsets e a bloqueios (locks) para alcançar a essencial consistência no sistema, ou seja, que não haja sobreposições, colisões de dados e eliminação acidental de mensagens assegurando a cobiçada sincronização de robôs. A utilização de UML ao longo do projecto foi interessante no modo a ser sempre revista e alterada perante o desenvolvimento prático sendo que a sua forma final pode ser aqui vista pelas seguintes imagens: 33

Use Quizgecko on...
Browser
Browser