Este documento apresenta a implementação do algoritmo de exclusão mútua distribuída de Lamport usando o framework Neko. O autor implementou o algoritmo em Java com classes que representam cada processo e a troca de mensagens entre eles. Ele também desenvolveu classes para gerar logs da execução e visualizar os resultados usando o programa LogView, mostrando a troca de mensagens em tempo real durante a execução distribuída.
Redes Avançadas - 1.Aspectos de InterconexãoMauro Tapajós
O documento discute aspectos da camada de rede no modelo OSI, incluindo: (1) Interconexão de redes heterogêneas usando um protocolo comum como IP; (2) Endereçamento e roteamento de pacotes entre redes; (3) Técnicas como fragmentação e controle de congestionamento para lidar com limitações entre redes.
O documento discute o controle de congestionamento no protocolo TCP. O TCP usa quatro algoritmos para evitar e responder à congestão: congestion avoidance, slow start, fast retransmit e fast recovery. A janela deslizante permite o envio de vários pacotes sem esperar ACKs e ajuda no controle de fluxo entre origem e destino.
Este documento apresenta um capítulo sobre a camada de transporte no modelo TCP/IP. Ele descreve as principais responsabilidades da camada de transporte, como fornecer comunicação entre processos de aplicação e controlar fluxo e congestionamento. Além disso, explica como a multiplexação e demultiplexação na camada de transporte permitem que múltiplos processos se comuniquem através da mesma interface de rede.
O documento descreve a camada de transporte no modelo TCP/IP, especificamente os protocolos UDP e TCP. UDP fornece transporte de dados sem conexão e não confiável através da utilização de portas para identificar processos de destino. TCP é orientado a conexão e fornece serviços adicionais como controle de fluxo e de erros. Ambos os protocolos utilizam portas para permitir a comunicação entre vários processos em um mesmo host.
O documento descreve os protocolos de camada de transporte ICMP, UDP e TCP. O ICMP é usado para enviar mensagens de controle e erros na camada de rede. O UDP é um protocolo não orientado a conexão que prioriza a velocidade em detrimento da confiabilidade. O TCP é orientado a conexão e garante a entrega confiável e na ordem correta dos dados.
Este artigo descreve como o software Wireshark pode ser usado para monitorar e analisar pacotes de rede. Ele explica as principais funcionalidades do Wireshark, como capturar pacotes, filtrar por protocolo e visualizar o fluxo de sessões TCP. O artigo também relata um experimento em laboratório usando o Wireshark para analisar o tráfego de rede gerado por um navegador da web.
O UDP é um protocolo de transporte que permite o envio de datagramas encapsulados em pacotes IP de forma não confiável, sem garantias de entrega ou ordem. Os datagramas UDP contêm cabeçalhos simples com números de porta e checksums para validação. O protocolo fornece broadcast e multicast sem conexão, tornando-o eficiente para transmissão de mídia, mas sensível a perdas.
Redes Avançadas - 1.Aspectos de InterconexãoMauro Tapajós
O documento discute aspectos da camada de rede no modelo OSI, incluindo: (1) Interconexão de redes heterogêneas usando um protocolo comum como IP; (2) Endereçamento e roteamento de pacotes entre redes; (3) Técnicas como fragmentação e controle de congestionamento para lidar com limitações entre redes.
O documento discute o controle de congestionamento no protocolo TCP. O TCP usa quatro algoritmos para evitar e responder à congestão: congestion avoidance, slow start, fast retransmit e fast recovery. A janela deslizante permite o envio de vários pacotes sem esperar ACKs e ajuda no controle de fluxo entre origem e destino.
Este documento apresenta um capítulo sobre a camada de transporte no modelo TCP/IP. Ele descreve as principais responsabilidades da camada de transporte, como fornecer comunicação entre processos de aplicação e controlar fluxo e congestionamento. Além disso, explica como a multiplexação e demultiplexação na camada de transporte permitem que múltiplos processos se comuniquem através da mesma interface de rede.
O documento descreve a camada de transporte no modelo TCP/IP, especificamente os protocolos UDP e TCP. UDP fornece transporte de dados sem conexão e não confiável através da utilização de portas para identificar processos de destino. TCP é orientado a conexão e fornece serviços adicionais como controle de fluxo e de erros. Ambos os protocolos utilizam portas para permitir a comunicação entre vários processos em um mesmo host.
O documento descreve os protocolos de camada de transporte ICMP, UDP e TCP. O ICMP é usado para enviar mensagens de controle e erros na camada de rede. O UDP é um protocolo não orientado a conexão que prioriza a velocidade em detrimento da confiabilidade. O TCP é orientado a conexão e garante a entrega confiável e na ordem correta dos dados.
Este artigo descreve como o software Wireshark pode ser usado para monitorar e analisar pacotes de rede. Ele explica as principais funcionalidades do Wireshark, como capturar pacotes, filtrar por protocolo e visualizar o fluxo de sessões TCP. O artigo também relata um experimento em laboratório usando o Wireshark para analisar o tráfego de rede gerado por um navegador da web.
O UDP é um protocolo de transporte que permite o envio de datagramas encapsulados em pacotes IP de forma não confiável, sem garantias de entrega ou ordem. Os datagramas UDP contêm cabeçalhos simples com números de porta e checksums para validação. O protocolo fornece broadcast e multicast sem conexão, tornando-o eficiente para transmissão de mídia, mas sensível a perdas.
Análise de Desempenho de Algoritmos de Controle de Congestionamento TCP utili...Felipe Alex
Este documento apresenta um resumo de uma dissertação de mestrado que avalia o desempenho de diferentes algoritmos de controle de congestionamento TCP em diferentes cenários de rede simulados. O documento descreve os objetivos, métodos e principais conclusões da dissertação, que encontrou que o algoritmo TCP Vegas teve o melhor desempenho geral na maioria dos cenários simulados.
O documento discute os conceitos de processos, threads, comunicação entre processos e problemas clássicos relacionados. Aborda técnicas como semáforos, monitores e regiões críticas para sincronização de acesso a recursos compartilhados e evitar condições de corrida. Apresenta exemplos como o problema do produtor-consumidor, jantar dos filósofos e barbeiro sonolento.
O documento descreve a implementação do protocolo RDT 3.0 para transferência confiável de dados através de redes, cobrindo a evolução dos protocolos RDT de versões anteriores e a implementação do código usando máquina de estados finitos e modelagem UML.
O documento fornece uma introdução aos protocolos TCP e UDP, descrevendo suas principais características e diferenças. TCP é orientado a conexão e fornece entrega confiável de dados através de confirmações, enquanto UDP é sem conexão e não garante entrega. Ambos usam números de porta para direcionar pacotes a aplicativos.
O documento discute vários métodos para exclusão mútua entre processos, incluindo desabilitar interrupções, variáveis de impedimento, alternância obrigatória, a solução de Peterson e a instrução TSL. Além disso, aborda semáforos, monitores, troca de mensagens e barreiras para sincronização de processos, bem como técnicas de escalonamento em sistemas em lote e interativos.
Um processo é um container que fornece recursos e isolamento para um programa em execução. Um processo pode estar em vários estados como new, ready, running, waiting ou terminated. Um sistema operacional usa threads para permitir a execução paralela de tarefas dentro de um mesmo processo.
Redes de computadores II - 4.Camada de Transporte TCP e UDPMauro Tapajós
O documento descreve os principais conceitos da camada de transporte no modelo TCP/IP, incluindo protocolos como TCP e UDP. O TCP implementa conexões orientadas a conexão de forma confiável através de mecanismos como três-way handshake, janelas deslizantes e controle de congestionamento. O UDP fornece serviço não orientado a conexão baseado em datagramas.
O documento discute algoritmos de escalonamento de processos em sistemas operacionais, incluindo Round Robin, prioridade e múltiplas filas. Round Robin atribui um quantum de tempo para cada processo antes de alternar para o próximo. Prioridade executa processos com prioridade mais alta primeiro. Múltiplas filas agrupam processos por tipo para execução.
O documento discute processos e threads no sistema operacional. Aborda conceitos como processos, threads, comunicação entre processos, estados de processos e implementação de processos e threads no kernel.
O documento descreve os protocolos UDP e TCP da camada de transporte. Brevemente discute como a camada de transporte é responsável pela comunicação entre processos através do paradigma cliente-servidor e do uso de endereços de porta para identificar processos únicos. Também resume as principais diferenças entre UDP, um protocolo não confiável e sem conexão, e TCP, um protocolo confiável e orientado a conexão.
Cluster é um grupo de computadores que trabalham juntos para fornecer recursos de alta disponibilidade e balanceamento de carga como um único sistema. O serviço de Balanceamento de Carga de Rede (NLB) melhora a disponibilidade de aplicativos de servidor como web, FTP e firewall distribuindo a carga entre os nós. Clusters podem ser configurados de várias formas como cluster de nó único, cluster com quorum único ou cluster principal de conjunto de nós.
Sistemas Operacionais Processos e Threads - Wellington Pinto de OliveiraWellington Oliveira
O documento discute processos e threads em sistemas operacionais. Aborda tópicos como criação e término de processos, hierarquia de processos, estados de processos, implementação de processos, modelo de threads, comunicação interprocesso usando regiões críticas, semáforos, monitores e problemas clássicos como produtor-consumidor, jantar dos filósofos e escalonamento.
Este documento discute os princípios e tecnologias da camada de enlace de dados. Ele introduz os objetivos e serviços da camada de enlace, incluindo detecção e correção de erros, compartilhamento de canal, endereçamento e transferência confiável de dados. Ele também discute implementações específicas como Ethernet, protocolos de acesso múltiplo e endereçamento MAC.
O documento descreve os principais protocolos da arquitetura TCP/IP, incluindo o protocolo IP, ICMP, ARP, RARP, DHCP e DNS. O protocolo IP fornece encaminhamento de pacotes entre redes heterogêneas, enquanto protocolos como ICMP, ARP e RARP fornecem funcionalidades adicionais como detecção de erros, mapeamento de endereços e configuração automática.
Redes de computadores II - 1.Arquitetura TCP/IPMauro Tapajós
O documento descreve os protocolos TCP/IP, especificamente o protocolo IP. O IP interconecta redes heterogêneas, permite a construção de grandes redes com pouco gerenciamento centralizado e é uma rede "best-effort" onde podem ocorrer atrasos e perda de pacotes. O IP define o formato dos pacotes e algoritmos de encaminhamento entre hosts em redes diferentes.
Arquitetura de Computadores: Processos e ThreadsEvandro Júnior
O documento discute processos em sistemas operacionais. Aborda conceitos como criação, término e hierarquia de processos, além de estados de processos e escalonamento de processos. Explica diferentes algoritmos de escalonamento como FIFO, Round Robin e múltiplas filas. Também discute threads como forma de dividir um processo em tarefas concorrentes.
Slides de suporte da aula de Redes de Computadores - Continuar pesquisas nas bibliografias:
TANENBAUM, Andrew S. Redes de Computadores. Editora Campus, 4 Edição. 2003.
COMER, Douglas E. Interligação de Redes com TCP/IP, volume 1. Editora Campus, 5 Edição. 2006.
TORRES, Gabriel. Redes de Computadores Curso Completo. 1 ed. Editora Axcel Books. 2001.
O documento discute os protocolos de camada de enlace, incluindo PPP e MPLS. PPP é usado para conexões ponto a ponto e negocia endereços de rede entre extremidades. MPLS é usado para roteamento eficiente baseado em rótulos e permite engenharia de tráfego.
O Parallel Virtual Machine (PVM) permite a execução de tarefas em máquinas distribuídas de forma transparente ao usuário. Ele fornece primitivas de alto nível para comunicação e sincronização entre processos através de mensagens, permitindo escalabilidade, heterogeneidade e tolerância a falhas. A biblioteca PVM facilita a programação em rede através de uma interface simples e portável entre diferentes sistemas.
Leslie Lamport é um cientista da computação conhecido por suas contribuições fundamentais para a teoria de sistemas distribuídos. Ele desenvolveu os relógios lógicos de Lamport, que permitem a ordenação total de eventos em sistemas distribuídos através da atribuição de marcas temporais aos eventos. O algoritmo de Lamport é amplamente utilizado em algoritmos distribuídos como exclusão mútua e multicast totalmente ordenado.
O documento descreve um experimento realizado para analisar o tráfego de rede usando a ferramenta Wireshark. O experimento envolveu acessar um site web e capturar os pacotes de rede para analisar os protocolos TCP, UDP, ARP e HTTP. Os resultados mostraram os protocolos usados na comunicação entre o navegador e o servidor web durante o carregamento da página.
Análise de Desempenho de Algoritmos de Controle de Congestionamento TCP utili...Felipe Alex
Este documento apresenta um resumo de uma dissertação de mestrado que avalia o desempenho de diferentes algoritmos de controle de congestionamento TCP em diferentes cenários de rede simulados. O documento descreve os objetivos, métodos e principais conclusões da dissertação, que encontrou que o algoritmo TCP Vegas teve o melhor desempenho geral na maioria dos cenários simulados.
O documento discute os conceitos de processos, threads, comunicação entre processos e problemas clássicos relacionados. Aborda técnicas como semáforos, monitores e regiões críticas para sincronização de acesso a recursos compartilhados e evitar condições de corrida. Apresenta exemplos como o problema do produtor-consumidor, jantar dos filósofos e barbeiro sonolento.
O documento descreve a implementação do protocolo RDT 3.0 para transferência confiável de dados através de redes, cobrindo a evolução dos protocolos RDT de versões anteriores e a implementação do código usando máquina de estados finitos e modelagem UML.
O documento fornece uma introdução aos protocolos TCP e UDP, descrevendo suas principais características e diferenças. TCP é orientado a conexão e fornece entrega confiável de dados através de confirmações, enquanto UDP é sem conexão e não garante entrega. Ambos usam números de porta para direcionar pacotes a aplicativos.
O documento discute vários métodos para exclusão mútua entre processos, incluindo desabilitar interrupções, variáveis de impedimento, alternância obrigatória, a solução de Peterson e a instrução TSL. Além disso, aborda semáforos, monitores, troca de mensagens e barreiras para sincronização de processos, bem como técnicas de escalonamento em sistemas em lote e interativos.
Um processo é um container que fornece recursos e isolamento para um programa em execução. Um processo pode estar em vários estados como new, ready, running, waiting ou terminated. Um sistema operacional usa threads para permitir a execução paralela de tarefas dentro de um mesmo processo.
Redes de computadores II - 4.Camada de Transporte TCP e UDPMauro Tapajós
O documento descreve os principais conceitos da camada de transporte no modelo TCP/IP, incluindo protocolos como TCP e UDP. O TCP implementa conexões orientadas a conexão de forma confiável através de mecanismos como três-way handshake, janelas deslizantes e controle de congestionamento. O UDP fornece serviço não orientado a conexão baseado em datagramas.
O documento discute algoritmos de escalonamento de processos em sistemas operacionais, incluindo Round Robin, prioridade e múltiplas filas. Round Robin atribui um quantum de tempo para cada processo antes de alternar para o próximo. Prioridade executa processos com prioridade mais alta primeiro. Múltiplas filas agrupam processos por tipo para execução.
O documento discute processos e threads no sistema operacional. Aborda conceitos como processos, threads, comunicação entre processos, estados de processos e implementação de processos e threads no kernel.
O documento descreve os protocolos UDP e TCP da camada de transporte. Brevemente discute como a camada de transporte é responsável pela comunicação entre processos através do paradigma cliente-servidor e do uso de endereços de porta para identificar processos únicos. Também resume as principais diferenças entre UDP, um protocolo não confiável e sem conexão, e TCP, um protocolo confiável e orientado a conexão.
Cluster é um grupo de computadores que trabalham juntos para fornecer recursos de alta disponibilidade e balanceamento de carga como um único sistema. O serviço de Balanceamento de Carga de Rede (NLB) melhora a disponibilidade de aplicativos de servidor como web, FTP e firewall distribuindo a carga entre os nós. Clusters podem ser configurados de várias formas como cluster de nó único, cluster com quorum único ou cluster principal de conjunto de nós.
Sistemas Operacionais Processos e Threads - Wellington Pinto de OliveiraWellington Oliveira
O documento discute processos e threads em sistemas operacionais. Aborda tópicos como criação e término de processos, hierarquia de processos, estados de processos, implementação de processos, modelo de threads, comunicação interprocesso usando regiões críticas, semáforos, monitores e problemas clássicos como produtor-consumidor, jantar dos filósofos e escalonamento.
Este documento discute os princípios e tecnologias da camada de enlace de dados. Ele introduz os objetivos e serviços da camada de enlace, incluindo detecção e correção de erros, compartilhamento de canal, endereçamento e transferência confiável de dados. Ele também discute implementações específicas como Ethernet, protocolos de acesso múltiplo e endereçamento MAC.
O documento descreve os principais protocolos da arquitetura TCP/IP, incluindo o protocolo IP, ICMP, ARP, RARP, DHCP e DNS. O protocolo IP fornece encaminhamento de pacotes entre redes heterogêneas, enquanto protocolos como ICMP, ARP e RARP fornecem funcionalidades adicionais como detecção de erros, mapeamento de endereços e configuração automática.
Redes de computadores II - 1.Arquitetura TCP/IPMauro Tapajós
O documento descreve os protocolos TCP/IP, especificamente o protocolo IP. O IP interconecta redes heterogêneas, permite a construção de grandes redes com pouco gerenciamento centralizado e é uma rede "best-effort" onde podem ocorrer atrasos e perda de pacotes. O IP define o formato dos pacotes e algoritmos de encaminhamento entre hosts em redes diferentes.
Arquitetura de Computadores: Processos e ThreadsEvandro Júnior
O documento discute processos em sistemas operacionais. Aborda conceitos como criação, término e hierarquia de processos, além de estados de processos e escalonamento de processos. Explica diferentes algoritmos de escalonamento como FIFO, Round Robin e múltiplas filas. Também discute threads como forma de dividir um processo em tarefas concorrentes.
Slides de suporte da aula de Redes de Computadores - Continuar pesquisas nas bibliografias:
TANENBAUM, Andrew S. Redes de Computadores. Editora Campus, 4 Edição. 2003.
COMER, Douglas E. Interligação de Redes com TCP/IP, volume 1. Editora Campus, 5 Edição. 2006.
TORRES, Gabriel. Redes de Computadores Curso Completo. 1 ed. Editora Axcel Books. 2001.
O documento discute os protocolos de camada de enlace, incluindo PPP e MPLS. PPP é usado para conexões ponto a ponto e negocia endereços de rede entre extremidades. MPLS é usado para roteamento eficiente baseado em rótulos e permite engenharia de tráfego.
O Parallel Virtual Machine (PVM) permite a execução de tarefas em máquinas distribuídas de forma transparente ao usuário. Ele fornece primitivas de alto nível para comunicação e sincronização entre processos através de mensagens, permitindo escalabilidade, heterogeneidade e tolerância a falhas. A biblioteca PVM facilita a programação em rede através de uma interface simples e portável entre diferentes sistemas.
Leslie Lamport é um cientista da computação conhecido por suas contribuições fundamentais para a teoria de sistemas distribuídos. Ele desenvolveu os relógios lógicos de Lamport, que permitem a ordenação total de eventos em sistemas distribuídos através da atribuição de marcas temporais aos eventos. O algoritmo de Lamport é amplamente utilizado em algoritmos distribuídos como exclusão mútua e multicast totalmente ordenado.
O documento descreve um experimento realizado para analisar o tráfego de rede usando a ferramenta Wireshark. O experimento envolveu acessar um site web e capturar os pacotes de rede para analisar os protocolos TCP, UDP, ARP e HTTP. Os resultados mostraram os protocolos usados na comunicação entre o navegador e o servidor web durante o carregamento da página.
O documento descreve como usar a ferramenta Wireshark para analisar o tráfego de rede, incluindo a instalação do Wireshark, captura de pacotes e análise dos protocolos usados como HTTP e TCP. Um experimento é descrito para ilustrar o uso do Wireshark para monitorar uma sessão de navegação na web.
1. Protocolos de comunicação estabelecem formalidades para comunicação entre nós de rede, avaliando-se conjuntos de formalidades em diversas camadas. Protocolos lógicos tratam da rede lógica e protocolos físicos do meio físico.
2. Protocolos nas camadas físicas podem ser insuficientes, necessitando camadas de software auxiliares que estabelecem protocolos lógicos para garantir envio e recebimento de informação.
3. Protocolos tratam do envio e recebimento de informação nas v
Este artigo descreve como usar a ferramenta Wireshark para analisar o tráfego gerado por uma aplicação web, incluindo a caracterização dos protocolos, objetos e ações de conexão e transferência de dados. O artigo também fornece conceitos sobre o protocolo TCP e como ele controla o estado da transmissão entre máquinas.
Um Injetor de Falhas para a Avaliação de Aplicações Distribuídas Baseadas no ...Dalton Valadares
Um Injetor de Falhas para a Avaliação de Aplicações Distribuídas Baseadas no Commune
Autores: Dalton Cézane, Diego Renato, Miguel Queiroga, Sabrina Souto, Marco A. Spohn
SBRC 2009
O documento descreve um simulador de eventos discretos para simular um buffer de pacotes. Resume os principais pontos:
1) O simulador usa processos de nascimento e morte e diagramas de estado para modelar transições entre estados.
2) Ele aplica equações de equilíbrio para calcular métricas como número médio de elementos e tempo médio de permanência.
3) A arquitetura do simulador agenda eventos em uma fila por ordem de tempo para avançar a simulação.
Analisando O Caminho Dos Pacotes No Wireshark Stalinstalinstm
Este documento discute a análise do tráfego de rede usando o Wireshark. Ele resume o que é gerenciamento de rede, descreve alguns protocolos comuns como TCP e HTTP, e detalha um experimento onde o Wireshark foi usado para examinar os caminhos dos pacotes em uma rede e facilitar o gerenciamento da rede.
O documento descreve um experimento utilizando o analisador de pacotes Wareshark para capturar e analisar o tráfego de rede ao acessar um site específico. O experimento mostra os protocolos TCP e IP em ação, com pacotes SYN, ACK e FIN sendo trocados entre o cliente e o servidor durante o estabelecimento e encerramento da conexão. O autor conclui que ainda precisa aprender mais sobre redes de computadores.
O documento descreve um experimento utilizando o analisador de pacotes Wareshark para capturar e analisar o tráfego de rede ao acessar um site específico. O experimento mostra os protocolos TCP e IP em ação, com o cliente enviando pedidos SYN e ACK e o servidor respondendo com ACK e envio de arquivos, demonstrando o funcionamento básico da comunicação em rede.
Aplicação das Redes Neuronais Artificiais do software STATISTICA 7.0: O caso ...Ricardo Brasil
Este documento descreve diferentes tipos de redes neurais artificiais no software STATISTICA e aplica essas redes para modelar a expansão urbana da cidade de Maputo. Os autores treinam redes neurais com dados sobre declive, uso do solo e vias para Maputo em 1991 e 2001 e analisam os resultados para comparar os diferentes tipos de redes.
Segurança na Interoperabilidade de Redes TCP IPBruno Milani
O documento discute a segurança na interoperabilidade de redes TCP/IP, descrevendo vulnerabilidades comuns nos protocolos TCP e IP e cenários de ataque, como SYN floods e IP spoofing. Ele também explica as camadas da pilha de protocolos TCP/IP e a importância da interoperabilidade entre sistemas.
Análise de Tráfego da Rede Utilizando o WiresharkIgor Bruno
Este artigo descreve como a ferramenta Wireshark pode ser usada para analisar o tráfego de rede, capturando pacotes TCP/IP durante testes em sala de aula. Também discute conceitos básicos de gerenciamento e segurança de redes.
Artigo Analise De Redes Pelo Wireshark IgorIgor Bruno
Este artigo descreve como a ferramenta Wireshark analisa o tráfego de rede, capturando pacotes TCP/IP e mostrando informações como endereços MAC e números de sequência. O documento também discute conceitos como gerenciamento de redes, monitoramento e protocolos como ARP.
Este documento discute o uso da linguagem JavaScript no servidor para construir aplicações web em tempo real e de alta concurrencia. O autor apresenta os desafios da programação multithread e como o modelo de programação assíncrono e orientado a eventos do Node.js pode resolver problemas de escalabilidade. O trabalho descreve a arquitetura do Node.js e seu potencial para suportar muitas conexões simultâneas de forma leve e eficiente.
O documento descreve o protocolo TCP/IP, que é um conjunto de protocolos usados para transmitir dados na Internet. TCP/IP funciona em quatro camadas, com TCP na camada de transporte responsável por receber dados, verificar a integridade e dividir em pacotes antes de encaminhar para a camada de internet. TCP permite comunicação segura e confiável entre aplicações, independentemente das camadas inferiores.
We define a distributed system as one in which hardware and software are located on computer networks and communicate and coordinate their actions through the messaging system. According to Andrew Tanenbaum, is a "collection of independent computers that appears to the user as a single, consistent system" since the second George Coulouris, is a "collection of autonomous computers interconnected by a computer network and equipped with software that allows sharing of system resources: hardware, software and data. "
Este artigo descreve o uso da ferramenta WireShark para caracterizar o tráfego de dados gerado ao acessar um site web específico. Primeiro, o autor reinicia o sistema e prepara o WireShark para captura. Em seguida, acessa o site web e observa a captura para caracterizar os protocolos, objetos, ações de conexão e transferência de dados. O WireShark facilita o gerenciamento de redes ao permitir o monitoramento do tráfego de pacotes.
Este documento descreve o uso do software Wireshark para analisar pacotes de dados gerados ao acessar um site específico. Ele detalha como o DNS, TCP, ICMP e HTTP foram usados nessa transmissão de dados e como o Wireshark capturou os pacotes para análise dos protocolos envolvidos.
1. Implementa¸c˜ao do algoritmo de exclus˜ao m´utua de Lamport
usando um framework de implementa¸c˜ao de algoritmos
distribu´ıdos
Alvaro Augustho de Souza Silva
Orientador: Luiz Eduardo Buzato
4 de novembro de 2011
Resumo
Neste documento ser´a apresentada uma implementa¸c˜ao em Java do algoritmo de ex-
clus˜ao m´utua de Lamport [1], baseado em rel´ogio l´ogicos, com o uso do framework
Neko. O Neko [3] ´e um framework desenvolvido para facilitar o desenvolvimento e im-
plementa¸c˜ao de algoritmos distribu´ıdos. O escolha do algoritmo de Lamport foi com
o objetivo de apresentar o funcionamento deste em um ambiente distribu´ıdo real (no
caso um cluster de 5 computadores) e os poss´ıveis usos dele e do pr´oprio Neko. Foi im-
plementado um mecanismo de gera¸c˜ao de log da troca de mensagens entre os processos
em um arquivo de texto simples, e com este log pˆode-se gerar um diagrama visual da
execu¸c˜ao correspondente a ele, em que um gr´afico representava a troca de mensagens
entre os n´os por meio de setas coloridas e etiquetas mostrando o tipos de mensagens
sendo enviadas. O programa usado para gerar este diagrama chama-se LogView e foi
feito em um projeto de semestre num instituto de tecnologia na Sui¸ca, com supervis˜ao
de um dos autores do Neko. O LogView [2] usado aqui foi modificado por mim, de
forma que ele pudesse exibir mais detalhes da troca de mensagens que a vers˜ao original
n˜ao exibia, como os tempos de envio e recebimento da mensagem, o tipo dela, algumas
mudan¸cas na interface de forma a tornar a visualiza¸c˜ao um pouco mais clara, entre
outras modifica¸c˜oes.
1 Introdu¸c˜ao
O problema da exclus˜ao m´utua ´e um ponto crucial de preocupa¸c˜ao em sistemas que com-
partilham recursos entre processos em v´arios computadores, ou mesmo threads de execu¸c˜ao
de um processo sendo executado em um ´unico computador. A quest˜ao ´e evitar que dois ou
mais processos ou threads tenham acesso simultaneamente a este recurso compartilhado,
comumente chamado de regi˜ao cr´ıtica (r.c.). A solu¸c˜ao apresentada para este problema
por Leslie Lamport em seu artigo Time, clocks, and the ordering of events in a distributed
system de 1978 se baseia na id´eia de timestamps. Timestamps s˜ao contadores monotonica-
mente crescentes mantidos unicamente por cada processo, e que seguem as trˆes seguintes
regras:
1
2. 1. Um processo incrementa seu contador antes de cada evento neste processo.
2. Quando um processo envia uma mensagem, ele inclui seu pr´oprio contador na men-
sagem enviada.
3. Ao receber uma mensagem, o processo recipiente atualiza seu pr´oprio contador para
que ele seja maior que o m´aximo entre seu valor atual e o valor recebido na mensagem,
antes que ele considere a mensagem como recebida.
Com este contador e estas regras simples ´e poss´ıvel estabelecer uma rela¸c˜ao de an-
tecedˆencia entre eventos numa execu¸c˜ao distribu´ıda. A partir da id´eia de timestamps o
algoritmo de exclus˜ao m´utua de Lamport se desenvolve. Antes de mostr´a-lo ´e necess´ario
mencionar um elemento crucial em seu funcionamento: cada processo mant´em um vetor de
mensagens com tamanho igual ao n´umero de processos presentes no ambiente distribu´ıdo,
incluindo ele pr´oprio. Cada posi¸c˜ao deste vetor guarda a ´ultima mensagem recebida pelo
processo corresponte a esta posi¸c˜ao (todos os processos tem identificadores, que v˜ao de 0 a
n-1, sendo n o n´umero de processos; este identificador se chama PID). Assim, cada processo
consegue saber o timestamp da ´ultima mensagem recebida de cada outro processo, e isso
´e necess´ario para o funcionamente do algoritmo. Quando este texto se referir ao vetor de
mensagens ou simplesmente ao vetor ele estar´a se referindo a este elemento. O algoritmo
se baseia nas seguintes regras:
• Envio de requisi¸c˜ao para entrada na r.c.: um processo envia uma mensagem de req-
uisi¸c˜ao req para todos os outros processos com um timestamp (valor do seu rel´ogio
l´ogico atual), e adiciona a requisi¸c˜ao rotulada com o timestamp ao vetor de mensagens,
na posi¸c˜ao correspondente a ele mesmo.
• Recep¸c˜ao de requisi¸c˜ao: a mensagem de requisi¸c˜ao, com o timestamp gravado nela, ´e
colocada no vetor na posi¸c˜ao correspondente ao processo remetente, e um reconheci-
mento ack ´e enviado a ele.
• Libera¸c˜ao da r.c.: um processo envia uma mensagem de libera¸c˜ao rel para todos os
outros processos.
• Recep¸c˜ao de rel: a requisi¸c˜ao correspondente `a libera¸c˜ao ´e removida do vetor de
mensagens.
• Entrada na r.c. (guarda): um processo determina que pode entrar na r.c. se e
somente se:
1. ele tem uma requisi¸c˜ao no vetor com timestamp t
2. t ´e o menor timestamp no vetor
3. se t for igual a outro timestamp no vetor, o acesso ser´a concedido ao processo
que tiver o menor identificador de processo (PID)
2
3. A entrada na r.c. ´e determinada pela ordena¸c˜ao total gerada pelos rel´ogios l´ogicos.
Quando a guarda de de Pi torna-se verdadeira (o processo ´e autorizado a entrar na r.c.)
n˜ao existe outra requisi¸c˜ao no sistema (no vetor de mensagens ou em trˆansito) que tenha
timestamp menor que o da requisi¸c˜ao de Pi. Para que ele entre ´e necess´ario que o estado
das demais posi¸c˜oes do vetor de mensagens tenha sido atualizado com timestamps maiores
que o da requisi¸c˜ao de Pi; essa atualiza¸c˜ao ´e garantida pelo ack e pelo fato dos canais de
comunica¸c˜ao serem FIFO. Portanto, ´e garantida a justi¸ca e os deadlocks devido `a ordena¸c˜ao
total.
J´a a exclus˜ao m´utua ´e garantida porque o processo que entra na regi˜ao cr´ıtica somente
remover´a a sua requisi¸c˜ao do vetor dos demais processos depois que a tiver deixado e enviado
uma mensagem de release com rel´ogio l´ogico maior para todos eles. Novamente o mecanismo
de rel´ogio l´ogico garante que o algoritmo est´a correto.
Este texto trata da implementa¸c˜ao deste algoritmo para a execu¸c˜ao em um cluster
de cinco computadores, sendo cada computador um processo na execu¸c˜ao, atrav´es do uso
de um framework para a constru¸c˜ao de algoritmos distribu´ıdos chamado Neko. O Neko
´e um framework desenvolvido em Java, e dispon´ıvel na internet para download e uso (ver
bibliografia). Ele foi escrito no Distributed Systems Laboratory do Swiss Federal Institute of
Technology in Lausanne (EPFL), por X´avier D´efago e P´eter Urb´an, em conjunto com outros
estudantes. Seu desenvolvimento continuou no Japan Advanced Institute of Technology
(JAIST), grupo DDSG, e na Universid´ad Polit´ecnica de Madrid, laborat´orio LSD. Ele ´e
mantido principalmente por P´eter Urb´an, e veio sendo desenvolvido desde 2000.
Esta pequena introdu¸c˜ao explicou brevemente o algoritmo de exclus˜ao m´utua aqui im-
plementado e deu uma id´eia de o que ´e o Neko. O restante do texto est´a estruturado
da seguinte forma. A se¸c˜ao 2 explicar´a em mais profundidade o que ´e e como funciona o
framework Neko, e como algoritmos distribu´ıdos s˜ao implementados e executados quando
se usa ele. Em seguida, na se¸c˜ao 3 ´e apresentada a implementa¸c˜ao do algoritmo em si,
explicando cada classe em detalhes, a forma como elas se ligam, como a pilha de protocolos
em cada processo ´e montada antes da execu¸c˜ao, e como ela se comporta durante a execu¸c˜ao,
seja ela simulada (que n˜ao ser´a mostrada aqui) ou distribu´ıda num ambiente de rede real.
Em seguida, na se¸c˜ao 4 finalmente ´e apresentado como essa implementa¸c˜ao ´e colocada em
funcionamento, mostrando como inicializar cada processo e a execu¸c˜ao em si, e o que ´e
mostrado indicando que o algoritmo est´a realmente sendo executado. Ap´os isso, na se¸c˜ao
5 s˜ao mostradas as classes respons´aveis pela gera¸c˜ao do log da execu¸c˜ao. O log gerado
numa execu¸c˜ao e o uso dele para criar o diagrama de execu¸c˜ao no LogView ´e mostrado na
se¸c˜ao 6. Por fim, uma conclus˜ao ´e apresentada na se¸c˜ao 7, listando os pr´os e os contras do
Neko e comentando a vantagem de se poder visualizar o funcionamento de um algoritmo
executando de forma distribu´ıda de verdade num diagrama visual e intuitivo que mostra a
troca de mensagens que est´a ocorrendo.
2 Neko: Arquitetura e Funcionamento
O Neko ´e uma ´e uma plataforma de comunica¸c˜ao que permite tanto simular um algoritmo
distribu´ıdo numa ´unica m´aquina quanto execu¸c˜oes verdadeiramente distribu´ıdas em v´arias
3
4. Figura 1: Estrutura em camadas de uma aplica¸c˜ao usando o Neko
m´aquinas, numa rede de computadores, usando a mesma implementa¸c˜ao para um algoritmo.
Ele foi feito em Java, com o objetivo de simplificar o desenvolvimento de algoritmos dis-
tribu´ıdos, diminuindo o tempo de implementa¸c˜ao e testes e facilitando a execu¸c˜ao e estudo
dos resultados.
Como ´e mostrado na Figura 1, a arquitetura do Neko consiste de duas partes principais:
aplica¸c˜ao (aplication) e rede (networks). No n´ıvel da aplica¸c˜ao, uma cole¸c˜ao de processos
(numerados de 0 a n-1) comunicam-se atrav´es de uma interface simples de troca de men-
sagens: um processo sender coloca sua mensagem na rede com a primitiva ass´ıncrona send
e a rede ent˜ao entrega essa mensagem ao processo destinat´ario com a primitiva deliver.
Processo s˜ao implementados como programas em v´arias camadas.
A comunica¸c˜ao n˜ao ´e uma caixa-preta: a infrastrutura de troca de mensagens pode ser
controlada de v´arias maneiras. Primeiro, uma rede pode ser instanciada de uma cole¸c˜ao
de redes pr´e-definidas, como uma rede real usando TCP/IP ou uma Ethernet simulada.
Segundo, o Neko consegue controlar v´arias redes em paralelo. Terceiro, redes que extendem
e modificam as existentes s˜ao facilmente implement´aveis. O fato de o c´odigo ser aberto e a
linguagem de implementa¸c˜ao ser Java facilitam muito a moldagem da plataforma ao gosto
do usu´ario.
Mas, em geral, n˜ao ´e necess´aria a modifica¸c˜ao do c´odigo-fonte do Neko; ele j´a oferece uma
plataforma pronta, simples e completa para o teste e implementa¸c˜ao de muitos algoritmos.
O algoritmo de exclus˜ao m´utua de Lamport foi implementado apenas usando as ferramentas
e classes de Java disponibilizadas por ele na sua vers˜ao atual (Neko 1.0 beta 1, colocada `a
disposi¸c˜ao para download e uso no site oficial do projeto Neko em 16 de junho de 2009).
Para a execu¸c˜ao do algoritmo um arquivo simples de configura¸c˜ao ´e necess´ario. O que
foi usado aqui ser´a apresentado e explicado para maior clareza de sua fun¸c˜ao e para mostrar
melhor um detalhe importante da plataforma Neko. Os c´odigos das classes representando o
algoritmo de Lamport tamb´em ser˜ao explicados detalhadamente, e assim tanto ele quanto
4
5. a plataforma devem ser bem apresentados.
Vamos `a exposi¸c˜ao do c´odigo implementando o algoritmo e a exclus˜ao m´utua distribu´ıda.
3 A Implementa¸c˜ao do Algoritmo
3.1 A Interface MEAlgorithm
A exposi¸c˜ao da implementa¸c˜ao da exclus˜ao m´utua ser´a come¸cada mostrando uma interface
simples, criada com o objetivo de simplificar o programa:
package lamport;
public interface MEAlgorithm {
public void enterCriticalSection();
public void exitCriticalSection();
}
Os dois m´etodos da interface s˜ao enterCriticalSection e exitCriticalSection.
Como os pr´oprios nomes dizem, o primeiro ´e chamado quando uma classe que use um
objeto que faz uso desta interface deseja entrar numa se¸c˜ao cr´ıtica do c´odigo, que usa dados
compartilhados entre processos, e para isso quer garantir acesso exclusivo e sem risco de
encontrar ou criar incosistˆencias. Quando a aplica¸c˜ao terminar de usar essa regi˜ao cr´ıtica
ela deve chamar exitCriticalSection, que faz o que for necess´ario para liberar o acesso
`a essa regi˜ao e deixar os outros processos cientes de que ningu´em mais tem a prioridade.
3.2 A Classe Que Faz Uso da Exclus˜ao M´utua: Application.java
Antes de mostrar a implementa¸c˜ao do algoritmo propriamente dita ser´a apresentada a classe
que chama os m´etodos da interface acima para entrar e sair da regi˜ao cr´ıtica sem o perigo
de gerar incosistˆencias de dados:
package lamport;
// java imports:
import java.util.Random;
//lse.neko imports:
import lse.neko.ActiveReceiver;
import lse.neko.NekoProcess;
import lse.neko.SenderInterface;
public class Application extends ActiveReceiver
{
private SenderInterface sender;
public void setSender(SenderInterface sender)
{
this.sender = sender;
}
/* O algoritmo de exclus~ao m´utua deste processo.
* Este m´etodo ´e usado pela classe MEInitializer no momento da cria¸c~ao dos processos. */
private MEAlgorithm algorithm;
5
6. public void setMEAlgorithm(MEAlgorithm algorithm)
{
this.algorithm = algorithm;
}
/* o PID deste processo */
private int me;
/* o n´umero de processos
private int n;
/* objeto gerador de n´umeros aleat´orios */
private Random random;
public Application(NekoProcess process) {
super(process, "[Aplica¸c~ao] Thread-p" + process.getID());
me = process.getID();
n = process.getN();
}
A primeira parte do c´odigo faz as importa¸c˜oes de classes necess´arias. Esta classe estende
ActiveReceiver, uma classe do Neko que cria objetos capazes de receber ativamente men-
sagens que forem enviadas a eles, ao inv´es de simplesmente esperar elas serem entregues.
Seu funcionamento ser´a melhor entendido quando o algoritmo for apresentado; ele foi im-
plementado usando o funcionamento desta classe.
Neste come¸co tamb´em ´e criado o objeto Sender que tratar´a de enviar as mensagens que
porventura devam ser enviadas a outros processos, e por fim o algoritmo de exclus˜ao m´utua
a ser usado. Se eu tivesse implementado outro algoritmo em outra classe, bastava que ele
implementasse a mesma interface. Para escolher um e n˜ao outro, o arquivo de configura¸c˜ao
mencionado anteriormente seria usado.
Por fim, o construtor desta classe ´e mostrado. Ele chama o construtor da classe
NekoThread, a que ActiveReceiver estende, usando super. Esse construtor recebe um
objeto NekoProcess, que representa o processo que ser´a criado, e um nome ´e passado para
nomear a thread deste novo processo. ´E inicializada tamb´em uma vari´avel que guarda
o pr´oprio PID, me, e outra que guarda o n´umero de processos no ambiente de execu¸c˜ao.
Ambos ser˜ao usados `a frente.
public void run()
{
if(me == (n-1))
System.out.println("Processo " + me + " fazendo logging da execu¸c~ao...");
else {
System.out.println("Processo " + me + " tentando entrar na r.c..");
littleSleep(-1);
algorithm.enterCriticalSection();
6
7. System.out.println("nn--------------- Processo " + me + " entrou na r.c. ---------------n");
littleSleep(8000);
System.out.println("Processo " + me + " saindo da r.c..");
algorithm.exitCriticalSection();
System.out.println("n----------------- Processo " + me + " saiu da r.c.-----------------nn");
littleSleep(8000);
}
}
Este ´e o m´etodo run que ficar´a executando em loop na thread do processo at´e que o
usu´ario termine a execu¸c˜ao. Basicamente, o que ele faz ´e ficar entrando e saindo da regi˜ao
cr´ıtica, e dormindo v´arias vezes para que a execu¸c˜ao n˜ao fique muito r´apida e possa ser
acompanhada por quem estiver monitorando. Caso o processo atual n˜ao tenha a prioridade
para entrar na r.c. no momento, mensagens ser˜ao impressas na tela esperando que a prior-
idade seja passada a ele. Mas isso ´e tratado na classe que implementa o algoritmo e ser´a
mostrado daqui a pouco. O m´etodo littleSleep coloca o processo em sleep e ´e mostrado
abaixo. O teste inicial ´e feito porque o processo n´umero n-1 ficar´a respons´avel pelo logging
da execu¸c˜ao, e n˜ao executar´a normalmente um n´o do algoritmo.
private void littleSleep(int k) {
int sleepTime;
random = new Random();
if(k != -1) sleepTime = k;
else sleepTime = random.nextInt(8000);
try {
sleep(sleepTime);
} catch (InterruptedException e) {
System.out.println("Erro ao tentar dormir na aplica¸c~ao.");
}
}
}
Esse m´etodo coloca o processo em sleep por tempos aleat´orios de at´e 8 segundos, exceto
quando a thread est´a dentro da r.c., quando ela dorme exatamente por 8 segundos, para
depois acordar e sair da regi˜ao.
Como d´a para perceber, seria poss´ıvel implementar algo ´util durante o tempo que o
processo ganha a prioridade para a regi˜ao cr´ıtica. Basta retirar o sleep de 8 segundos e
colocar algo nessa parte. Aqui o sleep foi usado para demonstrar que a exclus˜ao m´utua
estava funcionando.
7
8. 3.3 A Classe de Inicializa¸c˜ao: MEInitializer.java
Para montar a estrutura de processos necess´aria para a execu¸c˜ao de um algoritmo no Neko
package lamport;
// lse.neko imports:
import lse.neko.NekoProcess;
import lse.neko.NekoProcessInitializer;
import lse.neko.ReceiverInterface;
import lse.neko.SenderInterface;
// other imports:
import org.apache.java.util.Configurations;
public class MEInitializer
implements NekoProcessInitializer
{
public MEInitializer() {
}
public void init(NekoProcess process, Configurations config)
throws Exception
{
/* Primeiro, constr´oi a pilha de protocolos e configura a rede. */
/* Camada da aplica¸c~ao */
Class applicationClass =
Class.forName(config.getString("application"));
Class[] appConstructorParamClasses = { NekoProcess.class };
Object[] appConstructorParams = { process };
ReceiverInterface application = (ReceiverInterface)
applicationClass
.getConstructor(appConstructorParamClasses)
.newInstance(appConstructorParams);
application.setId("app");
/* Camada do algoritmo */
Class algorithmClass =
Class.forName(config.getString("algorithm"));
Class[] algConstructorParamClasses = { NekoProcess.class };
Object[] algConstructorParams = { process };
ReceiverInterface algorithm = (ReceiverInterface)
algorithmClass
.getConstructor(algConstructorParamClasses)
.newInstance(algConstructorParams);
algorithm.setId("alg");
/* Configura a rede. */
SenderInterface net = process.getDefaultNetwork();
Na primeira parte s˜ao criados os objetos usados na pilha de protocolos. Neste caso s˜ao
trˆes: a camada da aplica¸c˜ao, mostrada anteriormente, a camada do algoritmo, usando uma
8
9. classe que ser´a mostrada a seguir, e o objeto ’net’, que implementa a camada de rede e
tratar´a da troca de mensagens, envio e entrega, entre os processos.
Como pode-se perceber, foi usado uma propriedade do Java chamada Reflection. Isso
´e usado para podermos saber em tempo de execu¸c˜ao qual a classe da aplica¸c˜ao e a do
algoritmo, que dever˜ao estar no arquivo de configura¸c˜ao. Fazendo assim, podemos usar
uma classe de inicializa¸c˜ao apenas (esta mesma) e escrever v´arias aplica¸c˜oes e algoritmos,
bastando mudar uma linha no arquivo de configura¸c˜ao para trocar entre elas. Se n˜ao
quis´essemos isso, bastava criar os objetos fazendo ReceiverInterface application = new
Application(process) para a camada de aplica¸c˜ao, e ReceiverInterface algorithm =
new LamportME(process), mas a flexibilidade e modularidade da nossa implementa¸c˜ao
ficaria prejudicada. Essa decis˜ao fica a cargo do programador.
ReceiverInterface ´e uma interface do Neko que s´o tem um m´etodo: deliver. Ele tem
o papel de gerenciar mensagens recebidas. ActiveReceiver implementa esta interface e
sobrescreve este m´etodo de modo que ele joga numa queue as mensagens recebidas. O
m´etodo receive que ele tamb´em implementa, por sua vez, retira mensagens da fila e entrega
ao processo que o chama, o destinat´ario original delas. A classe da aplica¸c˜ao estende
ActiveReceiver, mas n˜ao faz uso deste m´etodo; a classe que implementa o algoritmo far´a
amplo uso dele, como ser´a mostrado em breve.
/* Segundo, liga as camadas. */
/* Configura o objeto Sender que a aplica¸c~ao pode usar para mandar mensagens. */
applicationClass
.getMethod("setSender", new Class[] { SenderInterface.class })
.invoke(application, new Object[] { net });
/* Configura a camada do algoritmo criada anteriormente para ser usada
* pela camada de aplica¸c~ao quando ela quiser garantir exclus~ao m´utua
* no acesso `a regi~ao cr´ıtica. */
applicationClass
.getMethod("setMEAlgorithm", new Class[] { MEAlgorithm.class })
.invoke(application, new Object[] { algorithm });
/* Configura o objeto Sender que a camada do algoritmo usar´a para mandar mensagens. */
algorithmClass
.getMethod("setSender", new Class[] { SenderInterface.class })
.invoke(algorithm, new Object[] { net });
Continuando a usar Java Reflection, esta segunda parte liga as camadas da pilha de
protocolos do processo que est´a sendo constru´ıdo. Usa m´etodos pr´oprios das classes Appli-
cation, que usa setMEAlgorithm para dizer que o objeto ’algorithm’ criado anteriormente
´e o que deve ser usado como gerenciador da exclus˜ao m´utua, e setSender em ambos Appli-
cation e LamportME (a classe do algoritmo) para dizer que ’net’ ´e o objeto que gerenciar´a
a troca de mensagens na rede entre os processos.
// Terceira, inicia a execu¸c~ao dos protocolos.
application.launch();
algorithm.launch();
9
10. }
}
Por ´ultimo, as camadas s˜ao lan¸cadas, e por conseguinte o processo. O m´etodo launch
come¸ca a execu¸c˜ao das threads e deve ser usado para este fim.
3.4 A Classe que Implementa o Algoritmo: LamportME.java
Ser´a apresentada finalmente a classe que implementa a execu¸c˜ao do algoritmo de exclus˜ao
m´utua de Lamport. O tamanho dela ´e relativamente extenso, mas cada m´etodo ´e bastante
simples de entender, apenas seguindo `a risca a id´eia original do algoritmo e procurando n˜ao
usar artif´ıcios que escapem do escopo dela. Come¸carei mostrando a vari´aveis usadas e o
m´etodo construtor.
package lamport;
// lse.neko imports:
import lse.neko.ActiveReceiver;
import lse.neko.MessageTypes;
import lse.neko.NekoMessage;
import lse.neko.NekoProcess;
import lse.neko.SenderInterface;
/**
* Lamport’s mutual exclusion algorithm.
* See the paper
* <blockquote>Lam78 <br>
* L.~Lamport. <br>
* Time, clocks, and the ordering of events in a distributed system. <br>
* Commun. ACM, 21(7):558--565, July 1978.</blockquote>
* for details of the algorithm.
*/
public class LamportME
extends ActiveReceiver
implements MEAlgorithm
{
// message types used by this algorithm, also used as states
private static final int req = 9032;
private static final int ack = 9033;
private static final int rel = 9034;
private static final int s = 9042;
private static final int r = 9043;
// registering the message types and associating names with the types.
static
{
MessageTypes.instance().register(req, "req");
MessageTypes.instance().register(ack, "ack");
MessageTypes.instance().register(rel, "rel");
MessageTypes.instance().register(s, "s");
MessageTypes.instance().register(r, "r");
}
private SenderInterface sender;
10
11. public void setSender(SenderInterface sender)
{
this.sender = sender;
}
/* objeto respons´avel pelo logging. */
/* Somente o processo n-1 ir´a tratar do logging, portanto somente ele usar´a este objeto */
MyLogger logger;
//algorithm variables
/* the id of this process */
private int me;
/* the number of processes */
private int n;
/* list of addresses that includes all processes but this one */
private int[] allButMe;
/* internal Lamport’s scalar clock */
int osn;
/* array of requests */
private NekoMessage[] q;
public LamportME(NekoProcess process) {
super(process, "LamportME-p" + process.getID());
n = process.getN();
me = process.getID();
allButMe = new int[n - 1];
for (int i = 0; i < n - 1; i++) {
allButMe[i] = (i < me) ? i : i + 1;
}
q = new NekoMessage[n];
osn = 0;
logger = new MyLogger(n);
}
Como dito anteriormente, esta classe estende ActiveReceiver e implementa a interface
MEAlgorithm, mostrada primeiro. Os tipos de menagens usados na execu¸c˜ao do algoritmo
s˜ao expostos no come¸co da classe: s˜ao associados n´umeros inteiros com as strings que
nomeiam os tipos da mensagens, e depois esses tipos s˜ao “registrados” no Neko com o uso
do m´etodo register da classe MessageTypes do Neko. Tudo que este m´etodo faz ´e associar
o nome do tipo da mensagem com o inteiro que a representar´a, e para isso usa um objeto
do tipo HashMap.
Ap´os isso s˜ao listadas as vari´aveis. Sender, como sabemos, ser´a o objeto que simular´a a
rede e gerenciar´a o envio de mensagens, e ´e inicializado usando o m´etodo setSender pela
classe de inicializa¸c˜ao, como mostrado anteriormente. Os inteiro me e n guardam o PID
do processo e o n´umero de processos no ambiente de execu¸c˜ao atual, respectivamente. O
vetor de inteiros allButMe serve para guardar o PID de todos os processos menos o pr´oprio
11
12. PID, e ele ser´a fundamental quando quisermos enviar mensagens em broadcast. O inteiro
osn guardar´a o rel´ogio l´ogico de Lamport do processo atual, e o vetor de NekoMessages q
guardar´a as mensagens que chegarem de outros processos, usando uma l´ogica pr´opria do
algoritmo que ser´a mostrada.
O construtor chama o m´etodo super para criar a thread de execu¸c˜ao e nome´a-la.
Tamb´em inicializa as vari´aveis me e n, os vetores allButMe e q, e o rel´ogio l´ogico osn ´e
setado inicialmente em zero, para mostrar que a execu¸c˜ao ainda n˜ao come¸cou. Cria tamb´em
o objeto respons´avel pelo logging da execu¸c˜ao. Somente o processo n-1 ´e respons´avel pelo
logging, portanto s´o ele usar´a este objeto.
public void run() {
if(me == (n-1)) {
while(true) {
NekoMessage m = receive();
logger.doLogging(m);
}
} else {
while(true) {
NekoMessage m = receive();
switch(m.getType())
{
case req:
requestMessageHandling(m);
break;
case ack:
ackMessageHandling(m);
break;
case rel:
releaseMessageHandling(m);
break;
default:
throw new RuntimeException("Unknown message received");
}
} // while(true)
}//method
Aqui est´a o m´etodo run que deve ser executado pela thread que controla o algoritmo. Se
o processo em quest˜ao n˜ao ´e o n-1, respons´avel pelo logging, o que ele faz ´e ficar num loop
infinito esperando mensagens e escolhendo como tratar elas, com base no seu tipo. Como
explicado antes, receive ´e um m´etodo da classe ActiveReceiver que retira mensagens da fila
de mensagens e entrega-as `a classe que a chamou. As mensagens s˜ao objetos NekoMessage,
e um dos campos que as definem ´e o seu tipo (type), que ´e obtido pelo m´etodo p´ublico
getType. Esses tipos de mensagens s˜ao os registrados anteriormente e associados a inteiros,
12
13. portanto este m´etodo retorna um inteiro. Vemos que, para cada tipo de mensagem, um
m´eodo foi escrito especialmente para tratar dela. Esses m´etodos ser˜ao mostrados abaixo.
/**
* M´etodo que gerencia mensagens do tipo "req"
* @param m: a mensagem do tipo "req" recebida
*/
private void requestMessageHandling(NekoMessage m) {
// obtem o valor do rel´ogio l´ogico enviado na mensagem
int k = ((Integer)m.getContent()).intValue();
// atualiza o pr´oprio rel´ogio l´ogico
update(k);
// coloca a mensagem no vetor de mensagens
int j = m.getSource();
q[j] = m;
// envia um "ack" de volta ao remetente, carregando o valor do pr´oprio rel´ogio
NekoMessage Ack = new NekoMessage(me, new int[] {j}, getId(), new Integer(osn), ack);
sender.send(Ack);
this.LogMessage(m, osn, r);
this.LogMessage(Ack, osn, s);
}
O tratamento de uma mensagem do tipo “req”, ou request ´e feito neste m´etodo. Primeiro
o rel´ogio l´ogico pr´oprio ´e atualizado com base no rel´ogio l´ogico recebido na mensagem envi-
ado de outro processo. Essa atualiza¸c˜ao ´e feita no m´etodo update. Ap´os isso, a mensagem
´e colocada na fila q na posi¸c˜ao destinada a mensagens recebidas pelo processo remetente
dela. Por fim, uma mensagem de resposta ack ´e enviada em unicast de volta ao processo
remetente, levando consigo o valor do rel´ogio l´ogico do processo atual.
O m´etodo send do objeto sender tem como ´unico argumento a mensagem a ser enviada.
Essa mensagem, encapsulada num objeto do tipo NekoMessage, ´e constru´ıda passando-se ao
m´etodo construtor como argumentos o PID do processo remetente, um vetor representando
os v´arios processos destinat´arios dela (neste caso o vetor s´o contem o remetente da mensagem
“req” recebida), um identificador do protocolo de destino (basta usar o m´etodo getId), o
conte´udo a ser transmitido (neste caso o valor do pr´oprio rel´ogio l´ogico, mas pode ser
qualquer objeto Java) e o tipo da mensagem, nesta ordem. send enviar´a a mensagem sem
que o usu´ario precise se preocupar com mais detalhes.
/**
* M´etodo que trata mensagens "rel"
* @param m: a mensagem do tipo "rel" recebida
*/
private void releaseMessageHandling(NekoMessage m) {
int k = ((Integer)m.getContent()).intValue(); // obtem o valor do rel´ogio l´ogico enviado na mensagem
update(k); // atualiza o pr´oprio rel´ogio l´ogico
int j = m.getSource();
13
14. q[j] = m;
this.LogMessage(m, osn, r);
}
Este ´e o m´etodo que trata mensagens do tipo “rel”, ou release. S˜ao feitas duas coisas: o
rel´ogio l´ogico pr´oprio ´e atualizado (ele sempre ´e atualiado quando uma mensagem ´e recebido,
como o algoritmo pede para ser feito) e a mensagem ´e colocada no vetor de mensagens, na
posi¸c˜ao destinada a mensagens do remetente dela.
/**
* Method that handles ack messages.
* It also counts the number of acks received since a request was sent.
* @param m: the message received
*/
private void ackMessageHandling(NekoMessage m) {
int k = ((Integer)m.getContent()).intValue(); // obtem o valor do rel´ogio l´ogico enviado na mensagem
update(k); // atualiza o pr´oprio rel´ogio l´ogico
int j = m.getSource();
if(q[j] != null && q[j].getType() != req)
q[j] = m;
this.LogMessage(m, osn, r);
}
Por fim, mensagens do tipo “ack” s˜ao tratadas por este m´etodo. Como nas mensagens do
tipo release, nenhuma resposta precisa ser enviada de volta ao remetente. Portanto, apenas
a atualiza¸c˜ao do rel´ogio l´ogico pr´oprio e o coloca¸c˜ao da mensagem no vetor de mensagens
´e feito. Por´em, essa coloca¸c˜ao do “ack” no vetor deve ser feita com um cuidado extra:
o “ack” n˜ao pode sobrescrever request que por acaso tenham sido enviados pelo processo
remetente deste “ack” anteriormente; somente releases podem fazˆe-lo. Caso contr´ario, o
processo atual poderia julgar que a prioridade para entrar na ´area cr´ıtica pudesse ser sua,
quando na verdade era do processo que teve sua mensagem de request apagada pelo “ack”.
Os dois processos entrariam na r.c. e a exclus˜ao m´utua n˜ao aconteceria. Portanto, esse
cuidado ´e tomado no teste do if, antes de atribuir q[j] a m.
public void enterCriticalSection() {
// multicast de uma mensagem do tipo ’req’ requisitando a entrada na r.c.
NekoMessage Req = new NekoMessage(me, allButMe, getId(), new Integer(osn), req);
sender.send(Req);
this.LogMessage(Req, osn, s);
// adiciona pr´opria requisi¸c~ao `a queue de mensagens e atualiza rel´ogio l´ogico
q[me] = Req; osn = osn + 1;
while(!testPriority()) {
try {
14
15. sleep(500);
} catch (InterruptedException e) {
System.out.println("Erro ao testar prioridade da thread.");
}
}
}
Este ´e m´etodo que coloca o algoritmo em funcionamento. ´E a implementa¸c˜ao do
enterCriticalSection presente na interface MEAlgorithm e, como sabemos, ´e o que deve
ser chamado quando a aplica¸c˜ao deseja entrar na regi˜ao cr´ıtica. Como a defini¸c˜ao do al-
goritmo pede, o que ´e feito ´e o seguinte: ´e feito um broadcast de uma mensagem “req”,
carregando o pr´oprio PID e o pr´oprio valor do rel´ogio l´ogico do processo atual antes do envio
da mensagem. Essa mensagem “req” tamb´em ´e guardada no pr´oprio vetor de mensagens,
na posi¸c˜ao destinada `as pr´oprias mensagens, e o rel´ogio l´ogico ´e atualizado. Entao, um loop
de teste fica rodando em ciclos de 500ms, testando se o processo atual tem a prioridade
para entrar na regi˜ao cr´ıtica. Quando esta prioridade ´e ganha, o loop termina, e o m´etodo
retorna. A aplica¸c˜ao continua sua execu¸c˜ao, agora com o processo atual utilizando-se da
regi˜ao cr´ıtica.
public void exitCriticalSection() {
// multicast de release
NekoMessage Rel = new NekoMessage(me, allButMe, getId(), new Integer(osn), rel);
sender.send(Rel);
this.LogMessage(Req, osn, s);
q[me] = Rel;
osn = osn + 1;
}
Quando a aplica¸c˜ao termina de usar a regi˜ao cr´ıtica, o m´etodo exitCriticalSection,
tamb´em presente na interface MEAlgorithm, ´e executado. O que ele faz ´e enviar em broad-
cast uma mensagem de release, “rel”, mostrando que terminou de usar sua prioridade e que
outro processo requisitante pode fazer uso da regi˜ao. Essa mensagem de release ´e colocada
no vetor de mensagens, na posi¸c˜ao destinada `as pr´oprias mensagens, e o rel´ogio l´ogico ´e
incrementado de uma unidade de tempo.
private void update(int k)
{
if(osn < k) osn = k;
osn = osn + 1;
}
Este m´etodo simples trata da atualiza¸c˜ao do rel´ogio l´ogico como deve ser feita na especi-
fica¸c˜ao do algoritmo de exclus˜ao m´utua de Lamport. Um inteiro k ´e recebido; se este k for
maior que o rel´ogio l´ogico atual, osn ´e atualizado com esse valor (acontece no caso que uma
mensagem recebida tinha um rel´ogio l´ogico maior que o do processo atual, significando que
15
16. ele estava atrasado em rela¸c˜ao ao processo remetente). Para terminar, osn ´e aumentado em
mais uma unidade.
public boolean testPriority() {
int myReqClock = ((Integer)q[me].getContent()).intValue();
for(int i = 0; i < n; i++) {
if(q[i] == null) return false;
if(q[i].getType() == req) {
int otherReqClock = ((Integer)q[i].getContent()).intValue();
if((otherReqClock < myReqClock)
|| (otherReqClock == myReqClock && i < me)) {
System.out.println(me + ": Processo " + i + " tem prioridade para entrar na r.c.!"
+ " O rel´ogio da minha req ´e " + myReqClock
+ " e o da dele ´e " + otherReqClock + ".");
return false;
}
}
}
osn = osn + 1;
return true;
}
} // class
Para terminar a descri¸c˜ao desta classe, o ´ultimo m´etodo ´e o que controla o processo
da exclus˜ao m´utua, e portanto ´e o mais importante. O teste para saber se o processo
em quest˜ao vai ganhar ou n˜ao a prioridade de entrada na ´area cr´ıtica ´e feito da seguinte
maneira, como especificado na defini¸c˜ao do algoritmo: o rel´ogio da mensagem de request do
pr´oprio processo presente na fila de mensagens ´e comparado com todas as outras mensagens
de request de outros processos presentes na fila. Se nenhuma delas tiver um rel´ogio de valor
menor que o da “req” pr´opria, ou tiver um valor igual, por´em o PID do outro processo for
maior que o PID do processo que est´a testando a prioridade, ent˜ao esse processo ganha a
prioridade e pode entrar na regi˜ao cr´ıtica. Caso contr´ario, ele n˜ao ganha a prioridade, e o
teste ser´a executado novamente no loop mostrado no m´etodo enterCriticalSection, at´e
que ele ganhe a prioridade e possa usufruir da ´area cr´ıtica. Dessa forma, ´e assegurado que
somente um processo por vez tem acesso a essa ´area, e a exclus˜ao m´utua funciona durante
a execu¸c˜ao da aplica¸c˜ao.
Quando o processo entra na ´area cr´ıtica, o rel´ogio dele aumenta em uma unidade, por
isto ser tratado como um evento na execu¸c˜ao. Isso tamb´em facilita um pouco a visualiza¸c˜ao
das mensagens de release no gr´afico gerado pelo logView, mostrado mais `a frente.
16
17. 3.5 O Arquivo de Configura¸c˜ao: distributed.config
O arquivo de configura¸c˜ao ´e um arquivo de texto com extens˜ao .config, passado como
argumento de linha de comando quando a execu¸c˜ao ´e iniciada, como ser´a mostrada na
parte de execu¸c˜ao. Ele ´e usado para se passar informa¸c˜oes ao Neko durante a inicializa¸c˜ao
da aplica¸c˜ao e que podem ser usadas durante toda ela. Portanto, pode ser uma ferramenta
muito ´util na implementa¸c˜ao de um algoritmo ou aplica¸c˜ao no Neko.
simulation = false
process.num = 4
slave = lsd96, lsd97, lsd98
process.initializer = lamport.MEInitializer
network = lse.neko.networks.comm.TCPNetwork
log = home/usu´ario/Desktop/log.txt
Esse come¸co define se a execu¸c˜ao ser´a uma simula¸c˜ao em m´aquina ´unica ou uma execu¸c˜ao
distribu´ıda entre v´arios computadores, na palavra-chave ’simulation’. Aqui foi feita uma
execu¸c˜ao distribu´ıda real. Depois, define-se o n´umero de processos em ’process.num’; neste
caso s˜ao 4 processos, rodando em 4 m´aquinas diferentes, cada um em uma m´aquina. O
endere¸co das m´aquinas que ser˜ao tratadas como slaves ´e passado na palavra-chave ’slave’.
Esses slaves, na verdade, s˜ao apenas as m´aquinas que ficar˜ao esperando a execu¸c˜ao
come¸car, aguardando que uma das m´aquinas, que det´em este arquivo de configura¸c˜ao, se
conecte a elas, envie o arquivo de configura¸c˜ao e dˆe o sinal para o in´ıcio da execu¸c˜ao. Quando
a execu¸c˜ao come¸ca, n˜ao h´a mais nenhuma distin¸c˜ao entre os n´os: n˜ao h´a mais ’master’ ou
’slave’, e todos rodam o algoritmo de forma igualit´aria.
Em ’process.initializer’ ´e passado o nome completo da classe que trata da inicializa¸c˜ao
da execu¸c˜ao; n´os sabemos que nesta aplica¸c˜ao esta classe ´e a MEInitializer, do pacote
’lamport’.
Por ´ultimo ´e passado que tipo de rede ser´a simulada com base numa classe do Neko
que simula esta rede. Neste caso, uma rede TCP ´e usada, por meio da classe do Neko
lse.neko.networks.comm.TCPNetwork. Outras redes est˜ao dispon´ıveis para serem usadas.
Basta ver na pasta do Neko quais s˜ao elas.
application = lamport.Application
algorithm = lamport.LamportME
#algorithm = mutualexclusion.RicartAgrawalaME
#algorithm = mutualexclusion.SinghalME
Aqui ´e importante. Anteriormente foi mencionada a capacidade do Neko de pegar o
nome das classes que implementar˜ao a pilha de protocolos de cada processo em tempo de
execu¸c˜ao, atrav´es do arquivo de configura¸c˜ao aqui exposto, e para isso usar a propriedade de
Reflection do Java na classe de inicializa¸c˜ao MEInitializer. Aqui est´a a parte em que isto
´e usado. Usando a palavras-chave application e algorithm, podemos dizer quais s˜ao as classes
que funcionar˜ao como a camada de aplica¸c˜ao e a camada do algoritmo do programa. Para
17
18. acessar estas informa¸c˜oes, o Neko usa um objeto do tipo Configurations, que guarda todas
as informa¸c˜oes expostas no arquivo de configura¸c˜ao. Estas informa¸c˜oes podem ser acessadas
durante a execu¸c˜ao atrav´es deste objeto. Examine a classe MEInitializer para ver como
isso ´e feito e perceber como ´e simples. O m´etodo getString da classe Configurations
retorna uma string associada `a chave que ´e passada a ela como argumento. Por exemplo,
em MEInitializer, para se descobrir o nome da classe que implementar´a o algoritmo, que
aqui se chama lamport.LamportME, ´e passado ao getString a palavra-chave algorithm.
Como pode-se ver, nestas linhas do arquivo de configura¸c˜ao a palavra-chave algorithm ´e
associada com a string lamport.LamportME, que ´e exatamente o nome da classe do algoritmo
de exclus˜ao m´utua que ser´a usado. Portanto, sabendo usar isso e a Reflection do Java,
podemos fazer v´arias implementa¸c˜oes de aplica¸c˜oes, algoritmos, e passar parˆametros como
n´umeros e etc., no arquivo de configura¸c˜ao, para que depois sejam usados em tempo real
na execu¸c˜ao da nossa aplica¸c˜ao no Neko. E isso ´e bastante ´util quando o principal objetivo
de quem est´a usando o Neko ´e simplicidade no uso e rapidez na implementa¸c˜ao e teste de
algoritmos.
4 Execu¸c˜ao
Para come¸car a execu¸c˜ao distribu´ıda do algoritmo ´e necess´ario antes iniciar os n´os slaves.
Slave ´e um n´o que ficar´a escutando numa porta, passada como argumento na linha de co-
mando ou na padr˜ao 8632, se nada for passado. Ele espera receber de um n´o, ´unico entre
todos os processos chamado master, o arquivo de configura¸c˜ao e o sinal para a execu¸c˜ao
come¸car. Assim que recebe esse arquivo, ele monta a pilha de protocolos do processo corre-
spondente a ele (cada n´o roda um processo) e come¸ca a execu¸c˜ao dele. Como ´e mostrado na
Figura 2, deve ser chamada a classe java.lse.comm.Slave do Neko, com o comando java
lse.neko.comm.Slave no terminal para o slave ser iniciado e ficar escutando em alguma
porta. Se uma porta diferente da padr˜ao quiser ser passada, basta adicionar o n´umero dela
como argumento deste comando (java lse.neko.comm.Slave XXXX, com XXXX sendo o
n´umero da porta). Esse procedimento deve ser feito independentemente em cada um dos
n´os que forem come¸car a execu¸c˜ao como slaves; o n´o master executa um comando diferente.
Na Figura 3 ´e mostrado como ´e feito o in´ıcio da execu¸c˜ao atrav´es do n´o master. Usando-
se o comando neko junto com o caminho para o arquivo de configura¸c˜ao mostrado ante-
riormente passado como argumento, e ap´os todos os outros n´os terem sido iniciados como
slaves e estarem conectados entre si (usando ssh, de preferˆencia), a execu¸c˜ao ter´a in´ıcio. Na
Figura 3 o arquivo de configura¸c˜ao estava na mesma pasta em que foi chamado o comando,
portanto n˜ao foi necess´ario passar um caminho absoluto ou relativo at´e ele, apesar de isso
ainda ser poss´ıvel.
A Figura 4 mostra o momento na execu¸c˜ao em que todos os processos est˜ao tentando
conseguir a prioridade para a regi˜ao cr´ıtica, mas somente o processo 1 conseguiu. Isso se
deve a ele ter enviado o req antes do processo 0, e de ou ter enviado antes do outros processos
tamb´em ou ter enviado ao mesmo tempo, sendo que neste caso ele ganha a prioridade por
ter PID menor, da forma como o algoritmo de exclus˜ao m´utua de Lamport decide a garantia
de prioridade `a ´area cr´ıtica.
18
19. Figura 2: Configurando um n´o slave no Neko antes de come¸car a execu¸c˜ao
Figura 3: Come¸cando a execu¸c˜ao com o n´o master
19
20. Figura 4: Momento em que um processo consegue acesso `a regi˜ao cr´ıtica
Por fim, a Figura 5 mostra o momento na execu¸c˜ao em que um processo termina de
usar a regi˜ao cr´ıtica e manda em broadcast uma mensagem de release. Assim que os outros
processos recebem essa mensagem, removem o req do processo remetente que estava no
vetor de mensagens e testam novamente a prioridade. Um dos processos descobre que ele ´e
o pr´oximo a receber o acesso `a regi˜ao cr´ıtica e entra, enquanto os outros processos continuam
esperando.
5 As Classes Usadas Para Gerar o Log da Execu¸c˜ao
Foi mencionada a cria¸c˜ao de um arquivo de log durante a execu¸c˜ao do algoritmo. Essa
cria¸c˜ao do log ´e feita por um processo, que aqui foi escolhido como o processo n-1, que
fica esperando mensagens espec´ıficas de gera¸c˜ao de log enviadas pelos outros processos,
que est˜ao envolvidos na execu¸c˜ao do algoritmo. Essas mensagens espec´ıficas carregam as
mensagens que estes processos enviam ou recebem, junto com o rel´ogio l´ogico do processo
quando o evento do envio ou recebimento desta mensagem ocorreu. Isto ´e utilizado para
criar o log, que consiste de linhas que registram detalhes das mensagens. Esse arquivo de
log ´e usado na gera¸c˜ao de um gr´afico da execu¸c˜ao pelo logView, como ser´a mostrado na
pr´oxima se¸c˜ao.
5.1 A Classe Event
package lamport;
import java.io.Serializable;
20
21. Figura 5: Momento em que um processo libera a r.c. e outro entra
import lse.neko.NekoMessage;
public class Event
implements Serializable {
NekoMessage m;
int osn;
public Event(NekoMessage m, int osn) {
this.m = m;
this.osn = osn;
}
public NekoMessage getMessage() {
return m;
}
public int getOsn() {
return osn;
}
}
A classe Event serve para que as mensagens de log possam ser enviadas pelos processos
participantes da execu¸c˜ao com as mensagens que eles trocam entre si e o tempo l´ogico
que marca o momento em que eles enviam ou recebem estas mensagens. ´E como se as
mensagens rebidas ou enviadas fossem “empacotadas” numa outra mensagem com alguns
metadados necess´ario ao registro dessa mensagem no arquivo de log. Como estes envios ou
recebimentos de mensagens s˜ao chamados de eventos em um ambiente distribu´ıdo a classe
21
22. recebeu este nome.
´E necess´ario que ela implemente a interface do Java chamada Serializable, caso contr´ario
uma exce¸c˜ao ´e levantada durante a execu¸c˜ao em um ambiente distribu´ıdo. Esta interface
Serializable n˜ao apresenta nenhum m´etodo a ser implementado.
5.2 A Classe MyLogger
MyLogger ´e a classe que trata da cria¸c˜ao e gerenciamento do arquivo de log.
package lamport;
import java.io.BufferedWriter;
import java.io.FileWriter;
import lse.neko.MessageTypes;
import lse.neko.NekoMessage;
import lse.neko.NekoSystem;
import org.apache.java.util.Configurations;
public class MyLogger {
Configurations config;
int n;
boolean firstEntry;
public MyLogger(int n) {
config = NekoSystem.instance().getConfig();
this.n = n;
firstEntry = true;
}
O m´etodo construtor inicia as vari´aveis da classe. Um objeto Configurations ´e criado,
para que o arquivo de configura¸c˜ao da execu¸c˜ao do Neko seja utilizado. Uma entrada nele
guarda o diret´orio e nome do arquivo de log a ser criado. Outra vari´avel iniciada ´e a que
guarda o n´umero de processos na execu¸c˜ao atual. Por fim, uma vari´avel booleana diz se
estamos tratando da primeira entrada no arquivo de log, e por isso ele precisa ser criado do
zero, ou se apenas anexamos a pr´oxima entrada ap´os as outras j´a gravadas, quando ele j´a
foi criado e a execu¸c˜ao atual j´a est´a avan¸cada.
public void doLogging(NekoMessage logMsg) {
FileWriter fw;
config = NekoSystem.instance().getConfig();
String logPath = config.getString("log");
Event event = (Event)logMsg.getContent();
int osn = event.getOsn();
NekoMessage msg = event.getMessage();
22
23. int eventSource = logMsg.getSource();
int eventType = logMsg.getType();
String[] s = formatString(msg, eventSource, eventType, osn);
for(int i=0; i<s.length;i++) {
if(s[i] != null) {
try{
if(firstEntry) {
fw = new FileWriter(logPath, false);
firstEntry = false;
} else fw = new FileWriter(logPath, true);
BufferedWriter out = new BufferedWriter(fw);
out.write(s[i] + "n");
out.close();
} catch (Exception e) {
System.err.println("Error: " + e.getCause());
}
}
}
}
O m´etodo doLogging trata os eventos de envio e recebimento de mensagens que devem
ser registrados no arquivo de log.
private String[] formatString(NekoMessage m, int source, int type, int osn) {
String[] v = new String[n];
String time = String.valueOf(osn);
String eventType = MessageTypes.instance().getName(type);
int messageSource = m.getSource();
int[] messageDest = m.getDestinations();
String messageType = MessageTypes.instance().getName(m.getType());
String messageContent = String.valueOf(m.getContent());
if(eventType == "r") {
String f = time + " p" + source + " messages e " + eventType + " p" + messageSource +
" p" + source + " " + messageType + " " + messageContent;
v[0] = f;
}
else for(int i=0; i<messageDest.length; i++) {
String f = time + " p" + source + " messages e " + "s" + " p" + source +
" p" + messageDest[i] + " " + messageType + " " + messageContent;
v[i] = f;
}
return v;
}
23
24. }
E o m´etodo formatString cria as strings que representam cada evento e que ficar˜ao
registradas em cada linha no arquivo de log. O formato das strings pode ser conferido no
arquivo de log mostrado na pr´oxima se¸c˜ao.
6 Visualiza¸c˜ao de Execu¸c˜oes: o LogView
Uma execu¸c˜ao do algoritmo produz um arquivo de log, com o nome e diret´orio passados
no arquivo de configura¸c˜ao mostrado anteriormente, e que registra as mensagens enviadas
e recebidas. Esse registros contˆem detalhes como o processo que enviou, o que recebeu,
o tipo da mensagem, o conte´udo e etc.. Um arquivo de log produzido por uma execu¸c˜ao
distribu´ıda ´e mostrado abaixo. Cada linha mostra, na ordem: o tempo l´ogico em que um
processo enviou ou recebeu uma mensagem, qual processo foi esse, se o evento foi de envio
(“s”) ou recebimento (“r”) de mensagem , qual foi o remetente e o destinat´ario, o tipo de
mensagem e o conte´udo que ela carregou (no caso o conte´udo ´e o rel´ogio l´ogico do processo
no momento de envio da mensagem).
1 p0 messages e r p2 p0 req 0
1 p0 messages e s p0 p2 ack 1
1 p1 messages e r p2 p1 req 0
1 p1 messages e s p1 p2 ack 1
0 p2 messages e s p2 p0 req 0
0 p2 messages e s p2 p1 req 0
2 p2 messages e r p1 p2 ack 1
3 p2 messages e r p0 p2 ack 1
1 p0 messages e s p0 p1 req 1
1 p0 messages e s p0 p2 req 1
4 p2 messages e r p0 p2 req 1
2 p1 messages e r p0 p1 req 1
4 p2 messages e s p2 p0 ack 4
2 p1 messages e s p1 p0 ack 2
3 p0 messages e r p1 p0 ack 2
5 p0 messages e r p2 p0 ack 4
2 p1 messages e s p1 p0 req 2
2 p1 messages e s p1 p2 req 2
6 p0 messages e r p1 p0 req 2
5 p2 messages e r p1 p2 req 2
6 p0 messages e s p0 p1 ack 6
5 p2 messages e s p2 p1 ack 5
6 p1 messages e r p2 p1 ack 5
7 p1 messages e r p0 p1 ack 6
6 p2 messages e s p2 p0 rel 6
6 p2 messages e s p2 p1 rel 6
7 p0 messages e r p2 p0 rel 6
8 p1 messages e r p2 p1 rel 6
8 p0 messages e s p0 p1 rel 8
8 p0 messages e s p0 p2 rel 8
9 p2 messages e r p0 p2 rel 8
9 p1 messages e r p0 p1 rel 8
9 p2 messages e s p2 p0 req 9
9 p2 messages e s p2 p1 req 9
24
25. 11 p1 messages e r p2 p1 req 9
10 p0 messages e r p2 p0 req 9
11 p1 messages e s p1 p2 ack 11
10 p0 messages e s p0 p2 ack 10
12 p2 messages e r p1 p2 ack 11
13 p2 messages e r p0 p2 ack 10
11 p1 messages e s p1 p0 rel 11
11 p1 messages e s p1 p2 rel 11
14 p2 messages e r p1 p2 rel 11
12 p0 messages e r p1 p0 rel 11
12 p0 messages e s p0 p1 req 12
12 p0 messages e s p0 p2 req 12
16 p2 messages e r p0 p2 req 12
13 p1 messages e r p0 p1 req 12
16 p2 messages e s p2 p0 ack 16
13 p1 messages e s p1 p0 ack 13
14 p0 messages e r p1 p0 ack 13
17 p0 messages e r p2 p0 ack 16
16 p2 messages e s p2 p0 rel 16
16 p2 messages e s p2 p1 rel 16
17 p1 messages e r p2 p1 rel 16
18 p0 messages e r p2 p0 rel 16
17 p1 messages e s p1 p0 req 17
17 p1 messages e s p1 p2 req 17
20 p0 messages e r p1 p0 req 17
18 p2 messages e r p1 p2 req 17
18 p2 messages e s p2 p1 ack 18
20 p0 messages e s p0 p1 ack 20
21 p1 messages e r p0 p1 ack 20
22 p1 messages e r p2 p1 ack 18
20 p0 messages e s p0 p1 rel 20
20 p0 messages e s p0 p2 rel 20
23 p1 messages e r p0 p1 rel 20
21 p2 messages e r p0 p2 rel 20
24 p1 messages e s p1 p0 rel 24
24 p1 messages e s p1 p2 rel 24
25 p0 messages e r p1 p0 rel 24
25 p2 messages e r p1 p2 rel 24
Com a ajuda de um programa chamado LogView podemos gerar um gr´afico visualizando
o fluxo dessas mensagens e assim tendo uma id´eia de como ocorre o funcionamento de um
algoritmo implementado no Neko. O LogView foi escrito tamb´em em Java e gera gr´aficos
a partir de logs do Neko com o formato de mensagens mostrado acima, e um arquivo XML
de configura¸c˜ao, em que v´arios detalhes podem ser modificados para gerar gr´aficos mais ao
gosto do usu´ario. O que foi usado aqui neste documento foi ligeiramente modificado por
mim em rela¸c˜ao ao original, que vem junto com o pr´oprio Neko. As modifica¸c˜oes incluem
menos dependˆencia deste arquivo de configura¸c˜ao, sendo necess´ario apenas que o arquivo
de log seja listado nele, e um menu de op¸c˜oes que possibilita mostrar tags sobre as setas
que mostrem conte´udo da mensagem, tipo, tempos de envio e recebimento, entre outras
modifica¸c˜oes. O arquivo de configura¸c˜ao usado nas visualiza¸c˜oes mostradas a seguir ´e este
abaixo:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logView SYSTEM "logView.dtd">
25
26. <logView>
<display>
<timeAxis xSize="200"/>
<!--timeAxis xSize="100"/>
<processAxis ySize="100"/>
<window xSize="1000" ySize="600"/>
<messages type="REQUEST" color="red"/>
<messages type="ACK" color="blue"/>
<messages type="SCORE" color="yellow"/>
<messages type="RELEASE" color="green"/>
<label halign="left" valign="top" distance="30" percent="0.7"/-->
</display>
<file>
<log filename="/home/alvaro/Desktop/log.txt"/>
</file>
</logView>
Pode se ver que esse arquivo ´e bem pequeno. O cabe¸calho inicial indica a vers˜ao do XML,
a codifica¸c˜ao e a segunda linha indica que este arquivo deve seguir o padr˜ao de um outro
arquivo DTD (Documente Type Definition , que diz como ele deve ser entendido pelo parser
e escrito pelo usu´ario. Este arquivo DTD ´e inclu´ıdo junto com o LogView. A segunda parte
indica detalhes do gr´afico, como espa¸camento nos eixos do tempo e de processos, intervalos
a serem representados, com que cor deve ser mostrado cada tipo de mensagem, entre outros.
Pode-se ver que a parte entre <!-- e --> est´a comentada e n˜ao foi portanto considerada
como configura¸c˜ao v´alida; essa parte ´e mostrada para exemplificar que tipo de op¸c˜oes est˜ao
dispon´ıveis neste arquivo de configura¸c˜ao para personalizar a visualiza¸c˜ao. A ´ultima parte
indica o arquivo de log a ser lido. A princ´ıpio a ´unica parte estritamente necess´aria que este
arquivo deve conter ´e o cabe¸calho e a indica¸c˜ao do arquivo de log; o resto n˜ao ´e necess´ario
e o logView consegue gerar diagramas sem estas outras configura¸c˜oes.
A Figura 6 mostra o come¸co da execu¸c˜ao. Setas azuis representam mensagens de request,
vermelhas de ack e cinzas de release. Os n´umeros sobre as setas s˜ao o conte´udo da mensagem,
que neste caso ´e o rel´ogio l´ogico do processo no momento de envio da mensagem. Nesta
figura visualiza-se as mensagens de request enviadas pelos processos 2, 1 e 0, nesta ordem,
e as mensagens de ack enviadas por outros processos quando estas s˜ao recebidas. As setas
come¸cam no tempo em que s˜ao enviadas pelo processo remetente e terminam no tempo em
que foram recebidas pelo processo destinat´ario.
A Figura 7 mostra o momento em que o processo 2 envia um release em broadcast.
Como ele tinha enviado o request antes de todos os outros processos a prioridade de entrada
na r.c. foi dada a ele primeiro. Ap´os fazer uso dela, ele faz esse broadcast aviasando todos
os outros processos de que a prioridade n˜ao ´e mais dele e que outro processo pode usar a
´area cr´ıtica. Sabendo disso, o processo 0 ganha a prioridade, por ter enviado o “req” antes
do processo 1. E, da mesma forma, ap´os terminar de usar a r.c. ele tamb´em faz broadcast
de “rel”, e as setas cinzas saindo dele e indo para os outros processos mostram isso. ´E
mostrado tamb´em o processo 2 tentando entrar na ´area cr´ıtica novamente, mandando um
broadcast de request, e as setas azuis saindo dele no lado direito da imagem ilustram isso.
Por ´ultimo, a Figura 8 mostra uma parte da execu¸c˜ao em que o Processo 0 termina de
usar a regi˜ao cr´ıtica, faz um broadcast de release e ent˜ao o Processo 1 ganha a prioridade.
26
27. Figura 6: O come¸co da execu¸c˜ao. Todos os processos tentam entrar na ´area cr´ıtica.
Figura 7: Processo 2 sai da r.c. e Processo 0 entra. Processo 2 tenta novamente entrar na
r.c., fazendo um broadcast de request.
27
28. Figura 8: Processo 0 deixa a r.c., e o Processo 1 entra. Ap´os o uso da r.c. ambos fazem
broadcast de release.
Ap´os tamb´em terminar de fazer uso desta prioridade ele tamb´em avisa aos outros processos
de que a r.c. est´a sem uso no momento. Importante deixar claro que ao entrar na regi˜ao
cr´ıtica um processo aumenta seu rel´ogio l´ogico em uma unidade, portanto o Processo 1
recebeu o “rel” do Processo 0 no tempo 23 e, ao entrar na ´area cr´ıtica, aumentou seu
rel´ogio l´ogico em 1 unidade, e por isso ele envia o seu broadcast de release no tempo 24.
7 Conclus˜ao
Neste documento, foi apresentado o Neko, uma plataforma Java simples de comunica¸c˜ao
que provˆe suporte `a simula¸c˜ao e prototipagem de algoritmos distribu´ıdos. Atrav´es dele, foi
implementado o algoritmo de exclus˜ao m´utua de Lamport, e dessa forma foi mostrado como
´e simples e pr´atico o uso do Neko para este fim. Na classe que implementava o algoritmo
propriamente, viu-se que n˜ao foi necess´ario muito mais c´odigo al´em do que descrevia a
pr´opria execu¸c˜ao dele. A troca de mensagens ´e feita com m´etodos j´a implementados em
classes do Neko, que tamb´em controla a camada de redes e a troca de mensagens entre as
camadas da pilhas que representam os processos.
Por fim, a execu¸c˜ao desta implementa¸c˜ao gerou um arquivo de log que tornou poss´ıvel a
gera¸c˜ao de um gr´afico, representando a execu¸c˜ao do algoritmo e a troca de mensagens entre
os processos. Cada mensagem foi representada por uma seta entre os processos remetente
e destinat´ario, mostrando tamb´em uma etiqueta com o conte´udo dessas mensagens. Os
tempos de chegada e sa´ıda destas setas eram os pr´oprios tempos l´ogicos em cada processo,
28
29. tornando poss´ıvel a visualiza¸c˜ao dos eventos na execu¸c˜ao segundo uma ordena¸c˜ao do tipo
happened-before entre todas a mensagens. Sendo assim, a visualiza¸c˜ao gerada se torna um
instrumento muito ´util para se enxergar como um algoritmo distribu´ıdo funciona.
O Neko e o LogView podem ser encontrados nas p´aginas listadas na bibliografia.
Referˆencias
[1] L Lamport. “Time, Clocks, and the Ordering of Events in a Distributed System”. In:
Communications of the ACM 21 (1978), pp. 558–565.
[2] J. Muller, M. Galanthay e P. Urb´an. Rapport de Projet de Semestre Visualisation des
Fichiers de Traces de Neko : LogView. 2002. url: http://ddsg.jaist.ac.jp/neko/
logView/rapport/rapport.pdf.
[3] P. ´Urban, X. D´efago e A. Schiper. “Neko: A Single Environment to Simulate and Pro-
totype Distributed Algotithms”. In: Journal of Information Science and Engineering
18 (2002), pp. 981–997. url: http://ddsg.jaist.ac.jp/pub/UDS02.pdf.
29