C 使用mmap将整个文件复制到内存中
我想使用C中的mmap将整个文件复制到内存中。我编写以下代码:C 使用mmap将整个文件复制到内存中,c,file-io,mmap,bus-error,C,File Io,Mmap,Bus Error,我想使用C中的mmap将整个文件复制到内存中。我编写以下代码: #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <sys/types.h> #include <sys/mman.h> #include <sys/stat.h> #include <errno.h> int ma
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <errno.h>
int main(int arg, char *argv[])
{
char c ;
int numOfWs = 0 ;
int numOfPr = 0 ;
int numberOfCharacters ;
int i=0;
int k;
int pageSize = getpagesize();
char *data;
float wsP = 0;
float prP = 0;
int fp = open("2.txt", O_RDWR);
data = mmap((caddr_t)0, pageSize, PROT_READ, MAP_SHARED, fp,pageSize);
printf("%s\n", data);
exit(0);
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int main(int arg,char*argv[]
{
字符c;
int numofs=0;
int numopr=0;
整数字符;
int i=0;
int k;
int pageSize=getpagesize();
字符*数据;
浮动wsP=0;
浮动prP=0;
int fp=打开(“2.txt”,O_RDWR);
数据=mmap((caddr t)0,页面大小,保护读取,地图共享,fp,页面大小);
printf(“%s\n”,数据);
出口(0);
}
当我执行代码时,我得到总线错误
消息。
接下来,我想迭代这个复制的文件并对其执行一些操作。
如何正确复制文件?mmap的最后一个参数是文件内的偏移量,即映射到内存的文件部分的起始位置。你的情况应该是0
data = mmap(NULL, pageSize, PROT_READ, MAP_SHARED, fp,0);
如果您的文件短于页面大小
,您将无法使用文件末尾以外的地址。要使用全尺寸,请在调用mmap
之前将尺寸扩展到pageSize
。使用类似于:
ftruncate(fp, pageSize);
如果要写入内存(文件),还应使用PROT_write标志。即
data = mmap(NULL, pageSize, PROT_READ|PROT_WRITE, MAP_SHARED, fp,0);
如果您的文件不包含0个字符(作为字符串结尾),并且您希望将其打印为字符串,则应使用明确指定的最大大小的printf
:
printf("%.*s\n", pageSize, data);
当然,正如@Jongware所指出的,您应该测试-1的
open
和mmap
的MAP\u失败的结果 mmap的最后一个参数是文件内的偏移量,映射到内存的文件部分从这里开始。你的情况应该是0
data = mmap(NULL, pageSize, PROT_READ, MAP_SHARED, fp,0);
如果您的文件短于页面大小
,您将无法使用文件末尾以外的地址。要使用全尺寸,请在调用mmap
之前将尺寸扩展到pageSize
。使用类似于:
ftruncate(fp, pageSize);
如果要写入内存(文件),还应使用PROT_write标志。即
data = mmap(NULL, pageSize, PROT_READ|PROT_WRITE, MAP_SHARED, fp,0);
如果您的文件不包含0个字符(作为字符串结尾),并且您希望将其打印为字符串,则应使用明确指定的最大大小的printf
:
printf("%.*s\n", pageSize, data);
当然,正如@Jongware所指出的,您应该测试-1的open
和mmap
的MAP\u失败的结果 2件事
mmap()
的第二个参数是要在地址空间中显示的文件部分的大小。最后一个是要从中创建贴图的文件中的偏移量。这意味着,正如您调用的mmap()
一样,您将只看到文件中从偏移量4096开始的1页(在x86和ARM上为4096字节)。如果您的文件小于4096字节,则将有无映射,mmap()
将返回MAP\u FAILED
(即(caddr\u t)-1
)。您没有检查函数的返回值,因此下面的printf()
取消引用非法指针=>总线错误
使用带有字符串函数的内存映射可能很困难。如果文件不包含二进制文件0。这些函数可能会尝试访问文件的映射大小,然后触摸未映射内存李>
要打开文件的内存,必须知道文件的大小
struct stat filestat;
if(fstat(fd, &filestat) !=0) {
perror("stat failed");
exit(1);
}
data = mmap(NULL, filestat.st_size, PROT_READ, MAP_SHARED, fp, 0);
if(data == MAP_FAILED) {
perror("mmap failed");
exit(2);
}
编辑:内存映射将始终以页面大小的倍数打开。这意味着最后一页将由0填充,直到页面大小的下一个倍数。通常,使用带有字符串函数的内存映射文件(如printf()
)的程序大部分时间都可以工作,但当映射一个大小正好是页面大小(4096、8192、12288等)倍数的文件时,程序会突然崩溃。传递给mmap()
大于实际文件大小的建议通常在Linux上有效,但不可移植,甚至违反了Posix,Posix明确指出超出文件大小的映射是未定义的行为。唯一可移植的方法是不要在内存映射上使用字符串函数。2件事
mmap()
的第二个参数是要在地址空间中显示的文件部分的大小。最后一个是要从中创建贴图的文件中的偏移量。这意味着,正如您调用的mmap()
一样,您将只看到文件中从偏移量4096开始的1页(在x86和ARM上为4096字节)。如果您的文件小于4096字节,则将有无映射,mmap()
将返回MAP\u FAILED
(即(caddr\u t)-1
)。您没有检查函数的返回值,因此下面的printf()
取消引用非法指针=>总线错误
使用带有字符串函数的内存映射可能很困难。如果文件不包含二进制文件0。这些函数可能会尝试访问文件的映射大小,然后触摸未映射内存李>
要打开文件的内存,必须知道文件的大小
struct stat filestat;
if(fstat(fd, &filestat) !=0) {
perror("stat failed");
exit(1);
}
data = mmap(NULL, filestat.st_size, PROT_READ, MAP_SHARED, fp, 0);
if(data == MAP_FAILED) {
perror("mmap failed");
exit(2);
}
编辑:内存映射将始终以页面大小的倍数打开。这意味着最后一页将由0填充,直到页面大小的下一个倍数。通常,使用带有字符串函数的内存映射文件(如printf()
)的程序大部分时间都可以工作,但当映射一个大小正好是页面大小(4096、8192、12288等)倍数的文件时,程序会突然崩溃。传递给mmap()
大于实际文件大小的建议通常在Linux上有效,但不可移植,甚至违反了Posix,Posix明确指出超出文件大小的映射是未定义的行为。唯一的便携方式