简体   繁体   中英

mmap64() works in Red Hat 6.6 but not in Red Hat 7.2

The function call to mmap64() is as follows:

addr = (unsigned char*) mmap64(NULL, regionSize, PROT_READ|PROT_WRITE, MAP_SHARED, FileDesc, (unsigned long long)regionAddr);

The arguments typically have values as follows:

regionSize = 0x20000;
FileDesc   = 27;
regionAddr = 0x332C0000;

Obviously in the code these values are not hard-coded like that, but I just want to show you what the typical values for them will be.

The problem:

mmap64() call works perfectly in Red Hat Linux 6.6, kernel version: 2.6.32-504.16.2.el6.x86_64. It fails in Red Hat Linux 7.2, kernel version: 3.10.0-327.13.1.el7.x86_64.

No difference in code as far as I'm aware of.

The errno returned is "Invalid argument" or errno #22 (EINVAL). Looking at this reference http://linux.die.net/man/3/mmap64 , I see 3 possiblilities for the EINVAL error:

  1. We don't like addr, length, or offset (eg, they are too large, or not aligned on a page boundary). -> most likely culprit in my situation.
  2. (since Linux 2.6.12) length was 0. -> Impossible, I checked length (regionSize) value in debug print, it was 0x20000.
  3. flags contained neither MAP_PRIVATE or MAP_SHARED, or contained both of these values. -> Can't be this as you can see from my function call, only MAP_SHARED flag was given as argument.

So I'm stuck at the moment. Not sure how to debug this. This problem is 100% reproducible. Anyone have tips on what could have changed between the two OS versions to cause this?

Transferring comments into an answer (with some comments trimmed as not relevant).

Why not simply use mmap() without the suffix if you're building 64-bit executables? Does that make any difference to your problem?

However, I think your problem is what you call regionAddr . The last argument to mmap64() is called offset in the synopsis, and:

offset must be a multiple of the page size as returned by sysconf(_SC_PAGE_SIZE) .

Is your value of regionAddr a multiple of the page size? It looks to me like it has too few trailing zeros in the hex (it is a multiple of 512, but not a multiple of 4K or larger).


Note that the question originally had a different value on display for regionAddr — see also the comments below.

 regionAddr = 0x858521600; 

and

 addr = (unsigned char*) mmap64(NULL, regionSize, PROT_READ|PROT_WRITE, MAP_SHARED, FileDesc, (unsigned long long)regionAddr); 

With the revised information (that the value in regionAddr is 0x332C0000 or decimal 828521600), it is less than obvious what is going wrong.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM