strace是你的朋友:
$ strace ./mmap-example mmap-example.c
...
... (lots of output)
...
open("mmap-example.c", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=582, ...}) = 0
mmap(NULL, 582, PROT_READ, MAP_FILE, 3, 0) = -1 EINVAL (Invalid argument)
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++
mmap 手册页告诉你所有你需要知道的 ;)
-
EINVAL 我们不喜欢 addr、length 或 offset(例如,他们也喜欢
大,或未在页面边界上对齐)。
-
EINVAL(自 Linux 2.6.12 起)length 为 0。
-
EINVAL flags 既不包含MAP_PRIVATE 也不包含MAP_SHARED,或者
包含这两个值。
-EINVAL 错误是由不能为 0 的标志引起的。必须选择 MAP_PRIVATE 或 MAP_SHARED。我已经能够通过在 Linux x86-64 上使用 MAP_PRIVATE 使其工作。
所以,您只需将 MAP_PRIVATE 添加到 mmap():
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/io.h>
#include <sys/mman.h>
int main(int argc, char const *argv[])
{
unsigned char *f;
int size;
struct stat s;
const char * file_name = argv[1];
int fd = open (argv[1], O_RDONLY);
/* Get the size of the file. */
int status = fstat (fd, & s);
size = s.st_size;
f = (char *) mmap (0, size, PROT_READ, MAP_PRIVATE, fd, 0);
for (int i = 0; i < size; i++) {
char c;
c = f[i];
putchar(c);
}
return 0;
}
注意:我的第一个答案确实包括EINVAL 的另一个可能原因:
size 必须是系统页面大小的整数倍。到
使用getpagesize()函数获取页面大小。
这实际上不是必需的,但是您必须考虑到,无论哪种方式,映射都将始终以系统页面大小的倍数执行,因此如果您想计算多少内存实际上可以通过返回的指针获得,更新size如下:
int pagesize = getpagesize();
size = s.st_size;
size += pagesize-(size%pagesize);