Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Natal 2004
Relatrio Submetido Universidade Federal do Rio Grande do Norte como parte dos requisitos para a obteno do grau de Bacharel em Cincia da Computao com nfase em Computao Cientca e especializao em Sistemas em Tempo Real para Otimizao e Automao no Setor Petrleo & Gs
"Todos estes que a esto Atravancando o meu caminho, Eles passaro. . . Eu pasarinho" Mrio Quintana
ii
Agradecimentos
Ao povo l de casa, o que inclui meu pai, minha me, minhas duas irms e at mesmo a gata. Agradeo a Deus, apesar da pouca f. Aos meus amigos fora do curso, aos meus amigos do curso que me ajudaram muito a suportar este tempo todo dentro da universidade e me ensinaram muito. A todos os meus professores, de agora e de antes, que foram fundamentais no meu aprendizado.
iii
Resumo da Relatrio apresentado UFRN como parte dos requisitos necessrios para obteno do grau de Bacharel em Cincia da Computao.
Maro/2004
Orientador: David Boris Paul Dharbe rea de Concentrao: Mtodos Formais Palavras-chave: Mtodos Formais, NuSMV, Engenharia de Software
Atualmente se encontra em desenvolvimento na UFRN o projeto Automao de Poos, que visa aperfeioar as tcnicas de automao de poos que utilizam mtodos de elevao. Associado a este projeto, existe um modelo de comunicao que deve funcionar corretamente para o bom andamento do sistema. Uma proposta atual o uso de mtodos formais em componentes crticos de sistemas. Desta forma, o objetivo deste trabalho avaliar o uso da tcnica de especicao formal conhecida como Symbolic Model Checking no contexto do projeto Automao de Poos.
iv
Report presented to UFRN as a partial fulllment of the requirements for the degree of Bachelor in Computer Science.
Formal Specication and Checking of the Model Communication in the Project Automao de Poos
March/2004
Advisor: David Boris Paul Dharbe Area of Concentration: Formal Methods Key words: Formal Methods, NuSMV, Software Engineering
Automao de Poos is a project under development at UFRN that intends to improve oil well automation techniques in wells using elevation methods. Associated with this project, there is a communication model that must be correct. A current approach is to use formal methods in system critical components. So, our work intends to evaluate the benets of one formal method technique called Symbolic Model Checking in the context of the Automao de Poos project.
Sumrio
Lista de Figuras . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Lista de Tabelas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 2 Introduo Protocolo de Comunicao Modbus 2.1 2.2 2.3 2.4 2.5 2.6 2.7 Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Comunicao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Modos de Transmisso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Quadro Framing da Mensagem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Campo Endereo do Escravo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Campo Funo Modbus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Campo Dados para o Escravo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.7.1 Comandos sem Erro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.7.2 2.8 2.9 Comandos com Erro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Campo Checksum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Funes Modbus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ix x 1 4 4 4 5 6 6 6 6 6 7 7 7 7 9 9 10 10 11 11 12 13 14 14 15 17 18 18
2.10 Temporizao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 Protocolo de Comunicao Inter-redes 3.1 3.2 3.3 3.4 Interface de Comunicao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Identicao de Requisies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Funes PCI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . O Software de Superviso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4.1 3.4.2 4 Funcionamento dos Clientes . . . . . . . . . . . . . . . . . . . . . . . . . . Funcionamento do Servidor . . . . . . . . . . . . . . . . . . . . . . . . . .
Modelagem da Comunicao Mestre/Escravo via Modbus Utilizando NuSMV 5.1 5.2 Mdulo main . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mdulo message . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vi
Mdulo channel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mdulo application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mdulo master . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mdulo slave . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Propriedades do Modelo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18 19 19 21 21 23 23 23 25 25 26 26 27 27 28 28 28 28 28 30 30 30 33 34 38
Modelagem da Comunicao Cliente Servidor Utilizando o PCI 6.1 Mdulo main . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 Mdulo message . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mdulo channel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mdulo buffer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mdulo application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mdulo server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mdulo serverReader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mdulo serverLocalProcess . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mdulo serverRemoteProcess . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.10 Mdulo serverWriter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.11 Mdulo serverInternalProcess . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.12 Mdulo client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.13 Mdulo clientSender . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.14 Mdulo clientReceiver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.15 Mdulo clientVerier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.16 Propriedades do Modelo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Concluso
vii
Lista de Figuras
2.1 3.1 3.2 3.3 4.1 5.1 5.2 5.3 5.4 5.5 5.6 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 Exemplo de um Quadro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exemplo de um Quadro de Requisio . . . . . . . . . . . . . . . . . . . . . . . . . Exemplo de um Quadro de Resposta . . . . . . . . . . . . . . . . . . . . . . . . . . Estados das Requisies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exemplo de Programa na Linguagem NuSMV . . . . . . . . . . . . . . . . . . . . . Modelo Esquemtico da Comunicao do Projeto Automao de Poos . . . . . . . Representao Hierrquica dos Mdulos do Sistema . . . . . . . . . . . . . . . . . . Implementao do Mdulo main . . . . . . . . . . . . . . . . . . . . . . . . . . . . Implementao do Mdulo message . . . . . . . . . . . . . . . . . . . . . . . . . . Implementao do Mdulo channel . . . . . . . . . . . . . . . . . . . . . . . . . . Implementao do Mdulo application . . . . . . . . . . . . . . . . . . . . . . . . . Representao Hierrquica dos Mdulos do Sistema . . . . . . . . . . . . . . . . . . Representao Hierrquica do Mdulo server . . . . . . . . . . . . . . . . . . . . . Representao Hierrquica do Mdulo client . . . . . . . . . . . . . . . . . . . . . . Implementao do Mdulo main . . . . . . . . . . . . . . . . . . . . . . . . . . . . Implementao do Mdulo message . . . . . . . . . . . . . . . . . . . . . . . . . . Implementao do Mdulo channel . . . . . . . . . . . . . . . . . . . . . . . . . . Implementao do Mdulo buffer . . . . . . . . . . . . . . . . . . . . . . . . . . . . Implementao do Mdulo application . . . . . . . . . . . . . . . . . . . . . . . . . 6 10 10 11 13 17 18 18 19 19 20 24 24 24 24 25 25 26 26 27 29 30 31 35 36 37 39 40 41
6.9 Implementao do Mdulo server . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.10 Implementao do Mdulo serverWriter . . . . . . . . . . . . . . . . . . . . . . . . 6.11 Implementao do Mdulo client . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.12 Implementao do Mdulo clientVerier . . . . . . . . . . . . . . . . . . . . . . . . A.1 Implementao da Comunicao Mestre/Escravo . . . . . . . . . . . . . . . . . . . A.2 Implementao da Comunicao Mestre/Escravo . . . . . . . . . . . . . . . . . . . A.3 Implementao da Comunicao Mestre/Escravo . . . . . . . . . . . . . . . . . . . A.1 Implementao da Comunicao Cliente/Servidor . . . . . . . . . . . . . . . . . . . A.2 Implementao da Comunicao Cliente/Servidor . . . . . . . . . . . . . . . . . . . A.3 Implementao da Comunicao Cliente/Servidor . . . . . . . . . . . . . . . . . . .
viii
A.4 Implementao da Comunicao Cliente/Servidor . . . . . . . . . . . . . . . . . . . A.5 Implementao da Comunicao Cliente/Servidor . . . . . . . . . . . . . . . . . . . A.6 Implementao da Comunicao Cliente/Servidor . . . . . . . . . . . . . . . . . . . A.7 Implementao da Comunicao Cliente/Servidor . . . . . . . . . . . . . . . . . . . A.8 Implementao da Comunicao Cliente/Servidor . . . . . . . . . . . . . . . . . . . A.9 Implementao da Comunicao Cliente/Servidor . . . . . . . . . . . . . . . . . . . A.10 Implementao da Comunicao Cliente/Servidor . . . . . . . . . . . . . . . . . . . A.11 Implementao da Comunicao Cliente/Servidor . . . . . . . . . . . . . . . . . . . A.12 Implementao da Comunicao Cliente/Servidor . . . . . . . . . . . . . . . . . . .
42 43 44 45 46 47 48 49 50
ix
Lista de Tabelas
Captulo 1
Introduo
O Departamento de Engenharia de Computao e Automao da UFRN tem participado de vrios projetos ligados automao na rea de petrleo, dentro os quais encontra-se o projeto Automao de Poos, que possui como objetivo aperfeioar as tcnicas de automao de poos que utilizam mtodos de elevao, particularmente no que diz respeito ao monitoramento [Mai03]. A idia do projeto que um operador localizado em Natal possa vericar o que est acontecendo com um poo instalado em outro lugar, como a zona rural de Mossor por exemplo, podendo at parar ou partir o poo [Mai03]. Visto que nem todos os poos possuem o mesmo equipamento de monitoramento e estes equipamentos possuem diferentes interfaces, interessante utilizar um mediador, que possa oferecer uma camada uniforme de comunicao com os equipamentos atrelados a cada poo. Dessa forma o modelo de comunicao do projeto Automao de Poos pode ser dividido em duas partes: Na primeira parte, acontece uma comunicao no estilo cliente/servidor, onde o cliente , por
exemplo, a mquina de um operador do sistema, situada em Natal, que deseja saber algum dado sobre um poo que est localizado num campo na zona rural de Mossor, e o servidor seria o
computador que est supervisionando os vrios controladores daquele campo na zona rural de Mossor e que oferece uma camada uniforme de comunicao com os diferentes controladores. Na segunda parte, ocorre uma comunicao mestre/escravo, onde o mestre o computador que est supervisionando os poos, e que faz o papel de servidor na primeira parte da comunicao; e o escravo um equipamento controlador atrelado ao poo do qual desejamos saber alguma informao. O mestre ento traduz a requisio que recebeu do cliente na primeira parte da comunicao para que possa se comunicar adequadamente com o equipamento controlador em questo. Podemos associar a cada parte do modelo de comunicao um tipo de rede distinto, onde a primeira parte caracteriza-se como uma rede local de superviso e a segunda como uma rede de campo. Na rede de campo, onde ocorre a comunicao mestre/escravo, o protocolo de comunicao utilizado o Modbus, o qual bastante conhecido na indstria e ser melhor descrito mais adiante. J
Captulo 1. Introduo
na rede local de superviso, onde ocorre comunicao cliente/servidor e o servidor tem a funo de interconectar as duas redes, faremos uso do Protocolo de Comunicao Inter-redes (PCI), o qual oferece uma interface de comunicao capaz de integrar as duas redes e estabelece um padro que pode ser utilizado em qualquer rede de comunicao de sistemas supervisrios para processos fsicos industriais [dS04]. Este modelo de comunicao precisa funcionar corretamente para o bom andamento do sistema, visto que falhas no processo de comunicao podem comprometer o bom supervisionamento dos poos que esto localizados remotamente. Dessa forma, o processo de comunicao constitui-se de uma parte crtica da aplicao. Uma proposta que ganhou fora nos ltimos anos a aplicao de tcnicas de especicao e vericao formal na modelagem de sistemas crticos, podendo ser modelado o sistema como um todo ou apenas as partes consideradas mais crticas do sistema. Com o uso de tcnicas de especicao formal podemos modelar, com o auxlio de alguma notao matemtica, vrias propriedades importantes do sistema, e utilizando tcnicas de vericao formal podemos mostrar que estas propriedades vo ser respeitadas ao longo do tempo, evitando assim possveis falhas que poderiam passar despercebidas se usssesmos outras tcnicas de engenharia de software mais tradicionais. O presente trabalho pretende avaliar o potencial da tcnica de especicao formal conhecida como Simbolic Model Checking, tendo como caso de estudo o sistema de comunicao do projeto automao de poos. Iremos modelar formalmente o sistema em duas etapas: Na primeira etapa, ser feito um modelo da comunicao mestre/escravo; Na segunda etapa, iremos trabalhar no modelo cliente/servidor, tentando posteriormente realizar a integrao destes dois modelos. Com a integrao destes dois modelos, teremos ento uma especicao formal completa do nosso sistema. Os captulos seguintes deste texto encontram-se organizados da seguinte forma: O captulo 2 trata do protocolo de comunicao Modbus [Alf00, MOD02, MOD96], utilizado no projeto Automao de Poos. O captulo 3 aborda o protocolo de comunicao inter-redes, explicando melhor o seu funcionamento; O captulo 4 fala sobre NuSVM [ITC02, CCGR99], uma ferramenta de apoio especicao formal, que permite a vericao e a simulao de modelos formais. O captulo 5 apresenta uma modelagem da parte do modelo de comunicao onde ocorre a comunicao mestre escravo atravs do protocolo Modbus. O captulo 6 apresenta uma modelagem da parte do modelo de comunicao onde ocorre a comunicao cliente/servidor e utilizado o protocolo de comunicao inter-redes.
Captulo 1. Introduo
O captulo 7 apresenta algumas concluses e tambm faz uma anlise dos resultados obtidos com a modelagem formal do sistema.
Captulo 2
2.2 Comunicao
Na comunicao mestre/escravo, um equipamente assume o papel de mestre, enquanto os demais se comportam como escravos. Cabe ao mestre tomar a iniciativa do processo de comunicao, cando o escravo encarregado de responder s solicitaes enviadas pelo mestre. Quando se d a comunicao entre o mestre e o escravo, h duas situaes que podem ocorrer: O mestre deseja enviar/receber dados para/do escravo; O escravo deseja enviar/receber dados para/do mestre. Na primeira situao, o mestre, como tem a possibilidade de iniciar a comunicao, pode enviar quando desejar uma mensagem requisitando ao escravo a realizao de uma funo. O escravo, ao
receber a mensagem enviada pelo mestre, executa a funo e envia uma resposta ao mestre contendo o resultado da funo em questo. Este processo de comunicao chamado de Select. J no segundo caso, visto que o escravo no pode iniciar um processo de comunicao, ele deve esperar o mestre perguntar se ele deseja enviar/receber alguma mensagem, para s ento enviar a sua mensagem ao mestre. Este processo de comunicao recebe o nome de Pooling. No Modbus, o mestre pode enderear os escravos individualmente ou enderear todos os escravos da rede enviando mensagens em broadcast. Somente o escravo endereado retorna uma resposta a um pedido do mestre, sendo que mensagens enviadas em broadcast nunca so respondidas. No formato estabelecido pelo Modbus para as mensagens de pedido, so denidos: o endereo do escravo (ou cdigo em caso de acesso broadcast); a funo solicitada, com eventuais parmetros; o campo de checksum, para vericar a integridade da mensagem. De maneira similar, gerada a resposta do escravo correspondente funo solicitada pelo mestre, onde se dene: a conrmao da funo realizada; resultado da funo realizada; o campo de checksum, para vericar a integridade da mensagem. Se ocorrer um erro na comunicao, ou se o escravo no estiver apto a realizar a funo solicitada pelo mestre, ele monta uma mensagem especca, exception, justicando o seu no atendimento.
Incio de Quadro
Endereo do Escravo
Funo Modbus
Checksum
Fim de Quadro
exception, identicando o que ocasionou o erro e orientando o mestre na execuo do prximo comando.
2.10 Temporizao
Todo mestre congurado para esperar por intervalo de tempo pr-determinado antes de abortar a comunicao, sendo este intervalo chamado de time-out. Este time-out deve ser programado para ser longo o bastante para dar tempo ao escravo de responder s requisies enviadas pelo mestre de maneira normal. Se o escravo detectar um erro de transmisso, a mensagem no ser validada e tambm no ser enviada nenhuma resposta para o mestre, dessa forma, o time-out ser atingido, o que permitir ao
mestre gerenciar a ocorrncia do erro. Devemos notar que uma mensagem endereada a um dispositivo escravo que no est presente na rede, encontra-se danicado, por exemplo, tambm acarretar num time-out.
Captulo 3
10
ID (4 bytes)
Funo (4 bytes)
Estao (4 bytes)
Dados (n bytes)
ID (4 bytes)
Funo (4 bytes)
Dados (n bytes)
11
Descrio Aguardando rplica intermediria (ACK ou NACK) Aguardando resposta denitiva Figura 3.3: Estados das Requisies
As locais so executadas no servidor, enquanto que as remotas exigem a comunicao com a rede de campo para a sua execuo. Neste caso, ser necessrio acessar uma estao da rede campo, que so identicadas por um nmero inteiro positivo, onde o endereo zero signica o acesso a todas as estaes da rede de campo.
12
eliminada de BC1. O recebimento de uma RD para uma requisio no estado PCI_WAIT_RI viola o protocolo de comunicao e, portanto, a resposta deve ser descartada. O mesmo deve acontecer no recebimento de uma RI para uma requisio no estado PCI_WAIT_RD. A busca por uma requisio correspondente s respostas deve ser feita comparando-se o campo ID dos quadros PCI. A inexistncia de uma requisio em BC1 correspondente a uma resposta recebida com um ID positivo deve fazer com que o cliente despreze tal resposta. As respostas com ID negativo devem ser processadas sem a busca por uma requisio correspondente, pois so originadas de requisies internas do servidor que podem indicar a ocorrncia de aviso ou alarmes. O processo de vericao deve percorrer BC1 a cada 10 ms e avaliar o tempo decorrido desde a chegada de cada requisio no buffer. Se a requisio estiver esperando uma RI ou RD e tiver ocorrido um timeout, o usurio deve ser noticado disto.
Captulo 4
NuSMV
NuSMV um vericador de modelos simblicos, de cdigo aberto, originado a partir de SMV [McM92], o vericador de modelos baseado em BDD desenvolvido na Carnegie Mellon University [McM93]. NuSMV foi projetado para ser robusto, atender aos padres requeridos pela indstria e ser fcil de manter e modicar, sendo escrito em ANSI C e tendo seu cdigo fonte dividido em vrios mdulos. A linguagem de entrada de NuSMV permite a descrio de Mquinas de Estado Finitas (MEFs), sendo capaz de descrever processos sncronos e assncronos bem como condies de no determinismo. O propsito inicial da entrada de NuSMV descrever as relaes de transio das MEFs, onde estas relaes descrevem as evolues vlidas do estado das MEFs e, conseqentemente, do sistema sendo modelado, dessa forma, podemos identicar as possveis conguraes futuras de um sistema a partir do seu estado atual. De um modo geral, qualquer expresso no clculo proposicional pode ser usada para denir as relaes de transio, o que prov uma grande exibilidade e ao mesmo tempo requer um certo cuidado adicional para evitar inconsistncias, como por exemplo a presena de uma contradio lgica, que pode resultar em um deadlock. Na gura 4.1, ilustramos um simples programa na linguagem NuSMV. O espao de estados das MEFs determinado pela declarao das variveis de estado, que no
MODULE main VAR request : boolean; state : {ready, busy}; ASSIGN init(state) := ready; next(state) := case state = ready & request = 1 : 1 : {ready, busy}; esac;
busy;
Captulo 4. NuSMV
14
exemplo acima so request e state. A varivel request declarada como sendo do tipo pr-denido boolean. Isto signica que ele pode assumir os valores inteiros 0 e 1. A varivel state uma varivel escalar, que pode tomar os valores simblicos ready e busy. A operao seguinte atribui ready como o valor inicial da varivel state. J o valor inicial de request no especicado, ou seja, ele pode ser ou 0 ou 1. A relao de transio das MEFs representada atravs da denio do valor das variveis na prximo estado (i.e. depois de cada transio), dado o valor das variveis no estado atual (i.e. antes da transio). O segmento case atribui o prximo valor da varivel state para o valor busy se o seu valor atual ready e request 1 (verdadeiro). Caso contrrio (o 1 antes do dois pontos), o prximo valor para state pode ser qualquer um no conjunto {ready, busy}. A varivel request no atribuda, isto signica que no h restries quanto ao seu valor, e portanto ela pode assumir qualquer valor. request ento considerada uma entrada irrestrita (unconstrained) para o sistema. NuSMV tambm possui algumas caractersticas interessantes, como a possibilidade de reutilizar mdulos denidos anteriormente. Pretendemos ento utilizar NuSMV para modelar o sistema de comunicao utilizado no projeto de Automao de Poos, e iremos testar a corretude do modelo especicado utilizando funcionalidades de NuSMV como a simulao e a vericao de modelos.
4.1.1 CTL
Utilizando CTL ns podemos descrever a evoluo de uma MEFs como uma rvore innita, onde os ns so os estados da MEFs e as arestas correspondem s transies entre estados. A estrutura de rvore deve-se ao no-determinismo possvel nas denies das transies. Os caminhos na rvore que iniciam em um dado estado so as possveis evolues da MEFs a partir daquele estado. Em CTL possvel expressar propriedades que devem ser satisfeitas para todos os caminhos iniciando num estado, bem como propriedades que devem ser satisfeitas apenas para algum dos caminhos. Considere a frmula AF p, que expressa a condio que para todos os caminhos (A) iniciando num estado, em algum momento no futuro (F), a condio p deve ser satisfeita. Isto , todas as evolues possveis do sistema futuramente alcanaro um estado satisfazendo a condio p. J a frmula CTL EF p, requer que exista algum caminho (E) que em algum estado futuro satisfaz p. Analogamente, a frmula AG p requer que a condio p sempre, ou globalmente, verdadeira em todos os estados de todos os possveis caminhos, enquanto a frmula EG p requer que exista
Captulo 4. NuSMV
15
alguma caminho ao longo do qual a condio p continuamente verdadeira. Operadores CTL podem ser aninhados de modo arbitrrio e podem ser combinados usando operadores lgicos (!, &, |, ->, <->, ...). Exemplos tpicos de frmulas CTL so: AG !p
AG EF p
AG (p -> AF q)
A [ p U q ] e E [ p U q ] A condio p ser verdadeira at que seja alcanado um estado onde a condio q verdadeira AX p e EX p
A condio p verdadeira em todos ou em alguns dos prximos estados que podem ser alcanados a partir do estado atual
Em NuSMV uma especicao CTL dada como uma frmula CTL introduzida pela palavra chave SPEC. Se uma especicao CTL processada, NuSMV verica se a frmula verdadeira em todos os estados iniciais do modelo. Se este no o caso, ento NuSMV gera um contra-exemplo, ou seja, uma trilha de execuo (nita ou innita) que exibe um comportamento vlido do modelo que no satisfaz a especicao. Trilhas de execuo so muito teis para identicar erros no programa (ou na especicao) que levam ao comportamento errado. Tambm possvel em NuSMV, restringir a ateno a algumas trilhas de execuo, chamadas de trilhas de execuo justa, colocando-se uma restrio de justia. Assim, ao avaliar as expresses, o vericador de modelos considera que os quanticadores de caminho so aplicados somente s trilhas de execuo justa. Uma declarao de justia consiste de uma frmula f que assumida ser freqentemente verdadeira em todos os caminhos justos. Um caminho ser considerado justo ento se e somente se ele satisfaz a todas as declaraes de justia.
4.1.2 LTL
Enquanto especicaes CTL expressam propriedades sobre a rvore de computao das MEFs (abordagem de ramicao com o tempo), LTL caracteriza cada caminho linear induzido pelas MEFs (abordagem linear com o tempo). As duas lgicas possuem em geral um poder expressivo diferente, mas tambm possuem vrios pontos em comum, os quais incluem a maioria das propriedades usadas na prtica. Operadores CTL tpicos so: F p
Captulo 4. NuSMV
16
G p A condio p satisfeita em todos os intantes de tempo no futuro p U q A condio p satisfeita at que seja alcanado um estado onde a condio q satisfeita X p
Devemos lembrar que, diferentemente de CTL, os operadores temporais de LTL no possuem quanticadores de caminho. De fato, frmulas LTL so avaliadas sobre caminhos lineares, e uma frmula considerada verdadeira em um modelo se ela verdadeira para todos os caminhos iniciando num dos estados iniciais daquele modelo.
Captulo 5
ClienteServidor
MestreEscravo
Operador
Equipamento Supervisorio
18
master
MODULE main VAR app : application; Figura 5.3: Implementao do Mdulo main
19
MODULE message VAR slaveAddress : 0..3; functionCode : 1..4; ASSIGN init(slaveAddress) := 0; init(functionCode) := 1; Figura 5.4: Implementao do Mdulo message MODULE channel VAR messageForMaster : boolean; messageForSlave : boolean; msg : message; ASSIGN init(messageForMaster) := FALSE; init(messageForSlave) := FALSE; Figura 5.5: Implementao do Mdulo channel
20
MODULE application VAR c : channel; m1 : master(c); s1 : slave(c, 1); s2 : slave(c, 2); s3 : slave(c, 3); ASSIGN next(c.messageForMaster) := case m1.stateMaster = processing : {FALSE}; m1.currentSlave = 0 : {FALSE}; m1.currentSlave m1.currentSlave m1.currentSlave m1.currentSlave m1.currentSlave m1.currentSlave m1.currentSlave m1.currentSlave m1.currentSlave m1.currentSlave m1.currentSlave m1.currentSlave = = = = = = = = = = = = 1 1 1 1 2 2 2 2 3 3 3 3 & & & & & & & & & & & & s1.stateSlave s1.stateSlave s1.stateSlave s1.stateSlave s2.stateSlave s2.stateSlave s2.stateSlave s2.stateSlave s3.stateSlave s3.stateSlave s3.stateSlave s3.stateSlave = = = = = = = = = = = = idle : {FALSE}; receiving : {FALSE}; processing : {FALSE}; sending : {TRUE}; idle : {FALSE}; receiving : {FALSE}; processing : {FALSE}; sending : {TRUE}; idle : {FALSE}; receiving : {FALSE}; processing : {FALSE}; sending : {TRUE};
21
No incio, o mestre encontra-se no estado idle. Alm disto, o mdulo master possui o seguinte conjunto de variveis: msgMaster: indica que o mestre deseja enviar uma mensagem; currentSlave: indica o escravo para o qual a mensagem deve ser enviada; timeout: indica se ocorreu timeout na espera por uma mensagem de resposta.
22
Sempre que h uma mensagem para o escravo no canal, o escravo a recebe; Quando a mensagem endereada especicamente quele escravo, o escravo sempre responde ao mestre; O escravo somente recebe mensagens que so endereadas a ele ou que so enviadas em broadcast; Sempre que o mestre manda mensagens para um escravo o escravo recebe a mensagem enviada; Sempre que o escravo responde e no ocorre timeout o mestre recebe a resposta enviada pelo escravo; Sempre que o mestre est esperando e o escravo recebe a mensagem que o mestre enviou, ocorrer timeout ou o mestre receber a resposta do escravo.
Captulo 6
24
buffer message
serverReader
serverWriter
serverInternalProcess
MODULE main VAR app : application; Figura 6.4: Implementao do Mdulo main
25
MODULE message VAR idClient: 1..2; idMessage: -1..1; idFunction: 1..4; -1 representa funcao local e 2 funcao remota -3 representa PCI_NACK e 4 PCI_ACK Figura 6.5: Implementao do Mdulo message MODULE channel VAR messageForClient : boolean; messageForServer : boolean; msgClient : message; msgServer : message; ASSIGN init(messageForClient) := FALSE; init(messageForServer) := FALSE; Figura 6.6: Implementao do Mdulo channel
26
MODULE buffer VAR msgBuffer1 : message; msgBuffer2 : message; currentSize : 0..2; status1 : 0..2; status2 : 0..2; ASSIGN init(currentSize) := 0; init(status1) := 0; init(status2) := 0; Figura 6.7: Implementao do Mdulo buffer MODULE application VAR c : channel; s : server(c); c1 : client(c, 1); c2 : client(c, 2); Figura 6.8: Implementao do Mdulo application currentSize: indica o nmero de posies atualmente ocupadas do buffer. No incio, o tamanho do buffer zero e todas as posies esto livres. A implementao deste mdulo pode ser vista na gura 6.7.
27
MODULE server(c) VAR BS1 : buffer; BS2 : buffer; BS3 : buffer; lockBS3 : boolean; -trava para acessar o buffer BS3 reader : process serverReader(c, BS1, BS2); local : process serverLocalProcess(BS1, BS3, lockBS3); remote : process serverRemoteProcess(BS2, BS3, lockBS3); writer : process serverWriter(c, BS3); internal : process serverInternalProcess(c); ASSIGN init(lockBS3) := FALSE; Figura 6.9: Implementao do Mdulo server
28
29
MODULE serverWriter(c, BS3) VAR state : {idle, writing}; ASSIGN init(state) := idle; next(state) := case state = idle & (BS3.status1 = 1 | BS3.status2 = 1) : {writing}; state = writing & c.messageForClient : {writing}; state = writing : {idle}; 1 : state; esac; next(c.msgClient.idMessage) := case state = writing & !c.messageForClient & BS3.status1 = 1 : BS3.msgBuffer1.idMessage; state = writing & !c.messageForClient & BS3.status2 = 1 : BS3.msgBuffer2.idMessage; 1 : c.msgClient.idMessage; esac; next(c.msgClient.idClient) := case state = writing & !c.messageForClient & BS3.status1 = 1 : BS3.msgBuffer1.idClient; state = writing & !c.messageForClient & BS3.status2 = 1 : BS3.msgBuffer2.idClient; 1 : c.msgClient.idClient; esac; next(c.msgClient.idFunction) := case state = writing & !c.messageForClient & BS3.status1 = 1 : BS3.msgBuffer1.idFunction; state = writing & !c.messageForClient & BS3.status2 = 1 : BS3.msgBuffer2.idFunction; 1 : c.msgClient.idFunction; esac; next(c.messageForClient) := case state = writing & !c.messageForClient : TRUE; 1 : c.messageForClient; esac; next(BS3.currentSize) := case state = writing & BS3.currentSize > 0 : {BS3.currentSize - 1}; 1 : BS3.currentSize; esac; next(BS3.status1) := case state = writing & BS3.status1 = 1 : 0; 1 : BS3.status1; esac; next(BS3.status2) := case state = writing & BS3.status2 = 2 : 0; 1 : BS3.status2; esac; FAIRNESS running
Figura 6.10: Implementao do Mdulo serverWriter
30
MODULE client(c, idClient) VAR BC1 : buffer; sender : process clientSender(c, idClient, BC1); receiver : process clientReceiver(c, idClient, BC1); verifier : process clientVerifier(BC1); Figura 6.11: Implementao do Mdulo client
31
MODULE clientVerifier(BC1) VAR state : {testing, removing}; remove1 : boolean; remove2 : boolean; ASSIGN init(state) := testing; next(state) := case state = testing : removing; state = removing : testing; 1 : state; esac; init(remove1) := FALSE; next(remove1) := case state = testing & BC1.status1 != 0 : {TRUE, FALSE}; state = testing : FALSE; 1 : remove1; esac; init(remove2) := FALSE; next(remove2) := case state = testing & BC1.status2 != 0 : {TRUE, FALSE}; state = testing : FALSE; 1 : remove2; esac; next(BC1.status1) := case state = removing & remove1 : 0; 1 : BC1.status1; esac; next(BC1.status2) := case state = removing & remove2 : 0; 1 : BC1.status2; esac; next(BC1.currentSize) := case state = removing & remove1 & remove2 & BC1.currentSize > 1 : {BC1.currentSize - 2}; state = removing & (remove1 | remove2) & BC1.currentSize > 0 : {BC1.currentSize - 1}; 1 : BC1.currentSize; esac; FAIRNESS running
Figura 6.12: Implementao do Mdulo clientVerier
32
Sempre que o servidor est ocioso e h uma mensagem para ele no canal ele recebe esta mensagem; Sempre que o cliente envia uma mensagem o servidor a recebe; O servidor sempre fornece uma RI para os clientes; Sempre que existem respostas no buffer BS3 o servidor as envia para os clientes.
Captulo 7
Concluso
O uso de mtodos formais permitiu-nos vericar propriedades importantes de subsistemas, principalmente na parte onde ocorre comunicao mestre/escravo. A modelagem formal do modelo de comunicao tambm til como uma forma de documentao do sistema. Devido a grande complexidade do modelo da parte cliente/servidor, no foi possvel ainda vericar muitas propriedades a respeito do mesmo. Visando solucionar este problema, foram feitos vrios renamentos no modelo, buscando sempre diminuir a sua complexidade, como a eliminao de variveis, a reduo do nmero de clientes e do tamanho dos buffers etc. Podemos concluir que a construo de modelos formais para sistemas complexos uma tarefa rdua, pois exige uma modelagem que torne o modelo possvel de ser vericado e ao mesmo tempo respresente da melhor forma possvel o sistema real. Uma possvel abordagem para tentar contornar este problema da complexidade do modelo seria a utlizao da lgica LTL, a qual poderia nos fornecer resultados mais signicativos. Isto se deve ao fato de que LTL nos permitiria vericar propriedades a respeito de cada mdulo do sistema, permintindonos ento fazer inferncias sobre o comportamento do sistema como um todo. Em virtude de NuSMV no permitir a ligao de mdulos declarados em arquivos distintos, zemos uso do pr-processador C para podermos trabalhar de forma mais modular, criando vrios mdulos em arquivos separados e usando diretivas include para formar um arquivo com todos os mdulos. Este procedimento foi utilizado tanto para a construo do modelo em si como para a vericao de propriedades a respeito do mesmo, separando as propriedades em grupos, de acordo com o mdulo a que elas se referiam. Como o modelo cliente/servidor cou muito complexo, no foi possvel a integrao entre os dois modelos, que era um dos objetivos iniciais deste trabalho.
Apndice A
35
MODULE main VAR app : application; MODULE application VAR c : channel; m1 : master(c); s1 : slave(c, 1); s2 : slave(c, 2); s3 : slave(c, 3); ASSIGN next(c.messageForMaster) := case m1.stateMaster = processing : {FALSE}; m1.currentSlave = 0 : {FALSE}; m1.currentSlave m1.currentSlave m1.currentSlave m1.currentSlave m1.currentSlave m1.currentSlave m1.currentSlave m1.currentSlave m1.currentSlave m1.currentSlave m1.currentSlave m1.currentSlave = = = = = = = = = = = = 1 1 1 1 2 2 2 2 3 3 3 3 & & & & & & & & & & & & s1.stateSlave s1.stateSlave s1.stateSlave s1.stateSlave s2.stateSlave s2.stateSlave s2.stateSlave s2.stateSlave s3.stateSlave s3.stateSlave s3.stateSlave s3.stateSlave = = = = = = = = = = = = idle : {FALSE}; receiving : {FALSE}; processing : {FALSE}; sending : {TRUE}; idle : {FALSE}; receiving : {FALSE}; processing : {FALSE}; sending : {TRUE}; idle : {FALSE}; receiving : {FALSE}; processing : {FALSE}; sending : {TRUE};
1 : c.messageForMaster; esac; MODULE message VAR slaveAddress : 0..3; functionCode : 1..4; ASSIGN init(slaveAddress) := 0; init(functionCode) := 1; MODULE channel VAR messageForMaster : boolean; messageForSlave : boolean; msg : message; ASSIGN init(messageForMaster) := FALSE; init(messageForSlave) := FALSE; MODULE master(c) VAR stateMaster : {idle, packing, sending, waiting, receiving, processing}; msgMaster : boolean; currentSlave : 0..3; timeout : boolean;
Figura A.1: Implementao da Comunicao Mestre/Escravo
36
ASSIGN init(stateMaster) := idle; next(stateMaster) := case stateMaster = idle & msgMaster : packing; stateMaster = packing & !msgMaster : sending; stateMaster = sending & c.messageForSlave & currentSlave != 0 : waiting; stateMaster = sending & c.messageForSlave & currentSlave = 0 : idle; stateMaster = waiting & timeout : idle; stateMaster = waiting & c.msg.slaveAddress = 0 : idle; stateMaster = waiting & c.messageForMaster : receiving; stateMaster = receiving & msgMaster : processing; stateMaster = processing & !msgMaster : idle; 1 : stateMaster; esac; init(msgMaster) := FALSE; next(msgMaster) := case stateMaster = idle : {FALSE, TRUE}; stateMaster = packing : {FALSE}; stateMaster = sending : {FALSE}; stateMaster = waiting : {FALSE}; stateMaster = receiving : {TRUE}; stateMaster = processing : {FALSE}; 1 : msgMaster; esac; next(c.messageForSlave) := case stateMaster = idle : {FALSE}; stateMaster = packing : {FALSE}; stateMaster = sending : {TRUE}; stateMaster = waiting & !c.messageForMaster : {TRUE}; stateMaster = waiting & c.messageForMaster : {FALSE}; stateMaster = receiving : {FALSE}; stateMaster = processing : {FALSE}; 1 : c.messageForSlave; esac; init(currentSlave) := 0; next(currentSlave) := case stateMaster = idle & msgMaster : {0,1,2,3}; 1 : currentSlave; esac; next(c.msg.slaveAddress) := case stateMaster = packing : {currentSlave}; 1 : c.msg.slaveAddress; esac; init(timeout) := FALSE; next(timeout) := case currentSlave != 0 & stateMaster = waiting : {TRUE, FALSE}; 1 : timeout; esac; FAIRNESS stateMaster = sending
Figura A.2: Implementao da Comunicao Mestre/Escravo
37
MODULE slave(c, id) VAR stateSlave : {idle, sending, receiving, processing}; idSlave : 1..3; msgSlave : boolean; res : boolean; currentId : 0..3; ASSIGN init(idSlave) := id; next(idSlave) := idSlave; init(stateSlave) := idle; next(stateSlave) := case stateSlave = idle & c.messageForSlave & (c.msg.slaveAddress = idSlave | c.msg.slaveAddress = 0) : receiving; stateSlave = receiving & msgSlave : processing; stateSlave = processing & currentId != idSlave : idle; stateSlave = processing & currentId = idSlave & res : sending; stateSlave = sending : idle; 1 : stateSlave; esac; init(msgSlave) := FALSE; next(msgSlave) := case stateSlave = idle : {FALSE}; stateSlave = receiving : {TRUE}; stateSlave = processing : {FALSE}; stateSlave = sending : {FALSE}; 1 : msgSlave; esac; init(res) := FALSE; next(res) := case stateSlave = idle : {FALSE}; stateSlave = receiving : {FALSE}; stateSlave = processing & currentId = idSlave : {TRUE}; stateSlave = processing & currentId != idSlave : {FALSE}; stateSlave = sending & c.msg.slaveAddress = idSlave : {FALSE}; 1 : res; esac; init(currentId) := 0; next(currentId) := case stateSlave = idle & (c.msg.slaveAddress = 0 | c.msg.slaveAddress = idSlave) : c.msg.slaveAddress; 1 : currentId; esac;
Figura A.3: Implementao da Comunicao Mestre/Escravo
Apndice A
39
MODULE main VAR app : application; MODULE message VAR idClient: 1..2; idMessage: -1..1; idFunction: 1..4; -1 representa funcao local e 2 funcao remota -3 representa not acknowledge e 4 acknowledge MODULE channel VAR messageForClient : boolean; messageForServer : boolean; msgClient : message; msgServer : message; ASSIGN init(messageForClient) := FALSE; init(messageForServer) := FALSE; MODULE buffer VAR msgBuffer1 : message; msgBuffer2 : message; currentSize : 0..2; -tamanho atual do buffer status1 : 0..2; -indica o status da mensagem na posicao 1 do buffer - 0 -> posicao livre - 1, 2 -> posicao ocupada - no caso de BC1, temos o seguinte signficado - 1 -> aguardando resposta intermediaria - 2 -> aguardando resposta definitiva status2 : 0..2; -indica o status da mensagem na posicao 2 do buffer ASSIGN init(currentSize) := 0; init(status1) := 0; init(status2) := 0; MODULE application VAR c : channel; s : server(c); c1 : client(c, 1); c2 : client(c, 2); MODULE server(c) VAR BS1 : buffer; BS2 : buffer; BS3 : buffer; lockBS3 : boolean; -trava para acessar o buffer BS3 reader : process serverReader(c, BS1, BS2); local : process serverLocalProcess(BS1, BS3, lockBS3); remote : process serverRemoteProcess(BS2, BS3, lockBS3); writer : process serverWriter(c, BS3); internal : process serverInternalProcess(c); ASSIGN init(lockBS3) := FALSE;
Figura A.1: Implementao da Comunicao Cliente/Servidor
40
MODULE serverReader(c, BS1, BS2) VAR state : {idle, asking, copying}; idInsert : 1..2; ASSIGN init(state) := idle; next(state) := case state = idle & c.messageForServer : {asking}; state = asking & ((BS1.currentSize < 2 & c.msgServer.idFunction = 1) | (BS2.currentSize < 2 & c.msgServer.idFunction = 2)) & c.messageForClient : {copying}; state = asking & ((BS1.currentSize = 2 & c.msgServer.idFunction = 1) | (BS2.currentSize = 2 & c.msgServer.idFunction = 2)) & !c.messageForClient : {idle}; state = copying : {idle}; 1 : state; esac; -********************************************* -tira a mensagem do canal next(c.messageForServer) := case state = copying : FALSE; 1 : c.messageForServer; esac; -********************************************* -respondendo ao cliente que recebeu a mensagem next(c.msgClient.idFunction) := case state = asking & !c.messageForClient & ((BS1.currentSize < 2 & c.msgServer.idFunction = 1) | (BS2.currentSize < 2 & c.msgServer.idFunction = 2)) : {3}; state = asking & !c.messageForClient & ((BS1.currentSize = 2 & c.msgServer.idFunction = 1) | (BS2.currentSize = 2 & c.msgServer.idFunction = 2)) : {4}; 1 : c.msgClient.idFunction; esac; next(c.msgClient.idClient) := case state = asking & !c.messageForClient : {c.msgServer.idClient}; 1 : c.msgClient.idClient; esac; next(c.msgClient.idMessage) := case state = asking & !c.messageForClient : {c.msgServer.idMessage}; 1 : c.msgClient.idMessage; esac; next(c.messageForClient) := case state = asking & !c.messageForClient : TRUE; 1 : c.messageForClient; esac; -terminou de responder ao cliente -********************************
Figura A.2: Implementao da Comunicao Cliente/Servidor
41
-considerando a funcao 1 como funcao local next(idInsert) := case state = idle & BS1.currentSize < 2 & c.msgServer.idFunction = 1 & BS1.status1 state = idle & BS1.currentSize < 2 & c.msgServer.idFunction = 1 & BS1.status2 state = idle & BS1.currentSize < 2 & c.msgServer.idFunction = 2 & BS2.status1 state = idle & BS1.currentSize < 2 & c.msgServer.idFunction = 2 & BS2.status2 1 : idInsert; esac;
next(BS1.status1) := case state = copying & c.msgServer.idFunction=1 & idInsert=1 : 1; 1 : BS1.status1; esac; next(BS1.status2) := case state = copying & c.msgServer.idFunction=1 & idInsert=2 : 1; 1 : BS1.status2; esac; next(BS2.status1) := case state = copying & c.msgServer.idFunction=2 & idInsert=1 : 1; 1 : BS2.status1; esac; next(BS2.status2) := case state = copying & c.msgServer.idFunction=2 & idInsert=2 : 1; 1 : BS2.status2; esac; next(BS1.msgBuffer1.idMessage) := case state = copying & c.msgServer.idFunction = 1 & idInsert = 1 : c.msgServer.idMessage; 1 : BS1.msgBuffer1.idMessage; esac; next(BS1.msgBuffer1.idFunction) := case state = copying & c.msgServer.idFunction = 1 & idInsert = 1 : c.msgServer.idFunction; 1 : BS1.msgBuffer1.idFunction; esac; next(BS1.msgBuffer2.idMessage) := case state = copying & c.msgServer.idFunction = 1 & idInsert = 2 : c.msgServer.idMessage; 1 : BS1.msgBuffer2.idMessage; esac; next(BS1.msgBuffer2.idFunction) := case state = copying & c.msgServer.idFunction = 1 & idInsert = 2 : c.msgServer.idFunction; 1 : BS1.msgBuffer2.idFunction; esac;
Figura A.3: Implementao da Comunicao Cliente/Servidor
42
next(BS2.msgBuffer1.idMessage) := case state = copying & c.msgServer.idFunction = 2 & idInsert = 1 : c.msgServer.idMessage; 1 : BS2.msgBuffer1.idMessage; esac; next(BS2.msgBuffer1.idFunction) := case state = copying & c.msgServer.idFunction = 2 & idInsert = 1 : c.msgServer.idFunction; 1 : BS2.msgBuffer1.idFunction; esac; next(BS2.msgBuffer2.idMessage) := case state = copying & c.msgServer.idFunction = 2 & idInsert = 2 : c.msgServer.idMessage; 1 : BS2.msgBuffer2.idMessage; esac; next(BS2.msgBuffer2.idFunction) := case state = copying & c.msgServer.idFunction = 2 & idInsert = 2 : c.msgServer.idFunction; 1 : BS2.msgBuffer2.idFunction; esac; next(BS1.currentSize) := case state = copying & c.msgServer.idFunction = 1 & BS1.currentSize < 2 : {BS1.currentSize + 1}; 1 : BS1.currentSize; esac; next(BS2.currentSize) := case state = copying & c.msgServer.idFunction = 2 & BS2.currentSize < 2 : {BS2.currentSize + 1}; 1 : BS2.currentSize; esac; FAIRNESS running MODULE serverLocalProcess(BS1, BS3, lockBS3) VAR state : {idle, copying}; idBS1 : 1..2; idBS3 : 1..2; ASSIGN init(state) := idle; next(state) := case state = idle & BS1.currentSize > 0 & lockBS3 = FALSE & BS3.currentSize < 2 : {copying}; state = copying : {idle}; 1 : state; esac; next(lockBS3) := case state = idle & BS1.currentSize > 0 & lockBS3 = FALSE & BS3.currentSize < 2 : TRUE; state = copying : 0; 1 : lockBS3; esac;
Figura A.4: Implementao da Comunicao Cliente/Servidor
43
init(idBS1) := 1; next(idBS1) := case state = idle & BS1.status1 != 0 : {1}; state = idle & BS1.status2 != 0 : {2}; 1 : idBS1; esac; init(idBS3) := 1; next(idBS3) := case state = idle & BS3.status1 = 0 : 1; state = idle & BS3.status2 = 0 : 2; 1 : idBS3; esac; next(BS1.status1) := case state = copying & idBS1 = 1 : 0; 1 : BS1.status1; esac; next(BS1.status2) := case state = copying & idBS1 = 2 : 0; 1 : BS1.status2; esac; next(BS1.currentSize) := case state = copying & BS1.currentSize > 0 : {BS1.currentSize - 1}; 1 : BS1.currentSize; esac; next(BS3.currentSize) := case state = copying & BS3.currentSize < 2 : BS3.currentSize + 1; 1 : BS3.currentSize; esac; next(BS3.status1) := case state = copying & idBS3 = 1 : 1; 1 : BS3.status1; esac; next(BS3.status2) := case state = copying & idBS3 = 2 : 1; 1 : BS3.status2; esac; next(BS3.msgBuffer1.idMessage) := case state = copying & idBS3 = 1 : {BS1.msgBuffer1.idMessage}; 1 : BS3.msgBuffer1.idMessage; esac; next(BS3.msgBuffer1.idFunction) := case state = copying & idBS3 = 1 : {BS1.msgBuffer1.idFunction}; 1 : BS3.msgBuffer1.idFunction; esac; next(BS3.msgBuffer1.idClient) := case state = copying & idBS3 = 1 : {BS1.msgBuffer1.idClient}; 1 : BS3.msgBuffer1.idClient; esac;
Figura A.5: Implementao da Comunicao Cliente/Servidor
44
next(BS3.msgBuffer2.idMessage) := case state = copying & idBS3 = 2 : {BS1.msgBuffer2.idMessage}; 1 : BS3.msgBuffer2.idMessage; esac; next(BS3.msgBuffer2.idFunction) := case state = copying & idBS3 = 2 : {BS1.msgBuffer2.idFunction}; 1 : BS3.msgBuffer2.idFunction; esac; next(BS3.msgBuffer2.idClient) := case state = copying & idBS3 = 2 : {BS1.msgBuffer2.idClient}; 1 : BS3.msgBuffer2.idClient; esac; FAIRNESS running MODULE serverRemoteProcess(BS2, BS3, lockBS3) VAR state : {idle, copying}; idBS2 : 1..2; idBS3 : 1..2; ASSIGN init(state) := idle; next(state) := case state = idle & BS2.currentSize > 0 & lockBS3 = FALSE & BS3.currentSize < 2 : {copying}; state = copying : {idle}; 1 : state; esac; next(lockBS3) := case state = idle & BS2.currentSize > 0 & lockBS3 = FALSE & BS3.currentSize < 2 : TRUE; state = copying : 0; 1 : lockBS3; esac; init(idBS2) := 1; next(idBS2) := case state = idle & BS2.status1 != 0 : {1}; state = idle & BS2.status2 != 0 : {2}; 1 : idBS2; esac; init(idBS3) := 1; next(idBS3) := case state = idle & BS3.status1 = 0 : 1; state = idle & BS3.status2 = 0 : 2; 1 : idBS3; esac; next(BS2.status1) := case state = copying & idBS2 = 1 : 0; 1 : BS2.status1; esac;
Figura A.6: Implementao da Comunicao Cliente/Servidor
45
next(BS2.status2) := case state = copying & idBS2 = 2 : 0; 1 : BS2.status2; esac; next(BS2.currentSize) := case state = copying & BS2.currentSize > 0 : {BS2.currentSize - 1}; 1 : BS2.currentSize; esac; next(BS3.currentSize) := case state = copying & BS3.currentSize < 2 : BS3.currentSize + 1; 1 : BS3.currentSize; esac; next(BS3.status1) := case state = copying & idBS3 = 1 : 1; 1 : BS3.status1; esac; next(BS3.status2) := case state = copying & idBS3 = 2 : 1; 1 : BS3.status2; esac; next(BS3.msgBuffer1.idMessage) := case state = copying & idBS3 = 1 : {BS2.msgBuffer1.idMessage}; 1 : BS3.msgBuffer1.idMessage; esac; next(BS3.msgBuffer1.idFunction) := case state = copying & idBS3 = 1 : {BS2.msgBuffer1.idFunction}; 1 : BS3.msgBuffer1.idFunction; esac; next(BS3.msgBuffer1.idClient) := case state = copying & idBS3 = 1 : {BS2.msgBuffer1.idClient}; 1 : BS3.msgBuffer1.idClient; esac; next(BS3.msgBuffer2.idMessage) := case state = copying & idBS3 = 2 : {BS2.msgBuffer2.idMessage}; 1 : BS3.msgBuffer2.idMessage; esac; next(BS3.msgBuffer2.idFunction) := case state = copying & idBS3 = 2 : {BS2.msgBuffer2.idFunction}; 1 : BS3.msgBuffer2.idFunction; esac; next(BS3.msgBuffer2.idClient) := case state = copying & idBS3 = 2 : {BS2.msgBuffer2.idClient}; 1 : BS3.msgBuffer2.idClient; esac; FAIRNESS running
Figura A.7: Implementao da Comunicao Cliente/Servidor
46
MODULE serverWriter(c, BS3) VAR state : {idle, writing}; ASSIGN init(state) := idle; next(state) := case state = idle & (BS3.status1 = 1 | BS3.status2 = 1) : {writing}; state = writing & c.messageForClient : {writing}; state = writing : {idle}; 1 : state; esac; next(c.msgClient.idMessage) := case state = writing & !c.messageForClient & BS3.status1 = 1 : BS3.msgBuffer1.idMessage; state = writing & !c.messageForClient & BS3.status2 = 1 : BS3.msgBuffer2.idMessage; 1 : c.msgClient.idMessage; esac; next(c.msgClient.idClient) := case state = writing & !c.messageForClient & BS3.status1 = 1 : BS3.msgBuffer1.idClient; state = writing & !c.messageForClient & BS3.status2 = 1 : BS3.msgBuffer2.idClient; 1 : c.msgClient.idClient; esac; next(c.msgClient.idFunction) := case state = writing & !c.messageForClient & BS3.status1 = 1 : BS3.msgBuffer1.idFunction; state = writing & !c.messageForClient & BS3.status2 = 1 : BS3.msgBuffer2.idFunction; 1 : c.msgClient.idFunction; esac; next(c.messageForClient) := case state = writing & !c.messageForClient : TRUE; 1 : c.messageForClient; esac; next(BS3.currentSize) := case state = writing & BS3.currentSize > 0 : {BS3.currentSize - 1}; 1 : BS3.currentSize; esac; next(BS3.status1) := case state = writing & BS3.status1 = 1 : 0; 1 : BS3.status1; esac; next(BS3.status2) := case state = writing & BS3.status2 = 2 : 0; 1 : BS3.status2; esac; FAIRNESS running MODULE serverInternalProcess
Figura A.8: Implementao da Comunicao Cliente/Servidor
47
MODULE client(c, idClient) VAR BC1 : buffer; sender : process clientSender(c, idClient, BC1); receiver : process clientReceiver(c, idClient, BC1); verifier : process clientVerifier(BC1); MODULE clientSender(c, idClient, BC1) VAR state : {idle, copying, sending}; idInsert : 1..2; ASSIGN init(state) := idle; next(state) := case state = idle & BC1.currentSize < 2 : {idle, copying}; state = copying : {sending}; state = sending & c.messageForServer : {sending}; state = sending & !c.messageForServer : {idle}; 1 : state; esac; init(idInsert) := 1; next(idInsert) := case state = idle & BC1.status1 = 0 : 1; state = idle & BC1.status2 = 0 : 2; 1 : idInsert; esac; next(BC1.currentSize) := case state = copying & BC1.currentSize < 2 : BC1.currentSize + 1; 1 : BC1.currentSize; esac; next(BC1.msgBuffer1.idClient) := case state = copying & idInsert = 1 : {idClient}; 1 : BC1.msgBuffer1.idClient; esac; next(BC1.msgBuffer1.idFunction) := case state = copying & idInsert = 1 : {1, 2}; 1 : BC1.msgBuffer1.idFunction; esac; next(BC1.msgBuffer1.idMessage) := case state = copying & idInsert = 1 & (BC1.status2 = 0 | BC1.msgBuffer2.idMessage != 0) : {0}; state = copying & idInsert = 1 & (BC1.status2 = 0 | BC1.msgBuffer2.idMessage != 1) : {1}; 1 : BC1.msgBuffer1.idMessage; esac; next(BC1.status1) := case state = copying & idInsert = 1 : 1; 1 : BC1.status1; esac;
Figura A.9: Implementao da Comunicao Cliente/Servidor
48
next(BC1.msgBuffer2.idClient) := case state = copying & idInsert = 2 : {idClient}; 1 : BC1.msgBuffer2.idClient; esac; next(BC1.msgBuffer2.idFunction) := case state = copying & idInsert = 2 : {1, 2}; 1 : BC1.msgBuffer2.idFunction; esac; next(BC1.msgBuffer2.idMessage) := case state = copying & idInsert = 2 & BC1.msgBuffer1.idMessage != 0 : {0}; state = copying & idInsert = 2 & BC1.msgBuffer1.idMessage != 1 : {1}; 1 : BC1.msgBuffer2.idMessage; esac; next(BC1.status2) := case state = copying & idInsert = 2 : 1; 1 : BC1.status2; esac; next(c.messageForServer) := case !c.messageForServer & state = sending : TRUE; 1 : c.messageForServer; esac; next(c.msgServer.idClient) := case state = sending & !c.messageForServer : idClient; 1 : c.msgServer.idClient; esac; next(c.msgServer.idMessage) := case state = sending & !c.messageForServer & idInsert = 1 : BC1.msgBuffer1.idMessage; state = sending & !c.messageForServer & idInsert = 2 : BC1.msgBuffer2.idMessage; 1 : c.msgServer.idMessage; esac; next(c.msgServer.idFunction) := case state = sending & !c.messageForServer & idInsert = 1 : BC1.msgBuffer1.idFunction; state = sending & !c.messageForServer & idInsert = 2 : BC1.msgBuffer2.idFunction; 1 : c.msgServer.idFunction; esac; FAIRNESS running MODULE clientReceiver(c, idClient, BC1) VAR state : {idle, processing};
Figura A.10: Implementao da Comunicao Cliente/Servidor
49
ASSIGN init(state) := idle; next(state) := case state = idle & c.messageForClient & c.msgClient.idClient = idClient : processing; state = processing : {idle}; 1 : state; esac; next(c.messageForClient) := case state = processing : FALSE; 1 : c.messageForClient; esac; next(BC1.status1) := case -a requisicao nao pode ser atendida pelo servidor BC1.status1 = 1 & state = processing & c.msgClient.idMessage = BC1.msgBuffer1.idMessage & c.msgClient.idFunction = 3 : {0}; -a requisicao vai ser atendida pelo servidor BC1.status1 = 1 & state = processing & c.msgClient.idMessage = BC1.msgBuffer1.idMessage & c.msgClient.idFunction = 4 : {2}; -recebeu resposta definitiva BC1.status1 = 2 & state = processing & c.msgClient.idMessage = BC1.msgBuffer1.idMessage : {0}; 1 : BC1.status1; esac; next(BC1.status2) := case -a requisicao nao pode ser atendida pelo servidor BC1.status2 = 1 & state = processing & c.msgClient.idMessage = BC1.msgBuffer2.idMessage & c.msgClient.idFunction = 3 : {0}; -a requisicao vai ser atendida pelo servidor BC1.status2 = 1 & state = processing & c.msgClient.idMessage = BC1.msgBuffer2.idMessage & c.msgClient.idFunction = 4 : {2}; -recebeu resposta definitiva BC1.status2 = 2 & state = processing & c.msgClient.idMessage = BC1.msgBuffer2.idMessage : {0}; 1 : BC1.status2; esac; next(BC1.currentSize) := case BC1.currentSize > 0 & BC1.status1 = 1 & state = processing & c.msgClient.idMessage = BC1.msgBuffer1.idMessage & c.msgClient.idFunction = 3 : BC1.currentSize - 1; BC1.currentSize > 0 & BC1.status1 = 2 & state = processing & c.msgClient.idMessage = BC1.msgBuffer1.idMessage : BC1.currentSize - 1; BC1.currentSize > 0 & BC1.status2 = 1 & state = processing & c.msgClient.idMessage = BC1.msgBuffer2.idMessage & c.msgClient.idFunction = 3 : BC1.currentSize - 1;
Figura A.11: Implementao da Comunicao Cliente/Servidor
50
BC1.currentSize > 0 & BC1.status2 = 2 & state = processing & c.msgClient.idMessage = BC1.msgBuffer2.idMessage : BC1.currentSize - 1; 1 : BC1.currentSize; esac; FAIRNESS running MODULE clientVerifier(BC1) VAR state : {testing, removing}; remove1 : boolean; remove2 : boolean; ASSIGN init(state) := testing; next(state) := case state = testing : removing; state = removing : testing; 1 : state; esac; init(remove1) := FALSE; next(remove1) := case state = testing & BC1.status1 != 0 : {TRUE, FALSE}; state = testing : FALSE; 1 : remove1; esac; init(remove2) := FALSE; next(remove2) := case state = testing & BC1.status2 != 0 : {TRUE, FALSE}; state = testing : FALSE; 1 : remove2; esac; next(BC1.status1) := case state = removing & remove1 : 0; 1 : BC1.status1; esac; next(BC1.status2) := case state = removing & remove2 : 0; 1 : BC1.status2; esac; next(BC1.currentSize) := case state = removing & remove1 & remove2 & BC1.currentSize > 1 : {BC1.currentSize - 2}; state = removing & (remove1 | remove2) & BC1.currentSize > 0 : {BC1.currentSize - 1}; 1 : BC1.currentSize; esac; FAIRNESS running
Figura A.12: Implementao da Comunicao Cliente/Servidor
Referncias Bibliogrcas
[Alf00] Alfa Instrumentos. Protocolo de Comunicao Modbus RTU/ASCII, 2000. [CCGR99] A. Cimatti, E.M. Clarke, F. Giunchiglia, and M. Roveri. N U SMV: a new Symbolic Model Verier. In N. Halbwachs and D. Peled, editors, Proceedings Eleventh Conference on Computer-Aided Verication (CAV99), number 1633 in Lecture Notes in Computer Science, pages 495499, Trento, Italy, July 1999. Springer. [dS04] [ITC02] [Mai03] [McM92] [McM93] Rodrigo Barbosa de Souza. Uma Arquitetura Para Sistemas Supervisrios Industriais e sua Aplicao em Processos de Elevao Articial de Petrleo. Mestrado em automao e sistemas, DCA/UFRN, Natal, 2004. ITC-IRST. NuSMV 2.1 User Manual, 2002. A. Maitelli. A ufrn e a automao na rea do petrleo. In Caderno Da Vinci. UFRN, 2003. K. L. McMillan. The SMV System, 1992. Disponvel em http://www.cs.cmu.edu/ modelcheck/smv/smvmanual.r2.2.ps. Acesso em maro de 2004. K. L. McMillan. Symbolic Model Checking. Kluwer Academic Publishers, 1993.
[MOD96] MODICON, Inc., Industrial Automation Systems. Modicon Modbus Protocol Reference Guide, 1996. [MOD02] MODBUS. Modbus Application Protocol Specication, 2002.