我有这个程序应该以读写模式映射文件并能够编辑其内容。此处写的文件大约为40-50 GB,因此我需要mmap64
。问题是,虽然mmap64
没有返回错误,但它返回的地址无法访问。
#include <assert.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <unistd.h>
typedef unsigned long long u64;
void access_test(u64 p, u64 sz)
{
u64 i;
char tmp;
for (i=0; i<sz; i++) {
tmp = *(char*)(p+i);
}
}
int main(int argc, char *argv[])
{
int fd;
long long int sz, p;
struct stat buf;
fd = open(argv[1], O_RDWR, 0x0666);
if (fd == -1) {
perror("open");
return 1;
}
fstat64(fd, &buf);
sz = buf.st_size;
printf("File size: 0x%016llx\n", sz);
p = mmap64 (0, buf.st_size, PROT_READ | PROT_WRITE , MAP_SHARED, fd, 0);
if (p == -1) {
perror ("mmap");
return 1;
}
access_test(p,sz);
if (close (fd) == -1) {
perror ("close");
return 1;
}
if (munmap ((void*)p, buf.st_size) == -1) {
perror ("munmap");
return 1;
}
return 0;
}
结果是一个小文件:
$ ./testmmap minicom.log
File size: 0x0000000000000023
[1] 8282 segmentation fault (core dumped) ./testmmap minicom.log
同样适合大人物。
答案 0 :(得分:4)
以下是启用警告的结果:
$ gcc mmp.c -Wall -g
mmp.c: In function ‘access_test’:
mmp.c:18:10: warning: variable ‘tmp’ set but not used [-Wunused-but-set-variable]
char tmp;
^
mmp.c: In function ‘main’:
mmp.c:36:5: warning: implicit declaration of function ‘fstat64’ [-Wimplicit-function-declaration]
fstat64(fd, &buf);
^
mmp.c:40:5: warning: implicit declaration of function ‘mmap64’ [-Wimplicit-function-declaration]
p = mmap64 (0, buf.st_size, PROT_READ | PROT_WRITE , MAP_SHARED, fd, 0);
这里的最后两个警告非常重要。他们说没有mmap64的原型。因此C给你一个默认原型,这是错误的,至少对于mmap64()调用(因为原型将返回一个int,它不能代表64位Linux主机上的指针)
fstat64()的参数也是struct stat64
BTW,这是另一个问题。
如果要使fstat64()/mmap64()
函数可用,则需要使用_LARGEFILE和LARGEFILE64_SOURCE #define编译代码,请参阅信息here,因此您应该将其编译为例如:
gcc -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE mmp.c -Wall -g
但是没有必要这样做。编译时,只需调用普通fstat()
和mmap()
以及#define _FILE_OFFSET_BITS=64
即可。 e.g:
gcc -D_FILE_OFFSET_BITS=64 mmp.c -Wall -g
这将启用对大文件的支持,例如如果需要,将mmap()调用转换为mmap64()(例如,如果你在32位主机上)。
如果你试图mmap()一个50 GB的文件,你无论如何都需要在64位主机上,而在64位Linux主机上则不需要任何这个--mmap()和fstat( )处理大文件而无需任何操作。
下一个问题是您将mmap()
的返回值赋给整数。这可能会起作用,但代码看起来确实很奇怪。如果您想将该事物视为char *
,请将其指定给char *
。不要使用将指针转换为64位整数类型来玩弄技巧。
E.g。你的访问功能应该是:
void access_test(char *p, u64 sz)
{
u64 i;
char tmp;
for (i=0; i<sz; i++) {
tmp = p[i];
}
}
p
应在main()中声明为char *p;
,如果您打算将数据视为二进制数据,则使用uint8_t *p;
。