When I run this code I get "mmap: Operation not supported", according to mmap man that's because one of the flags is invalid (validated by MAP_SHARED_VALIDATE). The "bad" flag is MAP_FIXED_NOREPLACE
#include <fcntl.h>
#include <errno.h>
#include <sys/mman.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char** argv)
{
int fd_addr = open("test", O_CREAT | O_RDWR);
if (fd_addr == -1) {
std::cout << "open: " << strerror(errno) << "\n";
return EXIT_FAILURE;
}
if (ftruncate(fd_addr, 100) == -1) {
std::cout << "ftruncate: " << strerror(errno) << "\n";
return EXIT_FAILURE;
}
auto mem =mmap((void*)0x7f4b1618a000, 1, PROT_READ | PROT_WRITE, MAP_FIXED_NOREPLACE | MAP_SHARED_VALIDATE | MAP_LOCKED, fd_addr, 0);
if (mem == MAP_FAILED) {
std::cout << "mmap: " << strerror(errno) << "\n";
return EXIT_FAILURE;
}
}
Any sane ideas what that could be and how to figure out what the problem is? I use Ubuntu 20 (kernel 5.4.0-131-generic) and g -11 (with glibc 2.31)
g -11 (Ubuntu 11.1.0-1ubuntu1~20.04) 11.1.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
ldd (Ubuntu GLIBC 2.31-0ubuntu9.9) 2.31
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.
Replacing MAP_FIXED_NOREPLACE with MAP_FIXED works just fine. Compiling like that:
g -11 -g0 -Ofast -DNDEBUG -Wall -Werror --std=c 2a -march=native -flto -fno-rtti main.cpp -pthread -lrt
CodePudding user response:
The only way to answer your question is to look at the source. Taking an excerpt from do_mmap:
switch (flags & MAP_TYPE) {
case MAP_SHARED:
/*
* Force use of MAP_SHARED_VALIDATE with non-legacy
* flags. E.g. MAP_SYNC is dangerous to use with
* MAP_SHARED as you don't know which consistency model
* you will get. We silently ignore unsupported flags
* with MAP_SHARED to preserve backward compatibility.
*/
flags &= LEGACY_MAP_MASK;
fallthrough;
case MAP_SHARED_VALIDATE:
if (flags & ~flags_mask)
return -EOPNOTSUPP;
and comparing your flags
against those in LEGACY_MAP_MASK
,
it becomes evident that MAP_FIXED_NOREPLACE
is not part of LEGACY_MAP_MASK
, which returns the "operation not supported" error you report.
In this case, the MAP_FIXED_NOREPLACE
bits result in an extra check up front and otherwise behaves as MAP_FIXED
.
Long story short: in this situation you can replace MAP_SHARED_VALIDATE
with MAP_SHARED
without loss of functionality.
Doing what you suggested (MAP_FIXED_NOREPLACE
to MAP_FIXED
) has the potential of accidentally creating overlapping memory mappings.