2016-11-03 19 views
5

İki farklı uygulama arasında POSIX modelinde paylaşılan bir dinamik dizim var. Kopyalamadan boyutunu değiştirebilme yeteneğine sahip olmak isterim. Ne yazık ki, C dilinde POSIX paylaşımlı belleği artırmak ve azaltmak için doğru çözümü bulamadım. İnternette kötü açıklamaları ve sefil örnekleri olan birçok belge buldum. Ben bazı ilginç konuları bulmak başardılar, ama bunların hepsi bana uygun değildir: POSIX paylaşılan belleği yeniden boyutlandırın. Çalışan bir örnek

  1. "Linux System Programming" - "Mapping Files into Memory" Part: "Resizing a Mapping"

    - SHM boyutlandırmak için hiçbir çalışma örneği olduğu.

  2. How do I implement dynamic shared memory resizing? - Yalnızca bir açıklama. Örnek yok.

  3. mremap function failed to allocate new memory - Sık kullanılan yanıt yanlış çalışıyor.

  4. mremap function failed to allocate new memory

  5. c/linux - ftruncate and POSIX Shared Memory Segments

    Characteristics of mremap function in Linux

  6. Fast resize of a mmap file

  7. - rszshm hiç mremap() kullanmaz. Bunun yerine belleği kopyalayın. En kötü yol.

Belgeleri anladığımda bir örnek geliştirdim. Maalesef doğru çalışmıyor. Lütfen yanıldığım bir tavsiye ver. Ve lütfen bana bir örnek vermek için çok nazik olun.

belgelerinde ben mremap önce ftruncate()() kullanmak zorunda olduğunu bulduk, ama bunları kullanmak için doğru sözdizimi bulamadık. Ayrıca, mremap() hizalanmış bellek sayfalarıyla çalışır. Bu durumda paylaşılan belleği düzgün şekilde nasıl artırabilirim?

/* 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; 
} 

Yapı:

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

çalıştırın:

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

En azından boyutları sayfa boyutlarına göre ölçmeniz gerekir. bkz. getpagesize() veya sysconf() '. Ve süreçler arasındaki hafızayı paylaşmak için, yeni boyutu diğer süreçlere iletmenin bir yolunu bulmanız gerekecek. – joop

cevap

2

Sen temp atanan yeni ayrılan/remapped bellek adresini kaybediyor.

Bu, for döngüsünün ikinci döngüsünden beri, zaten taşınmış bir belleği taşıdığınız anlamına gelir.

Mremap döndürülen değeri kontrol edildikten sonra, yeni adresi shm_address işaretçisine yeniden atayabilirsiniz.

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

Çok teşekkür ederim. Şimdi gerçekten hatasız çalışıyor. Kalan soruya ne dersin? mremap() hizalanmış bellek sayfalarıyla çalışır. Bu durumda paylaşılan belleği düzgün şekilde nasıl artırabilirim? –

+1

Bu büyük bir sorudur. Bazı linux managemnt gurusunun iyi bir açıklaması için farklı bir soru gönderin. Ne ben burada söyleyebiliriz arayan tarafından sağlanan len parametre bir sayfa sınırında hizalanmış değilse haritalama sonraki tam sayfaya yuvarlanır olmasıdır.Eklenen bu bayt içindeki baytlar, son geçerli bayt ile eşleştirmenin sonu arasında sıfır doldurulur. Bu bölgeden okunan tüm değerler sıfırlar. – LPs

+0

Tekrar teşekkürler. Çok kullanışlı! –

İlgili konular