read write lock mit mehreren Programmen



  • Hallo zusammen,

    kurz und knapp, ich bin gerade dabei ein shared memory Programm zu schreiben. Dafür nutze ich die boost library. Da schreiben und lesen gleichzeitig keine gute Idee ist will ich mit mutexen arbeiten.

    Hier habe ich mich an dem "interprocess::interprocess_sharable_mutex" von boost bedient. Nur habe ich hier einen kleinen Denkfehler begangen. Ich kann das Mutex entweder mit in die Datei schreiben, damit alle Programme drauf zugreifen können, was das Mutex selbst dann zu einem read/write problem macht. Oder ich schreibe es nicht mit in die Datei, aber dann haben die anderen Programme darauf auch keinen Zugriff.

    wie kann ich also Mutexe zwischen Programmen austauschen, oder auf den Namen einer Datei mappen?
    Das am besten nicht auf ein Betriebssystem gemünzt, sondern allgemein gehalten.

    Danke schon ein mal für eure Hilfe.

    Cheers
    EvD



  • Nimm lieber ein named mutex. Dieser mutex ist eindeutig mit einem namen im system erreichbar. Dadurch sparst du dir den shareable_mutex via shared memory zwischen processen zu "teilen".

    https://www.boost.org/doc/libs/1_57_0/doc/html/interprocess/synchronization_mechanisms.html#interprocess.synchronization_mechanisms.mutexes.mutexes_named_example

    Oder du erstellt ein shared memory segment in dem dann der sharable_mutex gespeichert wird.



  • @firefly ich sehe bei den named mutex keine Möglichkeit diese mit shared mutexe zu verbinden... bei einem shared memory bei dem auch oft gelesen wird wäre es wirklich gut, wenn man auch soft-locks verteilen kann.

    oder würdest du dafür dann einen Shared Mutex in einer Datei verpacken die durch ein named Mutex geschützt wird?

    also sowas:

    dataType read(){
    //setzen des named Mutex
    //setzen des sharable lock
    //freigeben des named Mutex
    //lesen
    //setzen des named Mutex
    //freigeben des sharable lock
    //freigeben des named Mutex
    }
    

    wobei es da dann zu dem Punkt kommen könnte, an dem der Overhead den Gewinn auffrisst, den man mit soft-locks zum lesen bekommt.

    Das ding ist, es soll sehr oft von vielen gelesen und mindestens jede 25 millisekunden geschrieben werden können.

    Aber generell sind die Named Mutexe wirklich eine gute Idee, danke 🙂



  • Ich meinte du ersetzt den shareable mutex mit dem named mutex.
    Ein named mutex ist system eindeutig! Und du sparst die die ganze sache den sharable mutex z.b. via shared memory segment zwischen prozessen zu teilen



  • @firefly dann kann halt nur ein Prozess gleichzeitig lesen, oder verstehe ich das falsch 🤔

    Was bei einem schreibenden und n lesenden Programmen zu einem bottleneck führen würde 🤔



  • Dann nimm die named_sharable_mutex variante ist das gleiche wie ein named_mutex nur mit dem zusätzlichen support für das konzept für reader writer lock konzept.
    Und du musst dich nicht drum kümmern wie die verschiedenen processe auf den mutex zugreifen können.

    Ansonsten muss du den mutex via shared memory allen prozessen bereitstellen.
    Beispiel
    https://www.boost.org/doc/libs/1_58_0/doc/html/interprocess/synchronization_mechanisms.html#interprocess.synchronization_mechanisms.mutexes.mutexes_anonymous_example

    Die Transferleistung wie von einem interprocess::interprocess_mutex auf interprocess::interprocess_sharable_mutex überlasse ich dir



  • @firefly ich habe noch eine kleine frage... habe mich gestern ein wenig hin gesetzt aber keine gescheite Lösung gefunden.

    Ich greife ja auf das shard memory mit einem Namen zu. diesen kann der Nutzer selbst Wählen. der Gedanke war das der Mutex den gleichen Namen hat (also dann im Konstruktor der Klasse "Sheard_Mem" erzeugt wird). Wie kann ich das nun erreichen, da boost das kopieren des named_sharable_mutex explizit verbietet. also kein = oder den Pointer übergeben oder so.

    wie kann ich das bewerkstelligen?

    und danke für deine Hilfe bis hier hin 🙂



  • Für einen named_sharable_mutex brauchst du kein shared memory segment um diesen mutex zwischen pozessen zu teilen.

    Ein named mutex ist über seinen namen schon direkt erreichbar.

    ein shared memory segment brauchst du nur wenn du einen non named mutex, in deinem falle dann ein interprocess_sharable_mutex, verwenden möchtest.



  • @firefly sorry, falsch ausgedrückt.

    Ich habe eine klasse Shm_element_imp

    template<class elementType>
    class Shm_element_imp{
        public:
            Shm_element_imp(const char* name, int size);
            Shm_element_imp(const char* name);
            ~Shm_element_imp();
            elementType* read();
            void write (elementType* input);
            template<typename ValueType>
            void write (ValueType value, void (*fu)(elementType &type,ValueType value));
            char get_name();
        
        private:
            elementType dataBlock;
            char name;
            mapped_region* region = new boost::interprocess::mapped_region;
            shared_memory_object shmObj;
            named_sharable_mutex named_mutex;
    };
    

    die Klasse bildet also die Schnittstelle um auf den Shared memory zu zugreifen. geplant ist in der Read Funktion auch noch die Möglichkeit einer Verschlüsselung ein zu bauen.

    Nun muss ich aber in "read()" und "write(...)" mit mutexen den zugriff schützen. Da die Mutexe aber den selben Namen haben sollen wie der Name des Shared memory, würde ich diesen gerne in dem Constructor der Shm_element_imp Klasse definieren und in "named_mutex" speichern. Leider habe ich keine Ahnung wie ich das hin bekommen soll. Ich kann es ja nicht mit einem "=" zuweisen.

    Hast du da eine Ahnung wie ich das schön hinbekomme?



  • Für was meint du jetzt einen named mutext zu benötigen? hier reicht doch ein anonymer mutex. Denn ein anonymer lässt sich in ein shared memory segment packen.

    ein named mutext hat den vorteil, dass du kein shared memory segment brauchst um den mutex zwischen prozessen zu teilen.

    Liest du überhaupt die verlinkte boost dokumentation zu interprocess synchronization mechanisms?
    Oder hast du das Probleme mit dem Verständnis?

    Da es in deinem initialen Post um den synchronisierten zugriff auf eine Datei ging ist die Verwendung eines named mutex einfacher, weil man da kein shared memory segment braucht. Da ein named mutex rein über sein namen zwischen Prozessen geteilt werden kann.

    Aber nun willst du ein shared memory segment verwenden, für was jetzt genau?

    Irgendwie ist dein vorgehen sehr verwirrend.
    Beschreibe mal sehr genau was du überhaupt erreichen möchtest.



  • @firefly ich will ein shared memory für Daten vom Typ 'elementType' ... beispielsweise einem Struct oder so... und diesen Memory dann mit verschiedenen Prozessen teilen. wenn ich jetzt in den Struct, das ich in den shared Memory packe, wie in dem ersten Post geschrieben ein Mutex packe, bekomme ich da ja schon Probleme beim Prüfen ob ich lesen darf, weil ich ja dafür das Struct lesen muss, in dem das Mutex gespeichert ist... ohne zu wissen ob da gerade jemand schreibt.

    Also muss ich ein Mutex haben (named) der den Zugriff aller anderen Prozesse regelt, damit diese dann auf Datenellenente zugreifen Können die kein Mutex enthalten.... also die Ellemente vom Typ 'elementType'.

    Sagen wir mal 'elementType' ist eine Matrix der größe 2.0000 x 6.
    Es gibt ein Programm das Schreibt.
    Es kann ein Shared-Memory element geben, das Programm könnte aber auch N elemente gleichzietig aktualisieren. Das ist variabel.
    Das muss dann von 12-13 Programmen gleichzeitig gelesen werden können.

    Diese Klasse ist also dafür da, den Shared-Memory bereit zu stellen und den Zugriff dann zu steuern. Der schreibende erzeugt das Shared memory und die lesenden greifen darauf zu. Der schreibende erzeugt die named_mutex und die lesenden können sie nur öffnen.

    So die Idee... aber vielleicht habe ich auch alle Seiten die du mir geschickt hast falsch verstanden und deine Aussagen ...



  • ich meine wenn das ginge, hättest du auch von Anfang an schreiben können das ich keinen Denkfehler gemacht habe, weil ich das schon lange habe ... aber dann frage ich mich wie das Funktioniert ... weil ich ja den Mutex schreibe und lese ... und das dann die Schreibe und leserechte von sich selbst quasi verwaltet ... lesen und schreiben (was man dann ja für ein lock() braucht) sind ja nicht atomar



  • @EvD sagte in read write lock mit mehreren Programmen:

    Sagen wir mal 'elementType' ist eine Matrix der größe 2.0000 x 6.
    Es gibt ein Programm das Schreibt.
    Es kann ein Shared-Memory element geben, das Programm könnte aber auch N elemente gleichzietig aktualisieren. Das ist variabel.
    Das muss dann von 12-13 Programmen gleichzeitig gelesen werden können.
    Diese Klasse ist also dafür da, den Shared-Memory bereit zu stellen und den Zugriff dann zu steuern. Der schreibende erzeugt das Shared memory und die lesenden greifen darauf zu. Der schreibende erzeugt die named_mutex und die lesenden können sie nur öffnen.

    Das was du beschreibst ist ähnlich dem log beispiel aus der boost dokumentation...

    @EvD sagte in read write lock mit mehreren Programmen:

    lesen und schreiben (was man dann ja für ein lock() braucht) sind ja nicht atomar

    Das locken eines Mutex muss "atomar" sein, bzw. die Implementierung sorgt dafür dass immer nur ein Aufrufer den Mutex locken kann.
    Dafür existieren ja das Konzept eines Mutex!

    Also du hast hier ein massives Verständnis Problem bezüglich mutexe

    Und du hast immer noch nicht erklärt für was du jetzt ein named mutex brauchst.
    Es gibt ein shared memory segment mit Daten welchen zwischen Prozessen geteilt werden soll.
    Gleichzeitiges schreiben soll vermieden werden um dafür zu sorgen, dass die Daten immer in einem konsistenten Zustand sind, wenn die Daten gelesen werden.

    Das entspricht der Beschreibung genau diesem Beispiel aus der Boost Dokumentation:
    https://www.boost.org/doc/libs/1_58_0/doc/html/interprocess/synchronization_mechanisms.html#interprocess.synchronization_mechanisms.mutexes.mutexes_anonymous_example

    Dort wird der Mutex im im shared memory segment zusammen mit der Datenstruktur erstellt.
    Und über diesen Mutex wird dann der zugriff auf die Daten der Datenstruktur (Im boost beispiel auf ein "memory log")

    Ersetze einfach den named_sharable_mutex durch interprocess_sharable_mutex dann funktioniert auch alles so wie du willst.

    Schau dir das boost Beispiel genau an und versuche es zu verstehen. Es bildet genau deine Anforderung an sich ab.
    Es gibt ein Prozess, welche das shared memory segment erstellt und Daten in diesem Segment beschreibt.
    Es gibt x Prozesse welche auf das shared memory segment zugreifen um darüber zugriff auf die Daten zu bekommen.


Anmelden zum Antworten