Estou passando por um programa escrito em C / C ++ para controle em robótica. Basicamente, três programas diferentes são executados ao mesmo tempo e eles se comunicam via memória compartilhada. O Google que encontrei parece com o vxWorks e os cabeçalhos de interprocessamento das bibliotecas de reforço ( documentação do Boost: compartilhamento de memória entre processos ).
Agora, não quero olhar para a implementação, posso ler o link acima. Mas não consigo entender como a biblioteca de impulso faz isso. Quero dizer, um aplicativo aloca memória e outro acessa essa memória, mas como eles se comunicam? não é perigoso fazer isso?
Respostas:
O mecanismo de interprocesso de impulso tem três componentes necessários para funcionar:
arquivo mapeado na memória: um arquivo mapeado na memória precisa ser criado e passado para um alocador boost.interprocess. Esse alocador pega pedaços do arquivo e os usa como se fossem retornados por um std :: alocador, com o mapeamento aplicado para que a memória seja compatível com a memória específica em processo.
container boost.interprocess; esse tipo de contêiner usará a memória retornada pelo alocador e oferecerá uma interface como std :: container (begin / end / size / push_back, etc).
mecanismo de sincronização; pode ser qualquer mutex entre processos e deve ser usado para impedir condições de corrida de acesso a dados.
A memória alocada é na verdade um arquivo mapeado na memória compartilhada. A comunicação é indireta, com os aplicativos configurando ou lendo os dados, conforme necessário. A segurança vem do uso de primitivas de sincronização interprocessos.
fonte
a memória compartilhada não é a imagem completa do IPC, é um mecanismo de passagem de dados, mas você ainda precisa de alguma maneira de informar o outro processo de que alguns dados foram atualizados e estão disponíveis para leitura. Você decide como você faz isso, normalmente você usaria um objeto de evento ou mutex do SO; cada processo espera que isso seja definido, a gravação do aplicativo o define assim que termina a gravação. Em seguida, os threads nos outros programas são ativados e lidos.
Como alternativa, você pode pesquisar, ler os dados regularmente para obter um valor que muda quando os dados são atualizados (por exemplo, um contador incremental).
fonte
O Boost usa o mapeamento de memória de um arquivo.
O unix e o Windows suportam a criação de arquivos que não existem no sistema de arquivos normal para esse fim.
Em seguida, você precisará sincronizar o acesso a essa memória como faria se threads diferentes o acessassem. Isso significa que leituras simultâneas podem ocorrer sem sincronização, mas assim que um processo desejar, você precisará impedir que outros acessem.
Operações atômicas na memória compartilhada ainda serão possíveis se você desejar uma sincronização sem bloqueio.
fonte
std::atomic
classe de modelo C ++ 11 ( cplusplus.com/reference/atomic ) em cada um dos dois programas para que eles possam gravar no espaço compartilhado sem sincronização aplicada por meio de bloqueios?A memória compartilhada ainda é apenas memória. Você pode colocar um mutex, spinlock ou qualquer outra primitiva de sincronização lá e usá-los para sincronizar o acesso de seus processos à memória compartilhada, exatamente como os threads usam essas primitivas para sincronizar o acesso à memória visível para eles.
As únicas diferenças reais são:
os threads compartilham toda a memória e o mesmo espaço de endereço; portanto, ponteiros brutos trabalham para eles. A memória compartilhada entre processos funciona exatamente da mesma forma, mas pode ser mapeada em endereços diferentes em cada processo, portanto, você não pode simplesmente passar ponteiros brutos entre eles
algumas primitivas de sincronização podem precisar de sinalizadores ou atributos especiais para funcionar corretamente entre processos (consulte o
PTHREAD_PROCESS_SHARED
atributo para mutexes de encadeamento POSIX, por exemplo). Isso não tem nada a ver com a memória e a sincronização em si, mas devido à interação do kernel / agendador necessária para ativar os garçons adormecidos.Assim:
Da mesma maneira que diferentes threads se comunicam, permitindo as advertências acima
Sim, é exatamente tão inseguro para os processos se comunicarem via memória compartilhada quanto para os threads se comunicarem via memória compartilhada, e eles precisam de sincronização equivalente (ou idêntica) para torná- la segura.
fonte
Observe que C e C ++ são linguagens diferentes.
A memória compartilhada é impossível no padrão C11 ou C ++ 11 (já que o padrão não define isso), ou mesmo no C ++ 14 (cujo rascunho n3690 , e presumivelmente padrão oficial, não menciona memória compartilhada fora do multi-threading ) Então você precisa de bibliotecas extras para obter memória compartilhada. Mas alguns sistemas operacionais têm suporte para memória compartilhada. Portanto, existem várias bibliotecas que fornecem memória compartilhada, construídas acima dos serviços existentes do sistema operacional. Talvez você possa considerar o uso da biblioteca de estruturas POCO (que abstrai detalhes específicos do SO)
Para Linux (e talvez POSIX), consulte shm_overview (7) . Você precisará sincronizar, veja também sem_overview (7)
O VXWorks (que eu não conheço, mas pesquisei por ele) possui o VxMP
Você precisa entender cuidadosamente o que realmente está acontecendo. Você provavelmente deseja compartilhar apenas dados antigos simples
struct
(não classes C ++!) E deve ter muito cuidado com os endereços (cada processo pode obter um endereço diferente para o segmento de memória compartilhada comum) e com a sincronização.Como alternativa, use threads. Observe que o padrão C ++ 11 define uma biblioteca de threads .
fonte