Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Komunikacja między procesami - Shared memory

megaman123 25 Sie 2010 18:18 1200 10
  • #1 25 Sie 2010 18:18
    megaman123
    Poziom 13  

    Cześć,

    Otóż pracuję nad projektem pisanym w c++ , którego założeniem jest uruchamianie n-instancji danej aplikacji w której każda wykonuję część pomiarów. Okresowo , trzeba się do nich dostać, odczytywać i uśredniać wyliczone dane.

    Wpadłem na pomysł użycia "Shared memory" , które tworzyłby "root" i rozdzielał bloki pamięci pomiędzy instancje. Teraz pytanie ! Każdy program może tworzyć w ramach potrzeby tablice dynamicznie , a całość zamknięta jest w jednej klasie zawierająca wiele danych , o wielu typach. Pod .NET'em pewnie użyłbym serializacji w bardzo prosty sposób , ale tutaj wydaje się to nie możliwe.

    Podsumowując : Zna ktoś jakiś "sprytny" pomysł ,żeby przełożyć obiekt takiej klasy na ten surowy obszar pamięci ?

    0 10
  • #2 25 Sie 2010 18:36
    Dżyszla
    Poziom 42  

    Utwórz własną metodę serializującą ;) Wbrew pozorom to jest całkiem proste, a z punktu programistycznego - całkiem bezpieczne rozwiązanie (bezpieczniejsze niż wyszukiwanie bloków pamięci, gdzie znajduje się obiekt).

    0
  • #3 26 Sie 2010 07:56
    megaman123
    Poziom 13  

    Dzięki za odpowiedź !

    Troszkę narazie nie jestem sobie w stanie tego wyobrazić, tzn. szczególnie tablic dynamicznych. W tym przypadku powinienem stworzyć dodatkowe zmienne informujące o rozmiarze tych tablic, racja ?

    Czy nie znasz jakiegoś kompletnego przykładu, na którym mógłbym się oprzeć ?

    0
  • #4 26 Sie 2010 20:09
    Dżyszla
    Poziom 42  

    (pseudokodem trochę)

    Code:

    class J
    {
        private:
                 int tablica[];
                 char znak;
        public:
               string serialize;
               void unserialize(string t);
    }

    J.serialize
    {
        result=count(tablica)+';';
        for(i=0;i<count(tablica);i++)
             result=result+tablica[i].toString+';'
         result=result+znak;
    }
    J.unserialize(string t)
    {
       int size=0;
        int w=0;
        for (;w<length(t);w++)
        {
              if (t[w]=';') break;
              size=size*10+t[w].toInt;
         }
        setLength(tablica,size);
        for (int i=0;i<size;i++)
        {
           int c=0;
            for (int i=w+1;;i++)
            {
                 if (t[i]=';') break;
                 c=c*10+t[i].toString;
            }
            tablica[i]=c;
         }
         w=i+1;
         znak=t[w];
    }
    Proszę.

    0
  • #5 27 Sie 2010 07:40
    megaman123
    Poziom 13  

    Rozumiem. A powiedz mi , czy nie można by tego zrobić w taki sposób ?

    Code:

    J.serialize
    {
            char* Memory = new char[sizeof(J)];
            memcpy(Memory ,this,sizeof(J));

            return Memory ;
    }

    0
  • #6 27 Sie 2010 16:52
    Dżyszla
    Poziom 42  

    pod warunkiem, że klasa nie będzie zawierać:
    1. metod (one raczej do niczego Ci nie potrzebne - to byłoby marnotrastwo pamięci)
    2. innych obiektów lub osobno alokowanych bloków pamięci (tak się do nich nie dostaniesz)
    3. Chyba niejawny parametr this miałby niepoprawną wartość. A poza tym nie wiem, czy cos jeszcze nie siedzi w pamięci związanego z danym obiektem.

    0
  • #7 27 Sie 2010 22:41
    beluosus
    Poziom 25  

    Dżyszla napisał:
    pod warunkiem, że klasa nie będzie zawierać:
    1. metod (one raczej do niczego Ci nie potrzebne - to byłoby marnotrastwo pamięci)
    2. innych obiektów lub osobno alokowanych bloków pamięci (tak się do nich nie dostaniesz)

    1. Oczywiście, że może zawierać metody (chyba że wirtualne, wtedy dochodzi vtable). Funkcje wszystkich obiektów danej klasy są w pamięci tylko raz.
    2. Jeżeli nie ma obiektów to w sumie nic nie ma...

    Ja serializację wykonuję mniej więcej w taki sposób (naskrobane na szybko), chociaż zazwyczaj danymi są listy albo wektory, a operuję na ostream. Tam jest write i nie trzeba przesuwać wskaźnika co wygląda nieczytelnie. BTW istnieje biblioteka dla c++ umożliwiające serializację: http://s11n.net/

    Code:
    HEAP SUMMARY:
    
        in use at exit: 0 bytes in 0 blocks
      total heap usage: 7 allocs, 7 frees, 119 bytes allocated

    All heap blocks were freed -- no leaks are possible

    For counts of detected and suppressed errors, rerun with: -v
    ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 19 from 8)

    Więc kod wydaje się w miarę prawidłowy. :)

    0
  • #8 29 Sie 2010 08:45
    megaman123
    Poziom 13  

    Cześć, dzięki wszystkim za pomoc ;-)

    Co do "własnoręcznej" serializcji , mam jeszcze jedno pytanie. Jak metoda z memcpy ma się do dziedziczenia ? W sensie pseudokodem :

    Code:
    class X
    
    {
    int a;
    char tab[50];
    }

    class Z : X
    {
    int tab_mem[100];
    }

    class Y : Z
    {
    double tab_x[4];
    }

    Y obY;
    memcpy(wsk,obY,sizeof(Y))


    Czy coś takiego ma prawo bytu ? Czy memcpy w tym momencie już się nie sprawdzi ?

    0
  • #9 29 Sie 2010 10:45
    beluosus
    Poziom 25  

    megaman123 napisał:
    Czy coś takiego ma prawo bytu ? Czy memcpy w tym momencie już się nie sprawdzi ?

    Sprawdzi się. To są akurat bardzo proste struktury, bez żadnych wskaźników czy dynamicznie alokowanych pamięci. Zawsze sobie wyświetl ile wynosi sizeof() danego obiektu i sprawdź czy się zgadza. W tym wypadku sizeof == 488, a obiekty w klasie 486 więc wszystko się zgadza. 2 bajty zostają na wyrównanie danych (padding).

    0
  • #10 29 Sie 2010 10:54
    megaman123
    Poziom 13  

    Świetnie !

    A powiedz mi jak to będzie przy de-serializacji. Mając taki blok pamięci, raczej nie sprawdzi się zapis :

    Code:

    Y * result = ( Y* ) wsk;


    Głównie chodzi o to , czy obiekty będą zapisane w takiej samej kolejności. Szczególnie przy wielokrotnym dziedziczeniu.

    0
  • #11 29 Sie 2010 11:06
    beluosus
    Poziom 25  

    Dlaczego rzutowanie? Na dodatek w stylu C. Wydaje mi się, że powinno zadziałać, ale proponowałbym coś takiego:

    Code:
    class Y : public Z
    
    {
    public:
        double tab_x[4];

        char *ser()
        {
            char *wsk = new char[sizeof(Y)];
            memcpy(wsk, this, sizeof(Y));
            return wsk;
        };

        void deser(char *mem)
        {
            memcpy(this, mem, sizeof(Y));
            delete [] mem;
        }
    };

    int main()
    {
        Y obY;
        obY.a = 1212123;
        obY.tab_mem[88] = 98765;
        char *wsk = obY.ser();

        Y obYdes;
        obYdes.deser(wsk);

        cout << obYdes.a << "\n" << obYdes.tab_mem[88] << endl;

        return 0;
    }

    0