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 <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#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 <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#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;
2. b.data
[cpp]
aaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[root@localhost tryrw]# ./mywr b.data 0 10
file size is 120
length = 10 , mapped memory length = 10 , pa_offset = 0
check write!
new mem[0] = 1
new mem[1] = 2
new mem[2] = 3
new mem[3] = 4
new mem[4] = 5
new mem[5] = 6
new mem[6] = 7
new mem[7] = 8
new mem[8] = 9
new mem[9] = a
string test = 123456789aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaa