Socketpair

Esse é o 14º artigo da série IPC, neste artigo é demonstrado uma alternativa para o IPC pipes

Introdução

Para que um processo se comunique com o outro de forma bidirecional é necessário ter duas instâncias de pipe para que o canal de escrita do pipe A se conecte ao canal de leitura do pipe B e vice e versa, em termos de código para realizar essa implementação é necessário criar duas instâncias de pipe e inserir como argumento ambos os handles para que a comunicação bidirecional seja possível. Existe uma alternativa para obter esse comportamento de forma simplificada.

socketpair

O socketpair é um systemcall capaz de conectar dois sockets de forma simplificada sem a necessidade de toda a inicialização de uma conexão tcp ou udp, devolvendo dois sockets conectados que podem ser usados para realizar a comunicação entre si de forma bidirecional.

Systemcalls usados no socketpair

Dependendo do protocolo utilizado a forma de realizar a leitura e escrita do socket pode mudar. No caso de uso TCP usar as systemcalls pertinentes a TCP, o mesmo para UDP.

Implementação

Para demonstrar o uso desse IPC, vai ser utilizado o modelo Produtor/Consumidor, onde o processo Produtor(button_process) vai escrever seu estado interno no arquivo, e o Consumidor(led_process) vai ler o estado interno e vai aplicar o estado para si. Aplicação é composta por três executáveis sendo eles:

  • launch_processes – é responsável por criar os sockets e lançar os processos button_process e led_process através da combinação fork e exec
  • button_interface – é responsável por ler o GPIO em modo de leitura da Raspberry Pi e escrever o estado interno no arquivo
  • led_interface – é responsável por ler do arquivo o estado interno do botão e aplicar em um GPIO configurado como saída

launch_processes

No main é criado algumas variáveis iniciando com pair que corresponde aos sockets que vão ser criados, pid_button e pid_led que recebem o pid dos processos referentes à button_process e led_process, duas variáveis para armazenar o resultado caso o exec venha a falhar e um buffer para montar a lista de argumentos.

Aqui é criado o par de sockets usando o protocolo TCP

Em seguida é criado um processo clone, se processo clone for igual a 0, os argumentos são preparados e armazenados na variável buffer e é criado um array de strings com o nome do programa que será usado pelo exec, em caso o exec retorne, o estado do retorno é capturado e será impresso no stdout e aborta a aplicação. Se o exec for executado com sucesso o programa button_process será carregado.

O mesmo procedimento é repetido novamente, porém com a intenção de carregar o led_process.

E por fim o pair de sockets é fechado para o processo pai

button_interface

A implementação da interface de botão é relativamente simples, onde o botão é iniciado e em seguida fica em loop aguardando um evento de pressionamento de botão, que quando pressionado altera o estado da variável interna e envia para o socket usando o handle e a mensagem formatada.

led_interface

A implementação da interface de LED é relativamente simples, onde o LED é iniciado e em seguida fica em loop aguardando uma mensagem, que quando recebida altera o estado do LED com o valor lido.

Compilando, Executando e Matando os processos

Para compilar e testar o projeto é necessário instalar a biblioteca de hardware necessária para resolver as dependências de configuração de GPIO da Raspberry Pi.

Compilando

Para faciliar a execução do exemplo, o exemplo proposto foi criado baseado em uma interface, onde é possível selecionar se usará o hardware da Raspberry Pi 3, ou se a interação com o exemplo vai ser através de input feito por FIFO e o output visualizado através de LOG.

Clonando o projeto

Pra obter uma cópia do projeto execute os comandos a seguir:

Selecionando o modo

Para selecionar o modo devemos passar para o cmake uma variável de ambiente chamada de ARCH, e pode-se passar os seguintes valores, PC ou RASPBERRY, para o caso de PC o exemplo terá sua interface preenchida com os sources presentes na pasta src/platform/pc, que permite a interação com o exemplo através de FIFO e LOG, caso seja RASPBERRY usará os GPIO’s descritos no artigo.

Modo PC

Modo RASPBERRY

Executando

Para executar a aplicação execute o processo launch_processes para lançar os processos button_process e led_process que foram determinados de acordo com o modo selecionado.

Uma vez executado podemos verificar se os processos estão rodando atráves do comando

O output

Interagindo com o exemplo

Dependendo do modo de compilação selecionado a interação com o exemplo acontece de forma diferente

MODO PC

Para o modo PC, precisamos abrir um terminal e monitorar os LOG’s

Dessa forma o terminal irá apresentar somente os LOG’s referente ao exemplo.

Para simular o botão, o processo em modo PC cria uma FIFO para permitir enviar comandos para a aplicação, dessa forma todas as vezes que for enviado o número 0 irá logar no terminal onde foi configurado para o monitoramento, segue o exemplo

Output

MODO RASPBERRY

Para o modo RASPBERRY a cada vez que o botão for pressionado irá alternar o estado do LED.

Matando os processos

Para matar os processos criados execute o script kill_process.sh

Conclusão

O socketpair é uma boa alternativa para o uso de pipes pois facilita o modo de comunicação entre processos caso haja necessidade que os processos se comuniquem entre si, ou seja, de forma bidirecional. Devido a sua facilidade de criação do par de sockets, isso o torna relativamente fácil de usar. Portanto caso houver a necessidade de usar pipes sempre prefira o socketpair por garantir a comunicação entre ambas as direções.

Referência

Outros artigos da série

<< UDP MulticastQueue System V >>
Notificações
Notificar
guest
0 Comentários
Inline Feedbacks
View all comments

WEBINAR

Visão Computacional para a redução de erros em processos manuais

DATA: 23/09 ÀS 17:00 H