Memória compartilhada, semáforo e criação de processos
Publicado por Perfil removido (última atualização em 17/02/2014)
[ Hits: 11.735 ]
Dois programas simples em C++ que usam recursos como memória compartilhada, semáforos e criação de processos para comunicarem entre si!
Observação: depois de compilado haverá dois binários, um chamado gerenciador e outro com o nome de cliente. Execute o gerenciador pois o mesmo executará o cliente, e um depende do outro para funcionar corretamente!
Arquivo main.cpp: #include "foo.hpp" #include <sys/wait.h> using namespace std; int shared_memory_clear(); int myfuction(); char *shared_memory; int main(){ int shmid; //Remove o segmento de memoría criado com a chave MY_KEY //MY_KEY está definido em foo.hpp shared_memory_clear(); //se esse segmento existir (ver detalhes nos comentários na função shared_memory_clear()) //shmget:para criar um segmento de memória compartilhada // para mais detalhes execute man shmget //shmat:retorna um pointeiro para o segmento de memória compartilhada // man shmat para mais detalhes if((shmid=shmget(MY_KEY,1,IPC_CREAT|IPC_EXCL|0644) ) <0 || (shared_memory=(char *)shmat(shmid,0,0) )<0 ) { cerr<<"\nFailhou ao iniciar um segmento de memória"<<endl; return -1; }else cout<<"\nSegmento de Memória... [{FONTE}33[1;32mOK{FONTE}33[0m]"<<endl; int status=myfuction(); if(status==0) return 0; //somente o processo ("child") ira retornar 0 mas // não tenho certeza disso pois o processo ("Child") //executará a função execv()para executar outro binário // deixe ele aqui no caso de dúvidas :) // esse treicho foi necessário quando eu estava testando os semaforos e o segmento de memória //nesse mesmo binario atraves da função fork() mais sem executar nenhum outro binário //mesmo modificando ele para excutar outro binário //decidi não remover: como eu disse em caso de dúvida //shmdt: eu uso essa função junto com a função shmctl mais não sei //se isso é realmente necessário :) //man shmdt para detalhes! //shmctl: faz o controle do segmento de memória.No caso usei a opção IPC_RMID para marcar para remoção // esse segmento de memória compartilhada // man shctl para detalhes if ( (shmctl(shmid,IPC_RMID,0))<0||(shmdt(shared_memory)) <0 ) { cerr<<"\nFalhou ao remover o segmento de memória!"<<endl; return -1; } return 0; } ////////////////////////////////////////////////////// int myfuction() { //Cria um semaforo nomeado para impedir que os dois programas tentem acessar //o segmento de memória ao mesmo tempo! // execute man sem_open para mais detalhes sem_t *SEM=sem_open(MY_FILE,O_CREAT|O_EXCL,644,1); if(SEM==SEM_FAILED) { cerr<<"\nFalhou ao criar um semaforo!"<<endl; return -1; } //remove o semaforo. //Se algum processo estiver usando ele a chamada da função sem_unlink é adiada // para mais detalhes execute man sem_unlink if ((sem_unlink(MY_FILE))<0) cerr<<"\nFailed to unlik semaphore file"<<endl; int child=fork(); //cria um novo processo semelhante ao em execução if(child<0) { cerr<<"\nFailed to create child process"<<endl; return -1; } if(child==0) //esse trecho só será executado pelo processo recem criado("child") { //////////////////////////////////////////// //////////////////child process//////////// ////////////////////////////////////////// execv("cliente",NULL); return 0; } else { //esse trecho só será excutado pelo processo pai ("parent"); ///////////////////////////////////////////////////// ////////////////////Parent process////////////////// //////////////////////////////////////////////////// int status; string line; //vai encerrar se o programa cliente escrever na //memória compartilhada exit while(line!="exit") { usleep(500000); //espeara um periodo curto de tempo antes de executar o //resto do código ("Taxa de atualização :)") sem_wait(SEM); line=shared_memory; //vai colocar o conteudo do pointeiro que aponta para //um segmento de memória compartilhada sem_post(SEM); } waitpid(child,&status,0); cout<<"\nCliente terminou com status"<<"("<<status<<")"; cout<<"\nSaindo"<<endl; return 1; } } //Função para remover o segmento de memoria criado com a chave "MY_KEY" //mais que pode nao ter sido removido por algum motivo,como encerramento do programa //antes de ele naturalmente remover o segmento ! int shared_memory_clear() { int shmid_del=shmget(MY_KEY,0,IPC_CREAT); if(shmid_del >0){ cout<<"\nSegmento de memória compartilhada encontrada"<<endl; if(( shmctl(shmid_del,IPC_RMID,0))<0) { cerr<<"\nFalhou ao tentar remover o segmento de memória compartilhada "<<endl; return -1; } cout<<"\nSegmento de memória compartilhada encontrada removida"<<endl; } Arquivo cliente.cpp: #include "foo.hpp" // meio sem criatividade eu! não acha? foo.hpp using namespace std; int myfuction(); char *shared_memory; int main() { int shmid=shmget(MY_KEY,0,IPC_CREAT); //colocamos a mesma chave do gerenciador aqui mais sem a flag IPC_EXCL a função não vai criar outro segmento se esse ja //existir if(shmid<0) { cerr<<"\nFalhou em shmid"<<endl; return -1; } shared_memory=(char *)shmat(shmid,0,0);// pointeiro para o segmento if(shared_memory<0) { cerr<<"\nFalhou em shmat"<<endl; return -1; } myfuction(); return 0; } int myfuction(){ sem_t *SEM=sem_open(MY_FILE,O_CREAT,0,1); //abri o semaforo ja existente if(SEM==SEM_FAILED) { cerr<<"\nFalhou em sem_open"<<endl; return -1; } if(( sem_unlink(MY_FILE))<0) //mesmo caso descrito no código do gerenciador { cerr<<"\nFalhou em sem_unlink"<<endl; return -1; } ////////////////ITER COMUNICATION AREA!/////////////////// string line; while(line!="exit") //só ira sair se voce digitar exit { cout<<"\nEscreva algo: "; getline(cin,line); sem_wait(SEM); strcpy(shared_memory,line.c_str()); sem_post(SEM); cout<<"\nVoce escreveu "<<shared_memory<<endl; } ///////////////END OF INTER COMUNICATION AREA!///////////// return 0; } Arquivo foo.hpp: #include <iostream> #include <cstring> #include <unistd.h> #include <sys/shm.h> #include <sys/stat.h> #include <fcntl.h> #include <semaphore.h> #define MY_KEY 11111 #define MY_FILE "file_for_semaphore"
Rotação à esquerda árvore Binária
Nenhum comentário foi encontrado.
Compartilhando a tela do Computador no Celular via Deskreen
Como Configurar um Túnel SSH Reverso para Acessar Sua Máquina Local a Partir de uma Máquina Remota
Configuração para desligamento automatizado de Computadores em um Ambiente Comercial
Como renomear arquivos de letras maiúsculas para minúsculas
Imprimindo no formato livreto no Linux
Vim - incrementando números em substituição
Efeito "livro" em arquivos PDF
Como resolver o erro no CUPS: Unable to get list of printer drivers
Mensagem quando tento fazer o apt update && apt upgrade no kal... (2)
Melhores Práticas de Nomenclatura: Pastas, Arquivos e Código (0)
[Python] Automação de scan de vulnerabilidades
[Python] Script para analise de superficie de ataque
[Shell Script] Novo script para redimensionar, rotacionar, converter e espelhar arquivos de imagem
[Shell Script] Iniciador de DOOM (DSDA-DOOM, Doom Retro ou Woof!)
[Shell Script] Script para adicionar bordas às imagens de uma pasta