2013-05-09 1 views
2

내가 원하는 작업은 다음과 같습니다. 64 비트 Linux 용 라이브러리가 있습니다. 그런 다음 해당 라이브러리를 연결하는 응용 프로그램을 만들었습니다. 응용 프로그램을 실행할 때 라이브러리에서 할당 된 메모리가 항상 상위 위치 (> 4GB)에 있는지 확인하려고합니다.64 비트 Linux에서 상위 주소 (> 4GB)에서 메모리 할당을 할당하십시오.

Windows에서

, 테스트 목적으로 낮은 주소 이전에 높은 주소에서 할당하는 할당을 강제로 사용자가에서 VirtualAlloc를 호출 할 때 MEM_TOP_DOWN을 지정하거나 0x100000에서 다음 레지스트리 값 설정 :

HKEY_LOCAL_MACHINE \ 시스템 \ CURRENTCONTROLSET 컨트롤 \ 세션 \를 관리자 \ 메모리 관리 \ AllocationPreference

Linux에 비슷한 전략이 있는지 궁금합니다. Linux 메모리 관리가 Window와 다르다는 것을 이해하지만 mmap() 또는 링커 스크립트를 사용하는 것과 같은 단서를 발견했습니다. 그러나 나는 목표를 달성하지 못했습니다. 누구든지 더 많은 정보를 제공 할 수 있습니까?

#include <sys/mman.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 

#define handle_error(msg) \ 
    do { perror(msg); exit(EXIT_FAILURE); } while (0) 

int main() 
{ 
    void *addr1=0, *addr2=0; 
    long sz = sysconf(_SC_PAGE_SIZE); // get page size 
    size_t length = sz*1000*1000; // 1,000,000 pages 
    int fd = -1; 

    printf("page size = %ld\n", sz); 

    // find some available address 
    int *p = (int*)malloc(sizeof(int)); 
    long start = (long)p + sizeof(int); 
    free(p); // free it anyway 

    start += (sz-(start % sz)); // page alignment 
    printf("start = 0x%lx\n", start); 

    // mmap fixed 
    addr1 = mmap((void*)start, length, PROT_NONE, 
       MAP_PRIVATE|MAP_NORESERVE|MAP_ANONYMOUS|MAP_FIXED, fd, 0); 
    if (addr1 == MAP_FAILED) 
    handle_error("mmap"); 
    printf("first map: %tx\n", addr1); 
    //msync(addr1, length, 0); 

    // another mmap 
    addr2 = mmap(NULL, sz*10, PROT_NONE, 
       MAP_ANONYMOUS|MAP_PRIVATE, fd, 0); 
    if (addr2 == MAP_FAILED) 
    handle_error("mmap"); 
    printf("second map: 0x%tx\n", addr2); 

    // test whether the memory is still available 
    p = (int*)malloc(sizeof(int)*10); 
    printf("allocated address: 0x%tx\n", p); 

    return 0; 
} 

출력 : 당신이이 (처음 네 기가 바이트 일부 주소를 제공 mmap을 피할 수) 그렇게 할 이유가 이해하지

page size = 4096 
start = 0x1d77000 
first map: 1d77000 
second map: 0x7f5f26c2f000 
allocated address: 0x1d76030 
+3

왜 하시겠습니까? 어떤 문제가 해결 될까요? – Mat

+0

그리고 어떻게 가상 메모리 페이지가 물리적으로 어디에 있는지 알 수 있습니까? –

+0

Mat : 포인터 잘라 내기 버그를 더 간신히 간질이라고 생각합니다! – duskwuff

답변

1

.

귀하는 매우 일찍 프로그램에 참여할 수있었습니다. 예 : main의 시작 또는 일부 생성자 함수 - mmap(2)MAP_FIXEDMAP_NORESERVE을 여러 메모리 세그먼트로 호출하여 목표를 달성하십시오. 따라서 프로그램의 기존 세그먼트 나 mmap에 대한 호출을 통해 4G 아래의 모든 주소 공간이 "채워질"수 있습니다.

그러나 라이브러리 (간접적으로 dlopen -ed 일 수 있음)는 프로그램 이후에 많이 시작될 수 있습니다.

처음 네 개의 기가 바이트가 주소 공간에서 사용되면 대부분의 일반 mmap 호출 (예 : malloc에 의해 수행 된 호출)이 외부로 이동합니다. 물론

, 당신이해야 할 몇 가지 시간에 mmap 전에 먼저 malloc (아마 mmap 또는 sbrk를 호출 할 것이다) mmapMAP_FIXED|MAP_NORESERVE에서이를 피할 필요가 있기 때문에 기존 메모리 세그먼트 (예 : /proc/self/maps을 구문 분석하여 얻을 수 있음)를 처리해야합니다.

그리고 자신 만의 malloc을 정의 할 수도 있습니다. 아마도 mmapMAP_NORESERVE은 거대한 지역 (예 : 테라 바이트) 일 수 있으며 내부 주소 만 사용하는 malloc (mmap- 다시)입니다.

나는 당신이 잘못된 문제를 해결하려고 노력하고 있다고 생각합니다. 내가 제안한 것을하는 것이 까다로울 수 있습니다 ... 처음 4 기가 바이트의 주소를 피할 이유가 없습니다.

현재 Linux에서 메모리 누수를 찾는 좋은 도구는 valgrind입니다.

+0

답장을 보내 주셔서 감사합니다! 시도했지만 다른 문제는 : _addr_을 _mmap() _에 전달하는 방법을 MAP_FIXED를 사용하는 방식으로 지정하는 방법입니다. –

+0

알아내는 것은 당신에게 달려 있습니다. 나는 당신의 프로그램의 소스 코드가 없다. * addr *는 페이지가 정렬되지 않은 null이 아니어야합니다. –

+0

샘플 코드 (원본 게시물을 참조하십시오)와 출력을 생성했습니다. 첫 번째 mmap 이후에 메모리가 예약되어야하고 malloc이 첫 번째 mmap 이후에 메모리를 선택해야합니다. 하지만 여전히 mem 앞에 사용됩니다. 어쩌면 시작 주소를 얻는 방법이 잘못 되었나요? –