Wie synchronisiert man eine DLL mit zwei Prozessen?



  • Soo ich hab mal ein wenig weiter gemacht mit der Idee der DllMain (natürlich bevor ich die Beiträge hier gelesen hab 🙂 )
    Wie ich mir das dachte, klappt es natürlich nicht.

    Lösung A:
    Der shared Bereich:

    #pragma data_seg( "shared" )
    static CRITICAL_SECTION CriticalSectionRead;
    int g_dllVarS = 0; // shared var
    #pragma data_seg()
    #pragma comment( linker, "/SECTION:shared,RWS" )

    Die "Dllmain" (hoffentlich ist der Name nicht ausschlaggebend):

    int dllinit() {
    InitializeCriticalSection( &CriticalSectionRead );
    }

    Die dllinit() wird nun bei jeder EXE aufgerufen. Ich hatte gehofft, dass falls "CriticalSectionRead" schon initialisiert ist, ein weiterer Aufruf von InitializeCriticalSection( &CriticalSectionForReadFct ); an der Variablen nichts weiter ändert (das z.B. wie bei CreateFileMapping() quasi ein already exists zurückkommt).
    In diesem Falle haben die Anpassungen in dem Code natürlich nichts gebracht:

    int dllInc() {
    EnterCriticalSection( &CriticalSectionRead );
    g_dllVarS++;
    return 0;
    }

    int dllDec() {
    g_dllVarS--;
    LeaveCriticalSection( &CriticalSectionRead )
    return 0;
    }
    ;

    (Ich weiß, dass man normaler Weise nur den Zugriff auf die Variable umschließt. Aber um die Funktionalität nachzuweisen, wollte ich die beiden Funktionen quasi verschränken 😉 )

    Lösung B:
    Also hab ich in den shared Bereich noch eine Variable angelegt (der Name ist ja wohl mehr als klasse :p ).

    static int critical_virgin=1;

    und die dllinit() damit ausgestattet:

    int dllinit() {
    if (critical_virgin) {
    InitializeCriticalSection( &CriticalSectionRead );
    critical_virgin=0;
    }
    }

    Nun stürzt mir die zweite EXE bei dem Aufruf von EnterCriticalSection( &CriticalSectionRead ); ab. Ich nehme mal an aus diesem Grunde:

    hustbaer schrieb:

    Die "shared" Datensegmente werden nicht "verdoppelt", alles andere schon. Meine Frage ist somit hinfällig 🙂

    Und weil nun meine Critical Section Varible somit nicht mehr initialisiert ist. Also würde Critical Section als Lösung schon mal wegfallen, richtig?

    Okay dann mal noch Antworten auf eure Fragen 🙂

    berniebutt schrieb:

    - Willst Du nur eine Zählvariable mitführen,

    Nein, ich mag nur herausfinden, wie man quasi IPC bei DLLs nutzt

    Martin Richter schrieb:

    ... funktionert nicht mehr, wenn es ... in unterschiedlichen Verzeichnissen liegt.

    Liegt alles im gleichen Verzeichnis

    Martin Richter schrieb:

    Ich würde hier eher zu Semaphoren oder anderem greifen.

    Okay, dann werd ich mal nach Semaphoren ausschau halten. Aber da hab ich doch auch das Problem, dass ich die Semaphoren irgendwo initialisieren muss, oder?
    Und was ist denn "oder anderem"? Bitte näher erläutern 🙂


  • Mod

    Critical Sections funktionieren nur im selben Prozess.

    Einen Semaphore/Mutex kann man unter einem Namen anlegen und Prozessübergreifend darauf zugreifen.



  • ARRR!
    Sorry, mein Fehler!
    Natürlich funktionieren Critical-Sections nur innerhalb eines Prozesses.

    Also entweder auf Mutexen umsteigen (relativ langsam), oder selbst ne Spin-Lock basteln (mit InterlockedCompareExchange).



  • Einmal kurz zusammengefasst, Du hast zwei getrennte Aufgaben, die aufeinander abgestimmt sein müssen:
    1. IPC - Die Kommunikation über Prozessgrenzen hinaus.
    2. Die Synchronisation der Zugriffe auf die systemglobalen Daten.
    Es eignen sich:
    für 1. a)Shared memory / b)FileSharing / c)Selbstgestrickte Lösungen
    Die Lösung a) ist leider compiler-abhängig, bei Borland über #pragmas nicht machtbar!
    für 2. Mutex-Objekte, vielleicht auch Semaphoren.



  • Erstmal noch mal danke für eure Unterstützung Leute!

    Hab das Problem nun mit Semaphoren gelöst, hier der Code dazu:

    // Shared var section
    #pragma data_seg( "shared" )
    int g_dllVarS = 0;
    #pragma data_seg()
    #pragma comment( linker, "/SECTION:shared,RWS" )
    
    // Global (not shared) var section
    int g_dllVarN = 0;
    HANDLE ghSem;
    
    int dllinit()
    {
    	ghSem = CreateSemaphore( NULL , 1, 1, "ReadSem");
    	return 0;
    }
    
    int dllclose()
    {
    	CloseHandle(ghSem);
    	return 0;
    }
    
    int dllInc()
    {
    	printf("Enter Critical Sec  -- ");
    	WaitForSingleObject(ghSem, INFINITE);
    	printf("Entered Critical Sec\n");
    
    	g_dllVarS++;
    	g_dllVarN++;
    	Sleep(3000);
    
    	printf("Leave Critical Sec  --  ");
    	ReleaseSemaphore(ghSem, 1, NULL);
    	printf("Leaved Critical Sec  \n");
    
    	return 0;
    }
    
    int dllDec()
    {
    	printf("Enter Critical Sec  -- ");
    	WaitForSingleObject(ghSem, INFINITE);
    	printf("Entered Critical Sec\n");
    
    	g_dllVarS--;
    	g_dllVarN--;
    	Sleep(3000);
    
    	printf("Leave Critical Sec  --  ");
    	ReleaseSemaphore(ghSem, 1, NULL);
    	printf("Leaved Critical Sec  \n");
    
    	return 0;
    }
    
    int dllGetVarS()
    {
    	return g_dllVarS;
    }
    
    int dllGetVarN()
    {
    	return g_dllVarN;
    }
    

    Nun kann immer nur ein Prozess auf die Variablen zugreifen. Bei mehrfachem Aufruf von CreateSemaphore(); mit dem gleichen Bezeichner (hier "ReadSem") wird kein neuer Semaphor erstellt, sondern nur das Zugriffsrecht erteilt.
    Mittels dem Sleep(); sieht man sehr schön, dass ein Prozess gerade sperrt und welcher es ist 🙂



  • Wieso verwendest du eine Semaphore und keine Mutex???



  • @ ThomasBlue: Gratulation! Mutex erscheint mir aber passender als Semaphore.
    @ Martin Richter: Du gehörst zu den wenigen Programmierern, die rundum mit den angebotenen Dingen von Microsoft zufrieden sind. Vielleicht bist Du später als mit DOS und Win16 eingestiegen? In den 1980er Jahren hiess es nicht zu unrecht: "Gates or Gates not?", jedenfalls unter deutschprachigen Programmierern.



  • Hey hier kein geflame bitte, schön beim Thema bleiben.

    hustbaer schrieb:

    Wieso verwendest du eine Semaphore und keine Mutex???

    Hatte mich mit Mutex noch nicht befasst und oben hattest du doch geschrieben, dass das relativ langsam sei ... gut, ich weiß auch nicht, wie schnell/langsam Semaphore sind.
    Wo besteht denn da der Unterschied?



  • Semaphore = genauso langsam wie die Mutex.

    Unterschied: Mutex ist "spezialisierter", und damit IMO besser geeignet für das was du machen willst.



  • ThomasBlue schrieb:

    Hey hier kein geflame bitte, schön beim Thema bleiben.

    Jeder Beitrag hier ist beim Thema geblieben. Boszameg, das Wort "geflame" kenne ich leider nicht. Nehme ein Mutex-Objekt.


Anmelden zum Antworten