Memória compartilhada, semáforo e criação de processos
Publicado por Perfil removido (última atualização em 17/02/2014)
[ Hits: 11.926 ]
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"
Pilhas Encadeadas Detalhadamente
Jogo da Velha com IA invencivel
Nenhum comentário foi encontrado.
Como aprovar Pull Requests em seu repositório Github via linha de comando
Como gerar um podcast a partir de um livro em PDF
Automatizando digitação de códigos 2FA no browser
Resolver problemas de Internet
Como compartilhar a tela do Ubuntu com uma Smart TV (LG, Samsung, etc.)
Resolvendo o erro "libQt6Widgets.so.6: cannot open shared object file" no Linux
Como instalar protetores de tela (Debian e derivados)
Conheça a 4Devs, caixa de ferramentas online para desenvolvedores
Como converter um vídeo MP4 para um GIF para publicar no README.md do seu repositório Github
Driver de rede realtek 8821ce bugado (1)
Problemas de compartilhame... de impressora no Ubuntu 24.04 (3)