Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > SharedMemory synchronization


Автор: sol78 5.4.2009, 17:45
Мне нужно организовать что то вроде shared memory  только под Виндовс для интер-процессинг.
После поисков в Гугле, использую File Mapping.  
Но ничего не нашла о реализации синхронизации между врайтером и ридером...
Т.е. как ридер дожен узнать, что есть дата.. и т.д.

Вот тут код, как лучше довести его до ума...:
Код

#ifndef _SHARED_MEMORY_
#define _SHARED_MEMORY_


#include <windows.h>
#include <stdio.h>
#include <conio.h>

#include <string>
using std::string;


class CSharedMemoryArea
{
public:
    CSharedMemoryArea(){}

    HRESULT CreateSharedMemoryArea(LPCSTR FileName);

    HRESULT    OpenSharedMemory(LPCSTR FileName);

    HRESULT DestroySharedMemoryArea ();

    void WriteOnSharedMemory(int data, int position);

    void ReadFromSharedMemory(int *data, int position);

private:
    HANDLE    m_hFile;
    LPINT    m_ipView,
        m_ipAux;  

};

#endif

Код

// ------------------------------------------------------
// Shared memory functions
// Sample file to create a Shared Memory area...
// ------------------------------------------------------

//#include <stdafx.h>

#include "SharedMemory.h"   


//________________________________________________________________
//
HRESULT CSharedMemoryArea::CreateSharedMemoryArea(LPCSTR FileName)
{

    m_hFile = CreateFileMapping(INVALID_HANDLE_VALUE, 
                                NULL,
                                PAGE_READWRITE, 
                                0, 
                                1024 * 4, 
                                FileName);
    if (m_hFile == NULL)
    {
         printf("Unable to create a file. Error %d", GetLastError());
         return 0; //@@
    }
    else 
    {
        if (GetLastError() == ERROR_ALREADY_EXISTS)
        {
            printf("A file was already created.Error %d", GetLastError());
            return 0;
        }
    }
    m_ipView = (LPINT) MapViewOfFile(m_hFile, 
                                     FILE_MAP_ALL_ACCESS,  
                                     0,
                                     0,
                                     0);
    if (m_ipView == NULL)
    {
         printf("Unable to create a VIEW.Error %d", GetLastError());
         return 0;
    }

    printf("Shared memory has been successfully created....\n");

    m_ipAux = m_ipView;
    return 1;
}    


//__________________________________________________________
//
HRESULT    CSharedMemoryArea::OpenSharedMemory(LPCSTR FileName)
{
   m_hFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, 
                           FALSE,
                           FileName);            
    if (m_hFile == NULL)
    {
         printf("Unable to open the shared area.\n");
         return 0;
    }

    m_ipView = (LPINT) MapViewOfFile(m_hFile, 
                                     FILE_MAP_ALL_ACCESS, //FILE_MAP_WRITE | FILE_MAP_READ, 
                                     0,
                                     0,
                                     0);
    if (m_ipView == NULL)
    {
         printf("Unable to create a VIEW. Error %d", GetLastError());
         return 0;
    }
    printf("Shared memory has been successfully openned....\n");

    m_ipAux = m_ipView;
    return S_OK;
}


//___________________________________________________
//
HRESULT CSharedMemoryArea::DestroySharedMemoryArea ()
{

    if (!UnmapViewOfFile(m_ipView)) 
    { 
       printf("Could not unmap view of file. Error %d ", GetLastError()); 
    } 
    
    CloseHandle(m_hFile); 
    
    printf("Shared memory has been successfully destroyed....\n");
    return 1;

}

//_________________________________________________________________
//
void CSharedMemoryArea::WriteOnSharedMemory(int data, int position)
{
    printf("Writing data on the shared area...\n");
    m_ipAux[position] = data;
}


//___________________________________________________________________
//
void CSharedMemoryArea::ReadFromSharedMemory(int *data, int position)
{
    printf("Reading data on the shared area...\n");
    *data = m_ipAux[position];
}

 
Reader
Код

