2016-11-03 4 views
5

Ich habe ein gemeinsames dynamisches Array im POSIX-Modell zwischen zwei verschiedenen Anwendungen. Ich möchte eine Fähigkeit haben, seine Größe zu ändern, ohne zu kopieren. Leider konnte ich keine richtige Lösung finden, um den gemeinsamen POSIX-Speicher in der C-Sprache zu erhöhen oder zu verringern. Im Internet habe ich viele Dokumente mit schlechten Erklärungen und elenden Beispielen gefunden. Ich habe es geschafft, einige interessante Themen zu finden, aber alle von ihnen sind nicht geeignet für mich:Größe ändern POSIX Shared Memory. Ein funktionierendes Beispiel

  1. "Linux System Programming" - "Mapping Files into Memory" Part: "Resizing a Mapping" - wo ist kein Arbeitsbeispiel SHM zu ändern.

  2. How do I implement dynamic shared memory resizing? - Nur eine Beschreibung. Habe kein Beispiel.

  3. mremap function failed to allocate new memory - Lieblingsantwort funktioniert nicht.

  4. Fast resize of a mmap file

  5. Characteristics of mremap function in Linux

  6. mremap function failed to allocate new memory

  7. c/linux - ftruncate and POSIX Shared Memory Segments - rszshm verwenden mremap() überhaupt nicht. Es kopiert stattdessen Speicher. Der schlimmste Weg.

Ich habe ein Beispiel entwickelt, wie ich die Dokumentation verstehe. Leider funktioniert es nicht richtig. Bitte geben Sie mir einen Hinweis, wo ich falsch liege. Und sei bitte so freundlich, mir ein funktionierendes Beispiel zu geben.

In der Dokumentation habe ich gefunden, dass ich ftruncate() vor mremap() verwenden muss, aber ich konnte nicht richtige Syntax für die Verwendung von ihnen finden. Außerdem arbeitet mremap() mit ausgerichteten Speicherseiten. Wie erhöht man in diesem Fall den gemeinsamen Speicher richtig?

/* main.c */ 
#define _GNU_SOURCE 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 
#include <fcntl.h> 
#include <sys/shm.h> 
#include <sys/stat.h> 
#include <sys/mman.h> 
#include <sys/types.h> 
#include <errno.h> 

int main(void) 
{ 
    size_t size_of_mem = 1024; 
    int fd = shm_open("/myregion", O_CREAT | O_RDWR, 
         S_IRWXO | S_IRUSR | S_IWUSR); 
    if (fd == -1) 
    { 
     perror("Error in shm_open"); 
     return EXIT_FAILURE; 
    } 

    if (ftruncate(fd, size_of_mem) == -1) 
    { 
     perror("Error in ftruncate"); 
     return EXIT_FAILURE; 
    } 

    void *shm_address = mmap(0, size_of_mem, 
          PROT_READ | PROT_WRITE | PROT_EXEC, 
          MAP_SHARED, fd, 0); 
    if (shm_address == MAP_FAILED) 
    { 
     perror("Error mmapping the file"); 
     return EXIT_FAILURE; 
    } 

    /* Increase shard memory */ 
    for (size_t i=0; i<1024; ++i){ 

     /* Does 8 align memory page? */ 
     size_t new_size_of_mem = 1024+(8*i); 

     if (ftruncate(fd, new_size_of_mem) == -1) 
     { 
      perror("Error in ftruncate"); 
      return EXIT_FAILURE; 
     } 

     /* 
      mremap() works with aligned memory pages. 
      How to properly increase shared memory in this case? 
     */ 
     void *temp = mremap(shm_address, size_of_mem, new_size_of_mem, MREMAP_MAYMOVE); 
     if(temp == (void*)-1) 
     { 
      perror("Error on mremap()"); 
      return EXIT_FAILURE; 
     } 

     size_of_mem = new_size_of_mem; 

    } 

    return 0; 
} 

Körperbau:

$ gcc -g -O0 -ggdb -pipe -Wall -Wextra -Wpedantic -Wshadow -march=native -std=c11 -o ./main ./main.c -lrt 

Run:

$ ./main 
Error on mremap(): Bad address 
+0

Zumindest müssen Sie Größen in Bezug auf die Seitengröße messen. siehe 'getpagesize()' oder 'sysconf()'. Und um den Speicher zwischen Prozessen zu teilen, müssen Sie eine Möglichkeit finden, die neue Größe den anderen Prozessen mitzuteilen. – joop

Antwort

2

Sie die Adresse des neuen zugewiesen/remapped Speicher temp zugewiesen zu verlieren.

Das bedeutet, dass Sie seit dem zweiten Zyklus der for-Schleife einen bereits verschobenen Speicher verschieben.

Nach der Überprüfung von Mremap zurückgegebenen Wert können Sie die neue Adresse an die shm_address Zeiger zuweisen.

void *temp = mremap(shm_address, size_of_mem, new_size_of_mem, MREMAP_MAYMOVE); 
if(temp == (void*)-1) 
{ 
    perror("Error on mremap()"); 
    return EXIT_FAILURE; 
} 

shm_address = temp; 
+0

Vielen Dank. Jetzt funktioniert es wirklich ohne Fehler. Wie wäre es mit der verbleibenden Frage? mremap() arbeitet mit ausgerichteten Speicherseiten. Wie erhöht man in diesem Fall den gemeinsamen Speicher richtig? –

+1

Es ist eine große Frage. Stellen Sie eine andere Frage, um eine gute Erklärung von einem Linux-Management-Guru zu erhalten. Was ich hier sagen kann, ist Folgendes: Wenn der vom Aufrufer bereitgestellte len-Parameter nicht an einer Seitengrenze ausgerichtet ist, wird das Mapping auf die nächste ganze Seite aufgerundet.Die Bytes innerhalb dieses hinzugefügten Speichers zwischen dem letzten gültigen Byte und dem Ende des Mappings sind mit Nullen gefüllt. Jeder Lesevorgang aus dieser Region gibt Nullen zurück. – LPs

+0

Nochmals vielen Dank. Sehr hilfreich! –