mmap报错Invalid argument的解决办法 (一)

2014-11-24 02:37:45 · 作者: · 浏览: 4

mmap这个函数到处都用到,很多问题都是用perror("mmap")出来的结果是Invalid argument

这个问题,我遇到有两种可能导致

1. open文件时的用的访问模式如O_RDONLY, O_WRONLY, or O_RDWR和你mmap的模式如

PROT_EXEC Pages may be executed.

PROT_READ Pages may be read.

PROT_WRITE Pages may be written.

PROT_NONE Pages may not be accessed.


不匹配。

2. 你mmap的文件所属的文件系统,如果是网络上的文件,linux是无法保证文件的一致性的,那么MAP_SHARED所要求的语义就不能够达到,这时就看你所需要的一致性要求了,如果你只需要在内存上操作,不需要保证munmap时把内存flush回文件的话,可以采用MAP_PRIVATE模式,而如果需要保证这种强的一致性要求的话,就必须要用到MAP_SHARED。

我发现我对VIRTUAL BOX共享文件夹下的文件进行mmap操作就不能够保证这个MAP_SHARED,perror的出错信息也报的是Invalid argument,实际上对于其他linux本机文件目录上的文件,这个一致性是可以保证的,也就是说只要除了这种共享的文件,对其他文件进行这个操作是可以正常执行的。

下面附上一个我自己调好的例子

1. mywriteread.c

[cpp]
#include
#include
#include
#include
#include
#include

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

int main(int argc, char * argv[])
{
char * addr;
int fd;
int i;
struct stat sb;
off_t offset, pa_offset;
size_t length;
ssize_t s;
char * buf = "123456789abcdefghijkl";

if (argc < 3 || argc > 4) {
fprintf(stderr, "%s file offset [length]\n", argv[0]);
exit(EXIT_FAILURE);
}


fd = open(argv[1],O_RDWR);
if(fd ==-1)
handle_error("open");

if(fstat(fd,&sb) == -1)
handle_error("fstat");

offset = atoi(argv[2]);
pa_offset = offset & ~(sysconf(_SC_PAGE_SIZE)-1);

if(offset >= sb.st_size){
fprintf(stderr,"offset is past end if file \n");
exit(EXIT_FAILURE);
}

if(argc == 4){
length = atoi(argv[3]);
if(offset + length > sb.st_size)
length = sb.st_size - offset;
}
else{
length = sb.st_size - offset;
}

printf("\tfile size is %d\n",sb.st_size);
printf("length = %d\t, mapped memory length = %d\t, pa_offset = %d\n",length,length + offset -pa_offset, pa_offset);
addr = mmap(NULL,length + offset - pa_offset, PROT_READ|PROT_WRITE,
MAP_SHARED,fd,pa_offset);

if(addr == MAP_FAILED)
handle_error("mmap");


memcpy(addr,buf,10);
printf("check write!\n");
for(i = 0;i<10 ; i++){
printf("new mem[%d] = %c\n",i, *(addr+i));
}

printf("string test = %s\n",(char *)addr);

munmap(addr,length + offset - pa_offset);
return 0;

#include
#include
#include
#include
#include
#include

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

int main(int argc, char * argv[])
{
char * addr;
int fd;
int i;
struct stat sb;
off_t offset, pa_offset;
size_t length;
ssize_t s;
char * buf = "123456789abcdefghijkl";

if (argc < 3 || argc > 4) {
fprintf(stderr, "%s file offset [length]\n", argv[0]);
exit(EXIT_FAILURE);
}


fd = open(argv[1],O_RDWR);
if(fd ==-1)
handle_error("open");

if(fstat(fd,&sb) == -1)
handle_error("fstat");

offset = atoi(argv[2]);
pa_offset = o