1

What is the proper way to allocate a specific region of memory using 'mmap' in C? I've read /proc/self/maps to determine that the area is available.

I've tried the following, but it crashes when trying to write to the allocated memory:

// rdram is defined in header as:  #define rdram ((unsigned int *)0x80000000)
     printf( "rdram=0x%x", (int)rdram );
     printf( "munmapping" );
     munmap ((void*)0x80000000, 0x800000);
     printf( "mmapping" );
     if(mmap ((void*)0x80000000, 0x800000,
            PROT_READ | PROT_WRITE,
            MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
            -1, 0) <= 0)
     {
         printf( "mmap(0x80000000) failed" );
     }
     else
     {
         for (i=0; i<(0x800000/4); i++)
         {
             printf( "writing a zero at 0x%x", (0x80000000 + i) );
             rdram[i]=0;    // <<---------CRASH HERE--------<<
         }
         printf( "done writing zeros" );
      }

It was suggested on my earlier question (which got closed for not being stated clearly), that I am not properly detecting when mmap failed, and that I should use posix_typed_mem_open instead of -1 for the fildes parameter. I thought I would try the following (please let me know if there is something wrong with this):

 int m;
 int p;

 printf( "rdram=0x%x", (int)rdram );
 printf( "munmapping" );
 munmap ((void*)0x80000000, 0x800000);
 printf( "posix_typed_mem_open" );
 p = posix_typed_mem_open( "/memory/ram", O_RDWR, POSIX_TYPED_MEM_ALLOCATE_CONTIG );
 printf( "mmapping" );
 m = (int) mmap ((void*)0x80000000, 0x800000,
             PROT_READ | PROT_WRITE,
             MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
             p, 0);
 if( m == (int) MAP_FAILED )
 {
     printf( "mmap failed" )
 }
 else
 {
     for (i=0; i<(0x800000/4); i++)
     {
         printf( "writing a zero at 0x%x", (0x80000000 + i) );
         rdram[i]=0;
     }
     printf( "done writing zeros" );
 }

This is being run on one of one of my testers' devices (the memory mapping on my device is not suitable), so I'd like to know this makes sense before I have him run it to see what kind of output he gets.

paulscode
  • 1,049
  • 1
  • 12
  • 29
  • Maybe I missed something obvious, but why don't you just call malloc and let the c-library handle the dirt stuff? – Nils Pipenbrinck Dec 02 '11 at 08:31
  • Because malloc does not let you specify where the allocated memory is located. As indicated in the question, I need to allocate a specific region of memory (0x80000000 in this case). – paulscode Dec 02 '11 at 10:29
  • @paulcode: The code looks fine now .As for the output of this code, I am a bit skeptical.You are trying to access 0x80000000 (physical memory) via your process (virtual memory). I dont think you can access part of the main memory (unless you write a driver module to get the actual address itself). Even if you are able to get hold of the physical address, you would need to lock it at the kernel level so that it is never given to some other process. Let me know what output you get from your tester. – tomkaith13 Dec 02 '11 at 22:40
  • Sadly, it appears that posix_typed_mem_open is not implemented in the Android NDK :( Any other ideas I could use to come up with a value to use for fildes? – paulscode Dec 03 '11 at 02:35
  • I had it print out errno, and got 12 (ENOMEM). According to the documentation, this means "MAP_FIXED was specified, and the range [addr,addr+len) exceeds that allowed for the address space of a process". I guess that means the address 0x80000000 is too high? Wish there was a way to extend this limit somehow.. – paulscode Dec 03 '11 at 03:18

2 Answers2

1

Are you trying to map virtual or physical memory? If virtual, then you're on right track but might be hitting some issue in Android with your first approach. Typed memory objects are not required, however, the kernel takes the first argument to mmap as hint only. The ENOMEM suggests that you're hitting some form of limit set on your device, though.

If your goal was allocation of physical memory, what you need to do is to mmap /dev/mem (requires root, or changing permissions on it) with the offset set to address you want.

p_l
  • 1,179
  • 8
  • 17
0

Just try like this

/* 使用映射 /dev/zero 分配内存页 */
memFd = open("/dev/zero", O_RDONLY);
if (memFd < 0) {
    jniThrowException(mJniEnv, RUNTIME_EXCEPTION, "open /dev/zero fail!");

    return MR_FAILED;
}

memBase = (char *) mmap(NULL, memLen, PROT_READ | PROT_WRITE | PROT_EXEC,
        MAP_PRIVATE, memFd, 0);
if (memBase == MAP_FAILED) {
    jniThrowException(mJniEnv, OUTOFMEMORY_ERROR, "");
    close(memFd);

    return MR_FAILED;
}