2016-11-03 11 views
5

두 개의 서로 다른 응용 프로그램 사이에 POSIX 모델 내에서 공유 동적 배열이 있습니다. 복사하지 않고 크기를 변경할 수있는 기능을 원합니다. 불행히도 나는 C 언어로 POSIX 공유 메모리를 늘리거나 줄이기위한 올바른 해결책을 찾지 못했습니다. 웹에서 나는 가난한 설명과 비참한 예를 가진 많은 문서를 발견했다. 나는 몇 가지 흥미로운 주제를 찾으려면 관리했지만, 그들 모두가 나에게 적합하지 않은 : POSIX 공유 메모리 크기를 조정하십시오. 작업 예제

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

    - SHM의 크기를 조정 할 일 예는없는 곳.

  2. How do I implement dynamic shared memory resizing? - 설명 만. 예를 들어 보지 마십시오.

  3. mremap function failed to allocate new memory - 좋아하는 답변이 잘못되었습니다.

  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 전혀 mremap는()를 사용하지 않습니다. 대신 메모리를 복사합니다. 최악의 방법.

설명서를 이해하면서 예제를 개발했습니다. 불행히도 그것은 올바르게 작동하지 않습니다. 내가 잘못한 조언을 해주세요. 그리고 제게 실용적인 예를 들어 주시길 바랍니다.

설명서에서 mremap() 전에 ftruncate()를 사용해야한다는 것을 발견했지만이를 사용하기위한 올바른 구문을 찾을 수 없습니다. 게다가 mremap()은 정렬 된 메모리 페이지와 함께 작동합니다. 이 경우 공유 메모리를 올바르게 늘리는 방법은 무엇입니까?

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

빌드 :

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

실행 :

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

적어도 페이지 크기 측면에서 크기를 측정해야합니다. 'getpagesize()'또는'sysconf()'를 참조하십시오. 또한 프로세스간에 메모리를 공유하려면 새 크기를 다른 프로세스와 통신하는 방법을 찾아야합니다. – joop

답변

2

당신은 temp에 할당 된 새 할당/매핑 메모리의 주소를 잃어버린있다.

즉, for 루프의 두 번째 사이클 이후로 이미 이동 된 메모리를 이동하고 있음을 의미합니다.

mremap 반환 값을 확인한 후 새 주소를 shm_address 포인터에 다시 지정할 수 있습니다.

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

고맙습니다. 이제는 오류없이 실제로 작동합니다. 남은 질문은 어떨까요? mremap()는 정렬 된 메모리 페이지와 함께 작동합니다. 이 경우 공유 메모리를 올바르게 늘리는 방법은 무엇입니까? –

+1

큰 질문입니다. 몇몇 리눅스 경영자로부터 좋은 설명을 얻기 위해 다른 질문을 올리십시오. 여기서 내가 말할 수있는 것은 호출자가 제공 한 len 매개 변수가 페이지 경계에 정렬되지 않으면 매핑이 다음 전체 페이지로 반올림된다는 것입니다.마지막으로 유효한 바이트와 매핑 끝 사이의이 추가 된 메모리 내부의 바이트는 0으로 채워집니다. 해당 영역에서의 읽기는 모두 0을 리턴합니다. – LPs

+0

다시 한 번 감사드립니다. 굉장히 유용하다! –