// ------------------------------------------------------------
// User.cpp
//    This program uses a shared area
//      It should run AFTER the other program.
// ------------------------------------------------------------
#include <stdio.h>
#include "SharedMemory.h"

void main(int argc, char* argv[])
{
   int i, data;
   CSharedMemoryArea cSM;
   HRESULT             hr;
    
   hr = cSM.OpenSharedMemory("SharedFile");

    printf("Reading data from the shared memory area...\n");
    for (i=0; i< 100; i++) {
        cSM.ReadFromSharedMemory(&data, i);
        printf("Data[%d] = %3d\n", i, data);
    }
    printf("The reading is done.\n");
    cSM.DestroySharedMemoryArea ();
    printf("The End.");
}

Writer
Код

// ------------------------------------------------------------
// Creator.cpp
//    This program creates a shared area.
// ------------------------------------------------------------
#include <stdio.h>
#include <conio.h>
#include "SharedMemory.h"

void main(int argc, char* argv[])
{
   int i;
   CSharedMemoryArea cSM;
   HRESULT             hr;    
// creates the area to be shared
    
   hr = cSM.CreateSharedMemoryArea("SharedFile");

    printf("Writing data on the shared memory area...\n");
    for (i=0; i< 100; i++)
       cSM.WriteOnSharedMemory(i*2, i); // performs the writing

    printf("The writing is done.\n");
    printf("Now you can run the other program to read the shared area.\n");
    printf("When you want to close the shared area and finish this program...\n");
    printf("Just press a key.\n");

    
    _getch();
    cSM.DestroySharedMemoryArea (); 
    printf("The End.");
}


Автор: GoldFinch 5.4.2009, 19:01
для синхронизации процессов есть мъютексы
или переменная в общей памяти

Автор: sol78 5.4.2009, 19:08
можно пример реализации мутакса для данной задачи??
Что то я не пойму а кто сообщит врайтеру что есть дата?

Автор: xvr 5.4.2009, 22:23
Одного мьютекса не хватит. Кроме того непонятен протокол обмена данными через эту shared memory. Какие данные, какими порциями должны передаваться?
Тут явно понадобится мьютекс, евент или семафор и общие переменные в этой самой разделяемой памяти

Автор: sol78 5.4.2009, 23:20
xvr, протокол сравнительно простой. Один поток пишет данные в память и читаем другим потоком, читаем и записываем одинаковыми порциями сравнительно не большими. Важна скорость и синхронизация.  
У меня есть ридер и врайтер (2 потока). Когда у врайтера появляеся дата, он выбрасывает ивент. Ридер тем временим жидает это сыбытие. Читает данные .... а что дальше где синхронизировать дальше...??? 

Автор: asd 6.4.2009, 08:19
CreateNamedPipe вам поможет.

Автор: GoldFinch 6.4.2009, 08:35
asd, так же можно слать через сокет или по POP3 на почту

Добавлено через 1 минуту и 6 секунд
Цитата(sol78 @  6.4.2009,  00:20 Найти цитируемый пост)
Когда у врайтера появляеся дата, он выбрасывает ивент. Ридер тем временим жидает это сыбытие. Читает данные .... а что дальше где синхронизировать дальше...???  

смысле что дальше? дальше ридер обрабатывает данные и ждет новых

Автор: xvr 6.4.2009, 10:20
Цитата(sol78 @ 5.4.2009,  23:20)
xvr, протокол сравнительно простой. Один поток пишет данные в память и читаем другим потоком, читаем и записываем одинаковыми порциями сравнительно не большими. Важна скорость и синхронизация.  

Т.е. вам нужна очередь пакетов фиксированной длинны. Я правильно понял?
Цитата

