Tag: SO2 – 2021 – Ficha 6 v.2.4 – Memoria Partilhada + Sincronizaao II.pdf
sessão 6 – Memória partilhada / Sincronização – II Memória partilhada e Semáforos
Bibliografia de apoio:
Capítulos 5, 6, 7 e 8 do Livro Windows System Programming (da bibliografia) (149-155, 194-195, 230-231, 285-287)
MSDN:
Synchronization Objects https://docs.microsoft.com/pt-pt/windows/win32/sync/synchronization-objects
Synchronization Objects (inclui semáforos) https://docs.microsoft.com/pt-pt/windows/win32/sync/synchronization-objects
Wait Functions https://msdn.microsoft.com/en-us/library/windows/desktop/ms687069(v=vs.85).aspx
Time Functions https://docs.microsoft.com/en-us/windows/win32/sysinfo/time-functions
Named Shared Memory https://docs.microsoft.com/en-us/windows/win32/memory/creating-named-shared-memory
A memória partilhada entre diferentes processos, e é controlado através de um Mutex
A memória partilhada:
é uma zona de memória que pode ser acedida por um ou mais processo, ou threads, em paralelo
o acesso normalmente é controlado com recurso a um semáforo (mutex), ou outro mecanismo de sincronização / exclusão mutua
O mapeamento de ficheiros em memória:
usa-se para facilitar o acesso a ficheiros
o ficheiro comporta-se como uma zona de memória de acesso comum, como se fosse um array partilhado entre processos
CreateFile (abrir o ficheiro),
CreateFileMapping (mapear o ficheiro em memória),
MapViewOfFile (criar uma vista do ficheiro ou parte dele),
FlushViewOfFile (sincronizar memória e ficheiro),
UnmapViewOfFile (terminar vista do ficheiro),
CloseHandle (usado para terminar o mapping e fechar o ficheiro
A memória partilhada:
CreateFileMapping (mapear o ficheiro em memória, criar zona de memória),
OpenFileMapping (obter um ponteiro para zona de memória já criada),
MapViewOfFile (criar uma vista do ficheiro ou parte dele, cada processo cria a sua vista para poder trabalhar),
FlushViewOfFile (sincronizar memória e ficheiro),
UnmapViewOfFile (terminar vista do ficheiro),
CloseHandle (usado para terminar o mapping e fechar o ficheiro
outras funções:
GetSystemInfo
CopyMemory
#include <Windows.h>
#include <tchar.h>
#include <math.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
int _tmain(int argc, TCHAR* argv[]) {
HANDLE hMapeamentoFicheiro, hFicheiro;
char* pBuffer, aux;
TCHAR auxt;
#ifdef UNICODE
_setmode(_fileno(stdin), _O_WTEXT);
_setmode(_fileno(stdout), _O_WTEXT);
_setmode(_fileno(stderr), _O_WTEXT);
#endif
//criar o ficheiro
hFicheiro = CreateFile(
TEXT("letras.txt"),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if(hFicheiro == INVALID_HANDLE_VALUE)
{
_tprintf(TEXT("Erro a abrir o ficheiro - CreateFile (%d)\n"), GetLastError());
return 1;
}
//o mapeamento
hMapeamentoFicheiro = CreateFileMapping(hFicheiro, NULL, PAGE_READWRITE, 0, 26, NULL);
if(hMapeamentoFicheiro == NULL){
_tprintf(TEXT("Erro no file map (%d)\n"), GetLastError());
CloseHandle(hFicheiro);
}
//a vista
pBuffer = (char*)MapViewOfFile(
hMapeamentoFicheiro,
FILE_MAP_READ | FILE_MAP_WRITE,
0,
0,
26
); //26 bytes, do tamanho da memória partilhada
if(pBuffer == NULL)
{
_tprintf(TEXT("Erro ao criar view da memoria partilada (erro %d)\n"), GetLastError());
CloseHandle(hMapeamentoFicheiro);
CloseHandle(hFicheiro);
return 1;
}
_tprintf(TEXT("A modificar o ficheiro em memoria.\n"));
for(unsigned int i = 0; i <13; i++)
{
aux = pBuffer[i];
pBuffer[i] = pBuffer[25 - i];
pBuffer[25 - i] = aux;
}
_tprintf(TEXT("Ficheiro por ordem inversa em memoria.\n"));
for(unsigned int i=0; i< 26; i++)
{
_tprintf(TEXT("%c"), pBuffer[i]);
}
UnmapViewOfFile(pBuffer);
CloseHandle(hMapeamentoFicheiro);
CloseHandle(hFicheiro);
return 0;
}
um programa que recebe input de um utilizador
o programa escreve em memoria partilhada o que o utilizador escreve
o programa tem uma thread que esta sempre a tentar ler da memoria partilhada
e assim todos os outros programas leem essas mensagens
o acesso à memoria partilhada é controlado pelo mutex
o utilizador só escreve se o semáforo permitir
o controlo de entrada não pode ser feito com mutex, porque só deixa entrar um (é binário o controlo)
assim o mecanismo a usar é o semáforo (pode funcionar como uma pilha).
funções:
CreateSemaphore, OpenSemaphore, WaitForSingleObject, CloseHandle
#include <Windows.h>
#include <tchar.h>
#include <math.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#define SEM_BOUNCER_NAME TEXT("SEMBOUNCER") //nome do semáforo
#define MAXUSERS 3 //numero de processo que vão passar no semáforo
typedef struct _ControlData{ //tipo de estrutura de dados de controlo
HANDLE hSemBouncer; //semáforo
} CData;
int _tmain(int argc, TCHAR* argv[]) {
HANDLE sem; // Handle do semáforo
CData cdata; //estrutura de dados de controlo
#ifdef UNICODE
_setmode(_fileno(stdin), _O_WTEXT);
_setmode(_fileno(stdout), _O_WTEXT);
_setmode(_fileno(stderr), _O_WTEXT);
#endif
cdata.hSemBouncer = CreateSemaphore(
NULL, //atributo de segurança
MAXUSERS, //começa o programa logo com o max users
MAXUSERS, //limite de users
SEM_BOUNCER_NAME //nome do semáforo
);
if(cdata.hSemBouncer == NULL)
{
_tprintf(TEXT("\nerro a criar semáforo"));
return FALSE;
}else
{
_tprintf(TEXT("Semáforo criado\n"));
}
cdata.hSemBouncer = OpenSemaphore( //abrir o semáforo
SYNCHRONIZE | SEMAPHORE_MODIFY_STATE,
FALSE,
SEM_BOUNCER_NAME
);
if(cdata.hSemBouncer == NULL)
{
_tprintf(TEXT("Problema na abertura do Semáforo (%d),\n"), GetLastError());
return FALSE;
}else
{
_tprintf(TEXT("Semáforo aberto.\n"));
}
_tprintf(TEXT("Vou aguardar no semáforo para entrar\n"));
WaitForSingleObject(cdata.hSemBouncer, INFINITE);
_tprintf(TEXT("Entrei. Qualquer tecla para continuar\n"));
_gettch();
ReleaseSemaphore(cdata.hSemBouncer, 1, NULL);
_tprintf(TEXT("Semáforo libertado\n"));
CloseHandle(cdata.hSemBouncer);
return 0;
}
#include <Windows.h>
#include <tchar.h>
#include <math.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#define SEM_BOUNCER_NAME TEXT("SEMBOUNCER") //nome do semáforo
#define MAXUSERS 3 //numero de processo que vão passar no semáforo
#define SHM_NAME TEXT("fmMsgSpace") //nome da memória
#define MUTEX_NAME TEXT("RWMUTEX") //nome do mutex
#define MSGTEXT_SZ 100 //tamanho máximo das mensagens
#define MSG_DELAY 500 //intervalo para leitura das mensagens pelos clientes
typedef struct _MSG{
TCHAR szMessagem[MSGTEXT_SZ];
} Shared_MSG;
typedef struct _ControlData{ //tipo de estrutura de dados de controlo
HANDLE hSemBouncer; //semáforo
//para o mutex
HANDLE hMapFile, hRWMutex;
Shared_MSG* shared; // ponteiro para memoria partilhada
HANDLE newmsg; //ponteiro para o evento
int continuar; // vairvel para terminar as threads
} CData;
//função que lê do teclado e envia para memoria partilhada
void le_envia(CData * pcd)
{
Shared_MSG msg; //estrutura local
while(pcd->continuar)
{
_tprintf(TEXT("Escreve mensagem (fim para sair)"));
wscanf_s(TEXT("%s"), msg.szMessagem, (unsigned)_countof(msg.szMessagem));
//_tprintf(TEXT("%s\n"), msg.szMessagem);
if(_tcscmp(msg.szMessagem, TEXT("fim"))==0)
{
break;
}
WaitForSingleObject(pcd->hRWMutex, INFINITE);
CopyMemory(pcd->shared, &msg, sizeof(Shared_MSG));
ReleaseMutex(pcd->hRWMutex);
//assinlar que há nova mensagem
SetEvent(pcd->newmsg);
//esperar que mensagem seja lida por outros processos
Sleep(MSG_DELAY);
//desativar evento
ResetEvent(pcd->newmsg);
}
pcd->continuar = 0;
_tprintf(TEXT("\nPrograma vai terminar"));
//para desbloquear a outra thread e sair de imediato
SetEvent(pcd->newmsg);
}
DWORD WINAPI recebe_msg(LPVOID p)
{
CData* pcd = (CData*)p;
Shared_MSG msg;
while(1)
{
WaitForSingleObject(pcd->newmsg, INFINITE); //aguardar evento
if(!pcd->continuar)
{
break;
}
WaitForSingleObject(pcd->hRWMutex, INFINITE); //obter mutex
CopyMemory(&msg, pcd->shared, sizeof(Shared_MSG));
ReleaseMutex(pcd->hRWMutex);
_tprintf(TEXT("Recebi: %s\n"), msg.szMessagem );
Sleep(MSG_DELAY * 2);
}
//no cao de haver outras thread, evento não fica ativo para elas quando esta thread termina
ResetEvent(pcd->newmsg);
return 0;
}
int _tmain(int argc, TCHAR* argv[]) {
HANDLE sem; // Handle do semáforo
CData cdata; //estrutura de dados de controlo
DWORD tid; //estrutura de dados de controlo
#ifdef UNICODE
_setmode(_fileno(stdin), _O_WTEXT);
_setmode(_fileno(stdout), _O_WTEXT);
_setmode(_fileno(stderr), _O_WTEXT);
#endif
cdata.hSemBouncer = CreateSemaphore(
NULL, //atributo de segurança
MAXUSERS, //começa o programa logo com o max users
MAXUSERS, //limite de users
SEM_BOUNCER_NAME //nome do semaforo
);
if(cdata.hSemBouncer == NULL)
{
_tprintf(TEXT("\nerro a criar semaforo"));
return FALSE;
}else
{
_tprintf(TEXT("Semáforo criado\n"));
}
cdata.hSemBouncer = OpenSemaphore( //abrir o semaforo
SYNCHRONIZE | SEMAPHORE_MODIFY_STATE,
FALSE,
SEM_BOUNCER_NAME
);
if(cdata.hSemBouncer == NULL)
{
_tprintf(TEXT("\nProblema na aberura do Semáforo (%d)"), GetLastError());
return FALSE;
}else
{
_tprintf(TEXT("Semáforo aberto.\n"));
}
_tprintf(TEXT("\nVou agurdar no semáforo para entrar"));
WaitForSingleObject(cdata.hSemBouncer, INFINITE);
//criar a zona de memória
cdata.hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
sizeof(Shared_MSG),
SHM_NAME
);
if (cdata.hMapFile == NULL)
{
_tprintf(TEXT("Problema em criar zona de memoria (%d),\n"), GetLastError());
return FALSE;
}
else
{
_tprintf(TEXT("\ncriada zona de memoria."));
}
//criar a zona de memória - a vista
cdata.shared = (Shared_MSG*)MapViewOfFile(
cdata.hMapFile,
FILE_MAP_ALL_ACCESS,
0,
0, //vista sobre a memoria inteira
sizeof(Shared_MSG)
);
if (cdata.shared == NULL)
{
_tprintf(TEXT("Problema em criar a vista (%d),\n"), GetLastError());
return FALSE;
}
else
{
_tprintf(TEXT("\ncriada a vista."));
}
//criar a zona de memória - o mutex (com um nome conhecido para todos os processos)
cdata.hRWMutex = CreateMutex(
NULL,
FALSE,
MUTEX_NAME
);
if (cdata.hRWMutex == NULL)
{
_tprintf(TEXT("Problema em criar o mutex (%d),\n"), GetLastError());
return FALSE;
}
else
{
_tprintf(TEXT("\nmutex criado."));
}
cdata.newmsg = CreateEvent(NULL, TRUE, FALSE, TEXT("Evento"));
cdata.newmsg = OpenEvent(SYNCHRONIZE | EVENT_MODIFY_STATE, TRUE, TEXT("Evento"));
if(cdata.newmsg == NULL)
{
_tprintf(TEXT("Erro ao criar evento %s (%d).\n"), TEXT("Evento"), GetLastError());
return FALSE;
}else
{
_tprintf(TEXT("\nEvento lançado com sucesso"));
}
_tprintf(TEXT("Lançar a thread para ouvir o que se passa\n"));
cdata.continuar = 1;
sem = CreateThread(NULL, 0, recebe_msg, &cdata, 0, &tid);
le_envia(&cdata);
_tprintf(TEXT("Este cliente vai fechar\n"));
WaitForSingleObject(sem, INFINITE);
_tprintf(TEXT("Thread ouvinte encerrada\n"));
ReleaseSemaphore(cdata.hSemBouncer, 1, NULL);
UnmapViewOfFile(cdata.shared); //memoria partilhada
CloseHandle(cdata.hMapFile);
CloseHandle(cdata.newmsg);
CloseHandle(cdata.hSemBouncer);
return 0;
}
esta é uma versão melhorada do exercício anterior, já que permite ter um “control” que vai recebendo pedidos de “aviões” e que dá resposta (caso seja positiva) a cada um dos “aviões”
pelo “control” surge o seguinte:
#include <Windows.h>
#include <tchar.h>
#include <math.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#define SEM_BOUNCER_NAME TEXT("SEMBOUNCER") //nome do semáforo
#define MAXUSERS 3 //numero de processo que vão passar no semáforo
#define SHM_NAME TEXT("fmMsgSpace") //nome da memória
#define MUTEX_NAME TEXT("RWMUTEX") //nome do mutex
#define MSGTEXT_SZ 100 //tamanho máximo das mensagens
#define MSG_DELAY 500 //intervalo para leitura das mensagens pelos clientes
typedef struct _MSG_AEROPORTO {
TCHAR szMessagem[MSGTEXT_SZ];
int pidMessagemControl; //aviao
int pidMessagemAviao; //areoporto
int comando; //0, semResposta, 1 pedido de aeroporto, 2, ok aeroporto, -1 , erro aeroporto
} Shared_MSG;
typedef struct _ControlData { //tipo de estrutura de dados de controlo
HANDLE hSemBouncer; //semáforo
//para o mutex
HANDLE hMapFile, hRWMutex;
Shared_MSG* shared; // ponteiro para memoria partilhada
HANDLE newmsg; //ponteiro para o evento
int continuar; // vairvel para terminar as threads
} CData;
//função que lê do teclado e envia para memoria partilhada
void le_envia(CData* pcd)
{
Shared_MSG msg; //estrutura local
while (pcd->continuar)
{
msg.pidMessagemControl = GetCurrentProcessId();
_tprintf(TEXT("\n[control: %d] Escreve mensagem (fim para sair)"), msg.pidMessagemControl);
wscanf_s(TEXT("%s"), msg.szMessagem, (unsigned)_countof(msg.szMessagem));
//_tprintf(TEXT("%s\n"), msg.szMessagem);
if (_tcscmp(msg.szMessagem, TEXT("fim")) == 0)
{
break;
}
WaitForSingleObject(pcd->hRWMutex, INFINITE);
CopyMemory(pcd->shared, &msg, sizeof(Shared_MSG)); //dest , source
ReleaseMutex(pcd->hRWMutex);
//assinlar que há nova mensagem
SetEvent(pcd->newmsg);
//esperar que mensagem seja lida por outros processos
Sleep(MSG_DELAY);
//desativar evento
ResetEvent(pcd->newmsg);
}
pcd->continuar = 0;
_tprintf(TEXT("\nPrograma vai terminar"));
//para desbloquear a outra thread e sair de imediato
SetEvent(pcd->newmsg);
}
DWORD WINAPI recebe_msg(LPVOID p)
{
CData* pcd = (CData*)p;
Shared_MSG msg;
TCHAR nome[MSGTEXT_SZ];
_tcscpy_s(nome, _countof(nome), _T("coimbra"));
while (1)
{
WaitForSingleObject(pcd->newmsg, INFINITE); //aguardar evento
if (!pcd->continuar)
{
break;
}
WaitForSingleObject(pcd->hRWMutex, INFINITE); //obter mutex
CopyMemory(&msg, pcd->shared, sizeof(Shared_MSG)); //dest , source
ReleaseMutex(pcd->hRWMutex);
if(msg.comando == 1){
_tprintf(TEXT("\nRecebi: %s do %d\n"), msg.szMessagem, msg.pidMessagemAviao);
if (wcscmp(msg.szMessagem, _T("coimbra")) == 0)
{
_tprintf(TEXT("\nSenhor aviao existe esse aeroporto.. volte sempre %d!"), msg.pidMessagemAviao);
pcd->shared->pidMessagemAviao = msg.pidMessagemAviao;
pcd->shared->comando = 2;
//Sleep(MSG_DELAY);
}else
{
pcd->shared->comando = -1;
}
}else
{
_tprintf(TEXT("\nAguardo por um pedido formal"));
pcd->shared->comando = -1;
}
Sleep(MSG_DELAY * 2);
pcd->shared->comando = -1;
}
//no cao de haver outras thread, evento não fica ativo para elas quando esta thread termina
ResetEvent(pcd->newmsg);
return 0;
}
BOOL comunicaAeroporto(BOOL valor)
{
HANDLE sem; // Handle do semáforo
CData cdata; //estrutura de dados de controlo
DWORD tid; //estrutura de dados de controlo
#ifdef UNICODE
_setmode(_fileno(stdin), _O_WTEXT);
_setmode(_fileno(stdout), _O_WTEXT);
_setmode(_fileno(stderr), _O_WTEXT);
#endif
cdata.hSemBouncer = CreateSemaphore(
NULL, //atributo de segurança
MAXUSERS, //começa o programa logo com o max users
MAXUSERS, //limite de users
SEM_BOUNCER_NAME //nome do semaforo
);
if (cdata.hSemBouncer == NULL)
{
_tprintf(TEXT("\nerro a criar semaforo"));
return FALSE;
}
else
{
_tprintf(TEXT("\nSemáforo criado"));
}
cdata.hSemBouncer = OpenSemaphore( //abrir o semaforo
SYNCHRONIZE | SEMAPHORE_MODIFY_STATE,
FALSE,
SEM_BOUNCER_NAME
);
if (cdata.hSemBouncer == NULL)
{
_tprintf(TEXT("\nProblema na aberura do Semáforo (%d)"), GetLastError());
return FALSE;
}
else
{
_tprintf(TEXT("\nSemáforo aberto."));
}
_tprintf(TEXT("\nVou agurdar no semáforo para entrar"));
WaitForSingleObject(cdata.hSemBouncer, INFINITE);
//criar a zona de memória
cdata.hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
sizeof(Shared_MSG),
SHM_NAME
);
if (cdata.hMapFile == NULL)
{
_tprintf(TEXT("\nProblema em criar zona de memoria (%d),"), GetLastError());
return FALSE;
}
else
{
_tprintf(TEXT("\ncriada zona de memoria."));
}
//criar a zona de memória - a vista
cdata.shared = (Shared_MSG*)MapViewOfFile(
cdata.hMapFile,
FILE_MAP_ALL_ACCESS,
0,
0, //vista sobre a memoria inteira
sizeof(Shared_MSG)
);
if (cdata.shared == NULL)
{
_tprintf(TEXT("\nProblema em criar a vista (%d),"), GetLastError());
return FALSE;
}
else
{
_tprintf(TEXT("\ncriada a vista."));
}
//criar a zona de memória - o mutex (com um nome conhecido para todos os processos)
cdata.hRWMutex = CreateMutex(
NULL,
FALSE,
MUTEX_NAME
);
if (cdata.hRWMutex == NULL)
{
_tprintf(TEXT("\nProblema em criar o mutex (%d),"), GetLastError());
return FALSE;
}
else
{
_tprintf(TEXT("\nmutex criado."));
}
cdata.newmsg = CreateEvent(NULL, TRUE, FALSE, TEXT("Evento"));
cdata.newmsg = OpenEvent(SYNCHRONIZE | EVENT_MODIFY_STATE, TRUE, TEXT("Evento"));
if (cdata.newmsg == NULL)
{
_tprintf(TEXT("\nErro ao criar evento %s (%d)."), TEXT("Evento"), GetLastError());
return FALSE;
}
else
{
_tprintf(TEXT("\nEvento lançado com sucesso"));
}
_tprintf(TEXT("\nLançar a thread para ouvir o que se passa"));
cdata.continuar = 1;
sem = CreateThread(NULL, 0, recebe_msg, &cdata, 0, &tid);
le_envia(&cdata);
_tprintf(TEXT("\nEste cliente vai fechar"));
WaitForSingleObject(sem, INFINITE);
_tprintf(TEXT("\nThread ouvinte encerrada"));
ReleaseSemaphore(cdata.hSemBouncer, 1, NULL);
UnmapViewOfFile(cdata.shared); //memoria partilhada
CloseHandle(cdata.hMapFile);
CloseHandle(cdata.newmsg);
CloseHandle(cdata.hSemBouncer);
valor = TRUE;
return valor;
}
int _tmain(int argc, TCHAR* argv[]) {
BOOL entra = FALSE;
while (entra == FALSE)
{
entra = comunicaAeroporto(FALSE);
}
}
pelo “aviao” surge o seguinte:
#include <Windows.h>
#include <tchar.h>
#include <math.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#define SEM_BOUNCER_NAME TEXT("SEMBOUNCER") //nome do semáforo
#define MAXUSERS 3 //numero de processo que vão passar no semáforo
#define SHM_NAME TEXT("fmMsgSpace") //nome da memória
#define MUTEX_NAME TEXT("RWMUTEX") //nome do mutex
#define MSGTEXT_SZ 100 //tamanho máximo das mensagens
#define MSG_DELAY 500 //intervalo para leitura das mensagens pelos clientes
typedef struct _MSG_AEROPORTO {
TCHAR szMessagem[MSGTEXT_SZ];
int pidMessagemControl; //aviao
int pidMessagemAviao; //areoporto
int comando; //0, semResposta, 1 pedido de aeroporto, 2, ok aeroporto, -1 , erro aeroporto
} Shared_MSG;
typedef struct _ControlData { //tipo de estrutura de dados de controlo
HANDLE hSemBouncer; //semáforo
//para o mutex
HANDLE hMapFile, hRWMutex;
Shared_MSG* shared; // ponteiro para memoria partilhada
HANDLE newmsg; //ponteiro para o evento
int continuar; // vairvel para terminar as threads
} CData;
//função que lê do teclado e envia para memoria partilhada
void le_envia(CData* pcd)
{
Shared_MSG msg; //estrutura local
while (pcd->continuar)
{
msg.pidMessagemAviao = GetCurrentProcessId();
if (_tcscmp(msg.szMessagem, TEXT("fim")) == 0 || (pcd->shared->pidMessagemAviao == GetCurrentProcessId() && pcd->shared->comando == 2))
{
_tprintf(TEXT("\ndone.."));
break;
}
_tprintf(TEXT("\n[aviao: %d]Escreve mensagem (fim para sair)"), msg.pidMessagemAviao);
wscanf_s(TEXT("%s"), msg.szMessagem, (unsigned)_countof(msg.szMessagem));
//_tprintf(TEXT("%s\n"), msg.szMessagem);
msg.comando = 1;
WaitForSingleObject(pcd->hRWMutex, INFINITE);
CopyMemory(pcd->shared, &msg, sizeof(Shared_MSG)); //dest , source
ReleaseMutex(pcd->hRWMutex);
//assinlar que há nova mensagem
SetEvent(pcd->newmsg);
//esperar que mensagem seja lida por outros processos
Sleep(MSG_DELAY);
//desativar evento
ResetEvent(pcd->newmsg);
}
pcd->continuar = 0;
_tprintf(TEXT("\nPrograma vai terminar"));
//para desbloquear a outra thread e sair de imediato
SetEvent(pcd->newmsg);
}
DWORD WINAPI recebe_msg(LPVOID p)
{
CData* pcd = (CData*)p;
Shared_MSG msg;
while (1)
{
WaitForSingleObject(pcd->newmsg, INFINITE); //aguardar evento
if (!pcd->continuar)
{
break;
}
WaitForSingleObject(pcd->hRWMutex, INFINITE); //obter mutex
CopyMemory(&msg, pcd->shared, sizeof(Shared_MSG)); //dest , source
ReleaseMutex(pcd->hRWMutex);
if(msg.pidMessagemAviao == GetCurrentProcessId()){
_tprintf(TEXT("\nProblemas com o nome do aeroporto"));
msg.comando = 1;
}else
{
_tprintf(TEXT("\n.."));
//_tprintf(TEXT("\nRecebi: %s do %d"), msg.szMessagem, msg.pidMessagemControl);
}
Sleep(MSG_DELAY * 2);
}
//no cao de haver outras thread, evento não fica ativo para elas quando esta thread termina
ResetEvent(pcd->newmsg);
return 0;
}
BOOL comunicaAeroporto(BOOL valor)
{
HANDLE sem; // Handle do semáforo
CData cdata; //estrutura de dados de controlo
DWORD tid; //estrutura de dados de controlo
#ifdef UNICODE
_setmode(_fileno(stdin), _O_WTEXT);
_setmode(_fileno(stdout), _O_WTEXT);
_setmode(_fileno(stderr), _O_WTEXT);
#endif
cdata.hSemBouncer = CreateSemaphore(
NULL, //atributo de segurança
MAXUSERS, //começa o programa logo com o max users
MAXUSERS, //limite de users
SEM_BOUNCER_NAME //nome do semaforo
);
if (cdata.hSemBouncer == NULL)
{
_tprintf(TEXT("\nerro a criar semaforo"));
return FALSE;
}
else
{
_tprintf(TEXT("Semáforo criado\n"));
}
cdata.hSemBouncer = OpenSemaphore( //abrir o semaforo
SYNCHRONIZE | SEMAPHORE_MODIFY_STATE,
FALSE,
SEM_BOUNCER_NAME
);
if (cdata.hSemBouncer == NULL)
{
_tprintf(TEXT("\nProblema na aberura do Semáforo (%d)"), GetLastError());
return FALSE;
}
else
{
_tprintf(TEXT("Semáforo aberto.\n"));
}
_tprintf(TEXT("\nVou agurdar no semáforo para entrar"));
WaitForSingleObject(cdata.hSemBouncer, INFINITE);
//criar a zona de memória
cdata.hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
sizeof(Shared_MSG),
SHM_NAME
);
if (cdata.hMapFile == NULL)
{
_tprintf(TEXT("Problema em criar zona de memoria (%d),\n"), GetLastError());
return FALSE;
}
else
{
_tprintf(TEXT("\ncriada zona de memoria."));
}
//criar a zona de memória - a vista
cdata.shared = (Shared_MSG*)MapViewOfFile(
cdata.hMapFile,
FILE_MAP_ALL_ACCESS,
0,
0, //vista sobre a memoria inteira
sizeof(Shared_MSG)
);
if (cdata.shared == NULL)
{
_tprintf(TEXT("Problema em criar a vista (%d),\n"), GetLastError());
return FALSE;
}
else
{
_tprintf(TEXT("\ncriada a vista."));
}
//criar a zona de memória - o mutex (com um nome conhecido para todos os processos)
cdata.hRWMutex = CreateMutex(
NULL,
FALSE,
MUTEX_NAME
);
if (cdata.hRWMutex == NULL)
{
_tprintf(TEXT("Problema em criar o mutex (%d),\n"), GetLastError());
return FALSE;
}
else
{
_tprintf(TEXT("\nmutex criado."));
}
cdata.newmsg = CreateEvent(NULL, TRUE, FALSE, TEXT("Evento"));
cdata.newmsg = OpenEvent(SYNCHRONIZE | EVENT_MODIFY_STATE, TRUE, TEXT("Evento"));
if (cdata.newmsg == NULL)
{
_tprintf(TEXT("Erro ao criar evento %s (%d).\n"), TEXT("Evento"), GetLastError());
return FALSE;
}
else
{
_tprintf(TEXT("\nEvento lançado com sucesso"));
}
_tprintf(TEXT("Lançar a thread para ouvir o que se passa\n"));
cdata.continuar = 1;
sem = CreateThread(NULL, 0, recebe_msg, &cdata, 0, &tid);
le_envia(&cdata);
_tprintf(TEXT("Este cliente vai fechar\n"));
WaitForSingleObject(sem, INFINITE);
_tprintf(TEXT("Thread ouvinte encerrada\n"));
ReleaseSemaphore(cdata.hSemBouncer, 1, NULL);
UnmapViewOfFile(cdata.shared); //memoria partilhada
CloseHandle(cdata.hMapFile);
CloseHandle(cdata.newmsg);
CloseHandle(cdata.hSemBouncer);
valor = TRUE;
return valor;
}
int _tmain(int argc, TCHAR* argv[]) {
BOOL entra = FALSE;
while (entra == FALSE)
{
entra = comunicaAeroporto(FALSE);
}
_tprintf(TEXT("\ntou feliz... cara#######"));
return 0;
}

