[LINUX] Kommunikation zwischen Prozessen ~ gemeinsamer Speicher ~

Zweck

Zur Erinnerung habe ich meine Forschungen zum "Shared Memory" in der Interprozesskommunikation (IPC) zusammengefasst.

Der folgende Artikel war sehr hilfreich als Zusammenfassung der Kommunikation zwischen Prozessen. Ich habe den Code auch als Referenz verwendet. Linux Interprocess Communication (Qiita)

Die Umgebung hier ist wie folgt. Der Code ist in C ++ geschrieben. MacOS 10.13.4 gcc 7.3.0

Ich würde mich freuen, wenn Sie auf Mängel hinweisen könnten.

[Zusatz] Die folgende Erklärung ist der gemeinsam genutzte Speicher von System V, und es scheint, dass der gemeinsam genutzte Speicher von POSIX ebenfalls vorhanden ist.

Kommentar

Was ist gemeinsamer Speicher?

Laut [Wikipedia](https://ja.wikipedia.org/wiki/shared memory) ist "Shared Memory eine effiziente Möglichkeit, Daten zwischen Programmen auszutauschen." "Ein Prozess befindet sich im Speicher und ein anderer Prozess. Erstellen Sie einen Bereich, auf den auch zugegriffen werden kann. " Das Austauschen von Daten über einen Speicherbereich wäre ein ziemlich schneller Prozess. Es scheint jedoch, dass Sie bei Konflikten vorsichtig sein müssen, da mehrere Prozesse auf denselben Speicher zugreifen können.

Betriebsablauf für gemeinsam genutzten Speicher

Wichtig ist, dass der gemeinsam genutzte Speicher zunächst unabhängig vom Prozess erstellt wird. Danach wird es mit mehreren Prozessen verknüpft.

Details zum Shared-Memory-Betrieb

Die folgenden Funktionen stehen im Unix-System zur Verfügung, um gemeinsam genutzten Speicher zu verwalten. shmget() (Man page of SHMGET) shmat() (Man page of SHMOP) shmdt() (Man page of SHMOP) shmctl() (Man page of SHMCTL) Bitte lesen Sie jede Manpage für Details.

Hier werde ich nur die wichtigen Teile erklären.

shmget() Diese Funktion ist eine Funktion, die einen gemeinsam genutzten Speicher erstellt und dessen Kennung ausgibt. Es wird auch verwendet, um die Kennung des bereits erstellten gemeinsam genutzten Speichers abzurufen. Es braucht drei Argumente. · * Schlüssel * Dies ist der IPC-Schlüssel, der mit "ftok ()" oder "IPC_PRIVATE" abgerufen werden kann. Sie können sich das als einen einzigartigen Wert vorstellen. Weitere Informationen finden Sie unter System VIPC Basics und Man Page of FTOK. -Bitte lesen Sie die Seiten / man3 / ftok.3.html) und so weiter. Dieser Schlüssel ist vom Typ key_t, aber Sie benötigen <sys / types.h>, um ihn zu verwenden.

· * Speichergröße * Dies muss ein Vielfaches von PAGE_SIZE sein. Wenn das nicht passiert, scheinen sie es zu beheben, indem sie es ein wenig erhöhen.

· * Flagge * Sie können Optionen zum Erstellen des gemeinsam genutzten Speichers und die Berechtigungen für den erstellten Speicher angeben. Weitere Informationen finden Sie unter Man Page. Es scheint, dass Sie Flags verwenden können, um andere als die hier aufgeführten Berechtigungen festzulegen (die in chmod verwendet werden).

Wenn Sie die ID des erstellten gemeinsam genutzten Speichers abrufen möchten, können Sie nur den Schlüssel angeben und die anderen auf 0 setzen.

shmat() Diese Funktion hängt den erstellten gemeinsam genutzten Speicher an den Adressraum des Prozesses an. Es braucht drei Argumente. ・ * Shared Memory ID * Dies ist der Wert, der von shmget () erstellt und zurückgegeben wird.

・ * Speicheradresse * Die Adresse, an die Sie den gemeinsam genutzten Speicher anhängen möchten. Wenn Sie dies auf 0 setzen, wird es anscheinend willkürlich ausgewählt.

· * Flagge * Es dient zum Festlegen von Optionen. Weitere Informationen finden Sie unter Man Page.

shmdt() Diese Funktion trennt den gemeinsam genutzten Speicher vom Adressraum des Prozesses. Es scheint, dass nur ein Argument erforderlich ist und die von shmat () zurückgegebene Adresse ausreicht. Es ist sehr leicht.

shmctl() Mit dieser Funktion werden verschiedene Steuerelemente für den gemeinsam genutzten Speicher ausgeführt. Da es verschiedene Funktionen gibt, möchte ich die Details Man Page überlassen. Es braucht drei Argumente. ・ * Shared Memory ID * Die ID des gemeinsam genutzten Speichers, den Sie steuern möchten. Es ist das von shmget () ausgegebene.