У меня есть ридер и врайтер (2 потока). Когда у врайтера появляеся дата, он выбрасывает ивент. Ридер тем временим жидает это сыбытие. Читает данные .... а что дальше где синхронизировать дальше...???
Дальше обрабатывает и снова ждет.
Система распадается на 2 практически независимые части - очередь (с доступом из 2х процессов) и система посылки сообщений.
Очередь организуется в виде кольцевого буфера. Все манипуляции с ней (добавление и удаление пакетов) делаются под закрытым мьютексом
Синхронизация делается в виде 2х семафоров. Один контролирует пустое пространство в очереди и его начальное значение - размер очереди в пакетах. Второй считает количество пакетов в очереди, его начальное значение - 0
Добавление пакета:
  •  Захватываем первый семафор
  •  Добавляем пакет
  •  Освобождаем второй семафор
Чтение пакета:
  •  Захватываем второй семафор
  •  Читаем пакет
  •  Освобождаем первый семафор



Автор: sol78 6.4.2009, 11:21
xvr, спасибо за доступное обьяснение...
Да но я пишу под Windows, подскажите плиз  что можно использовать для реализации семафоров в Windows.
Как мутех можно использовать Критикал Секшн?

Автор: xvr 6.4.2009, 12:37
Цитата(sol78 @ 6.4.2009,  11:21)
xvr, спасибо за доступное обьяснение...
Да но я пишу под Windows, подскажите плиз  что можно использовать для реализации семафоров в Windows.

Семафоры  smile См. CreateSemaphore, OpenSemaphore
Цитата

Как мутех можно использовать Критикал Секшн?
Нет, они только в пределах процесса. См. CreateMutex, OpenMutex

Автор: Alca 6.4.2009, 13:10
Цитата

Семафоры   См. CreateSemaphore, OpenSemaphore

Код

/****************************************************************************
*    Класс: CXSemaphore (CXSemaphore.h)
*
*****************************************************************************/


#ifndef CXSemaphoreH
#define CXSemaphoreH
//---------------------------------------------------------------------------
#include <iostream>
#include <windows.h>
#include <process.h>
#include <assert.h>
//---------------------------------------------------------------------------
class CXSemaphore {
    public:
               CXSemaphore          ();
               CXSemaphore          (PSECURITY_ATTRIBUTES lpsaAttributes, LONG nInitialCount, LONG nMaxCount, LPCSTR pszName);
              ~CXSemaphore          ();
        HANDLE hGetHandle           ();
        BOOL   bCreate              (PSECURITY_ATTRIBUTES lpsaAttributes, LONG nInitialCount, LONG nMaxCount, LPCSTR pszName);
        BOOL   bOpen                (DWORD dwAccess, BOOL bInheritHandle, LPCSTR lpszName);
        BOOL   bRelease             (LONG nReleaseCount, LONG *pnOldCount);
        DWORD  dwWaitForSingleObject(DWORD dwTimeout);

    private:
        HANDLE m_hSemaphore;
};
//---------------------------------------------------------------------------
#endif

/****************************************************************************
*    Класс: CXSemaphore (CXSemaphore.cpp
*
*****************************************************************************/


