Memória compartilhada, semáforo e criação de processos
Publicado por Perfil removido (última atualização em 17/02/2014)
[ Hits: 12.048 ]
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"
Thread, Courses, Shell e Aquivo
Nenhum comentário foi encontrado.
Como extrair chaves TOTP 2FA a partir de QRCODE (Google Authenticator)
Linux em 2025: Segurança prática para o usuário
Desktop Linux em alta: novos apps, distros e privacidade marcam o sábado
IA chega ao desktop e impulsiona produtividade no mundo Linux
Novos apps de produtividade, avanços em IA e distros em ebulição agitam o universo Linux
Como instalar o repositório do DBeaver no Ubuntu
Como instalar o Plex Media Server no Ubuntu
Digitando underscore com "shift" + "barra de espaços"
Como ativar a lixeira e recuperar aquivos deletados em um servidor Linux
Como mudar o nome de dispositivos Bluetooth via linha de comando
dpkg: erro: gatilho de arquivo duplicado chamado pelo arquivo de nome (6)
Instalação não está resolvendo as dependencias (2)
Captação de áudio no zorin linux começa a diminuir com o tempo (5)
Alternativas ao Multilogin para gerenciamento de múltiplas contas/prof... (0)