·Befehl Dies ist der Inhalt des Steuerelements, das Sie für den gemeinsam genutzten Speicher ausführen möchten. In diesem Artikel verwenden wir "IPC_RMID", um Speicher freizugeben.

· * Zeiger auf die Struktur shmid_ds * Es ist eine Struktur zum Speichern der Informationen, die Sie dem gemeinsam genutzten Speicher hinzufügen möchten. Erforderlich bei Verwendung von Befehlen wie "IPC_STAT" und "IPC_SET". Da dies diesmal nicht erforderlich ist, belassen Sie es als NULL (oder 0).

Eigentlich verwenden

Ich bin sicher, es ist okay, wenn ich so viel erkläre. Da ich es mit viel Mühe erklärt habe, werde ich versuchen, etwas zu machen, das tatsächlich funktioniert. shm_a.cpp verwaltet den gemeinsam genutzten Speicher und schreibt eine beliebige Zeichenfolge in diesen. shm_b.cpp liest und schreibt den geschriebenen Inhalt.

Lassen Sie uns die beiden im selben Verzeichnis von verschiedenen Terminals aus ausführen. Sie können sehen, dass der in shm_a geschriebene Inhalt auch in shm_b wiedergegeben wird.

shm_a.cpp


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
using namespace std;


int main(){
    //Erstellen Sie eine leere Datei
    FILE *fp;
    const string file_path = "./key.dat";
    fp = fopen(file_path.c_str(), "w");
    fclose(fp);

    //IPC-Schlüssel erhalten
    const int id = 50;
    const key_t key = ftok(file_path.c_str(), id);
    if(key == -1){
        cerr << "Failed to acquire key" << endl; 
        return EXIT_FAILURE;  
    }

    //ID des gemeinsam genutzten Speichers abrufen
    const int size = 0x6400;
    const int seg_id = shmget(key, size, 
                              IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);
    if(seg_id == -1){
        cerr << "Failed to acquire segment" << endl;
        return EXIT_FAILURE;
    }

    //Hängen Sie gemeinsam genutzten Speicher an einen Prozess an
    char* const shared_memory = reinterpret_cast<char*>(shmat(seg_id, 0, 0));

    //In den gemeinsamen Speicher schreiben
    string s;
    int flag = 0;
    cout << "if you want to close, please type 'q'" << endl;
    while(flag == 0){
        cout << "word: ";
        cin >> s;
        if(s == "q") flag = 1;
        else sprintf(shared_memory, s.c_str());
    }

    //Trennen Sie den gemeinsam genutzten Speicher vom Prozess
    shmdt(shared_memory);

    //Geben Sie gemeinsam genutzten Speicher frei
    shmctl(seg_id, IPC_RMID, NULL);    

    return 0;
}

shm_b.cpp


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
using namespace std;


int main(){
    //Rufen Sie die ID des erstellten gemeinsam genutzten Speichers ab
	const string file_path = "./key.dat";
    const int id = 50;

    const key_t key = ftok(file_path.c_str(), id);

    const int seg_id = shmget(key, 0, 0);
    if(seg_id == -1){
        cerr << "Failed to acquire segment" << endl;
        return EXIT_FAILURE;
    }

    //Hängen Sie gemeinsam genutzten Speicher an einen Prozess an
    char* const shared_memory = reinterpret_cast<char*>(shmat(seg_id, 0, 0));

    //Lesen Sie Zeichen im gemeinsamen Speicher
    int flag = 0;
    char c;
    cout << "If you want to close, please type 'q'" << endl;
    cout << "If you want to read the shared memory, push enter button." << endl;
    while(flag == 0){
        cin.get(c);
        if(c == 'q') flag = 1;
        else printf("%s\n", shared_memory);
    }

    //Trennen Sie den gemeinsam genutzten Speicher vom Prozess
    shmdt(shared_memory);

    return 0;
}

Wenn in Schwierigkeiten

Es gibt "ipcs" als Befehl zum Verwalten der Kommunikation zwischen Prozessen. Dadurch erhalten Sie Informationen zum vorhandenen gemeinsam genutzten Speicher. Sie können also die Existenz von gemeinsam genutztem Speicher überprüfen, indem Sie "ipcs" in einem anderen Terminal ausführen, während Sie "shm_a.cpp" ausführen. Wenn der gemeinsam genutzte Speicher durch gewaltsames Beenden dieses Programms nicht ordnungsgemäß freigegeben wird, können Sie ihn auch mit "ipcrm" löschen. Bitte lesen Sie die folgende Website für die Verwendung. ipcs command-IBM ipcrm - Interprozesskommunikations-ID entfernen --IBM

Referenz

Recommended Posts

Kommunikation zwischen Prozessen ~ gemeinsamer Speicher ~
Linux-Interprozesskommunikation
Arten der Kommunikation zwischen Prozessen
Gemeinsamer Speicher zwischen Prozessen
Verwenden Sie gemeinsam genutzten Speicher mit gemeinsam genutzten Bibliotheken
Interprozesskommunikation für Embedded DL