#include "CXSemaphore.h"
//---------------------------------------------------------------------------
CXSemaphore::CXSemaphore() {
    m_hSemaphore = NULL;
}
//---------------------------------------------------------------------------
CXSemaphore::CXSemaphore(PSECURITY_ATTRIBUTES lpsaAttributes = NULL, LONG nInitialCount = 1, LONG nMaxCount = 1, LPCSTR lpszName = NULL) {
    m_hSemaphore = NULL;
    
    BOOL bSuccess = FALSE; 
    bSuccess = bCreate(lpsaAttributes, nInitialCount, nMaxCount, lpszName);
    if (FALSE == bSuccess) {
        return;
    }
}
//---------------------------------------------------------------------------
CXSemaphore::~CXSemaphore() {
    if (NULL != m_hSemaphore) {
        ::CloseHandle(m_hSemaphore);    m_hSemaphore = NULL;
    }
}
//---------------------------------------------------------------------------
HANDLE CXSemaphore::hGetHandle() {
    assert(NULL != m_hSemaphore);
    
    return m_hSemaphore;
}
//---------------------------------------------------------------------------
BOOL CXSemaphore::bCreate(LPSECURITY_ATTRIBUTES lpsaAttributes, LONG nInitialCount, LONG nMaxCount, LPCSTR lpszName) {
    m_hSemaphore = ::CreateSemaphore(lpsaAttributes, nInitialCount, nMaxCount, lpszName);

    return (m_hSemaphore != NULL );
}
//---------------------------------------------------------------------------
BOOL CXSemaphore::bOpen(DWORD dwAccess, BOOL bInheritHandle, LPCSTR lpszName) {
    assert(NULL != m_hSemaphore);
    
    ::OpenSemaphore(dwAccess, bInheritHandle, lpszName);
    
    return (m_hSemaphore != NULL);
}
//---------------------------------------------------------------------------
BOOL CXSemaphore::bRelease(LONG nReleaseCount = 1, LONG *pnOldCount = NULL ) {
    assert(NULL != m_hSemaphore);

    return (::ReleaseSemaphore(m_hSemaphore, nReleaseCount, pnOldCount));
}
//---------------------------------------------------------------------------
DWORD CXSemaphore::dwWaitForSingleObject(DWORD dwTimeout = INFINITE) {
    assert(NULL != m_hSemaphore);

    return (::WaitForSingleObject(m_hSemaphore, dwTimeout));
}
//---------------------------------------------------------------------------
)

Автор: sol78 6.4.2009, 13:11
Вот пимерно что получается:
Код

//_________________________________________________________________
//
void CSharedMemoryArea::WriteOnSharedMemory(int data, int position)
{
    DWORD dwRetCode = WaitForSingleObject(m_hPackageCounter, TIME_OUT);
    
    if (dwRetCode == WAIT_TIMEOUT)    // The defined timeout has elapsed?
    {
        printf("");

        return;
    }
    else // Add data packege to our shared memory:
    {

        // Increment the Package counter:
        if (!ReleaseSemaphore(m_hPackageCounter,
                              1,    // increase the counter by one packege
                              NULL) )  // not interested in previous count
        {
            printf("ReleaseSemaphore error: %d\n", GetLastError());
        }
        printf("Writing data on the shared area...\n");
//        m_piAux[position] = data;
    }    
    //@@@
}


//___________________________________________________________________
//
void CSharedMemoryArea::ReadFromSharedMemory(int *data, int position)
{
    DWORD dwRetCode = WaitForSingleObject(m_hFreeSpaceCouter, TIME_OUT);
    
    if (dwRetCode == WAIT_TIMEOUT)    // The defined timeout has elapsed?
    {
        printf("");

        return;
    }
    else // Add data packege to our shared memory:
    {
        //Increment the Free Space Counter:
        if (!ReleaseSemaphore(m_hFreeSpaceCouter,
                              -1,    // decrease the counter by one packege
                              NULL) )  // not interested in previous count
        {
            printf("ReleaseSemaphore error: %d\n", GetLastError());
        }
        
        printf("Reading data on the shared area...\n");
//        *data = m_piAux[position];
    }
    //@@@
}

Как реализовать 'Освобождаем первый семафор' ?

Автор: Alca 6.4.2009, 13:13
Цитата

Как реализовать 'Освобождаем первый семафор' ?

::ReleaseSemaphore

Автор: xvr 6.4.2009, 13:37
В CSharedMemoryArea::WriteOnSharedMemory WaitForSingleObject нужно делать на m_hFreeSpaceCouter, а в CSharedMemoryArea::ReadFromSharedMemory на m_hPackageCounter
И не забыть при создании установить счетчик m_hFreeSpaceCouter в максимальное количество пакетов (иначе будет deadlock)

Автор: asd 6.4.2009, 18:16
Цитата(GoldFinch @  6.4.2009,  08:35 Найти цитируемый пост)
 так же можно слать через сокет или по POP3 на почту

B чем же вам пайпы не угодили? И что общего у них с сокетами и уж тем более с протоколом, который на них основан?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)