void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
我不知道使用mmap
标志时MAP_PRIVATE
的工作原理。我可以将大于文件length
大小的fd
传递给mmap
吗?这样之后,我可以读写超出文件大小但在length
范围内的内存吗?
我正在编写一些代码来计算文件的MD5。我决定编写仅将数据作为void*
和size_t len
进行操作的函数,而不使用标准库流函数。以前,我使用malloc
并将文件复制到某些使用malloc分配的内存中,但事实证明,这对于大型文件来说非常慢,而且一旦我发现有关mmap
的信息就很愚蠢。
我要解决的问题是,在计算任何数据的MD5之前,some padding and information is appended to the data that will be hashed.使用先前的malloc
解决方案,我只需要计算需要追加多少数据,然后再计算realloc
并写入。现在,我正在预先计算需要添加多少数据,并将此增加的长度传递给mmap
。在小文件上,这可以正常工作,但在大文件上尝试写入超出文件大小的地址会导致分段错误。
这显然是我想要做的:
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
// The Data + length struct
struct data{
void* s;
size_t len;
};
//mmap on opened file descriptor into a data struct
struct data* data_ffile(int fd)
{
struct data* ret = malloc(sizeof(struct data));
//Get the length of the file
struct stat desc;
fstat(fd, &desc);
ret->len = (size_t)desc.st_size;
//Calculate the length after appending
size_t new_len = ret->len + 1;
if((new_len % 64) > 56)
new_len += (64 * 2) - (new_len % 64);
else if((new_len % 64) <= 56)
new_len += 64 - (new_len % 64);
//Map the file with the increased length
ret->s = mmap(NULL, new_len, PROT_READ | PROT_WRITE,
MAP_PRIVATE, fd, 0);
if(ret->s == MAP_FAILED) exit(-1);
return ret;
}
//Append a character to the mmap'ed data
void data_addchar(struct data* w, unsigned char c)
{
((char*)w->s)[w->len++] = c;
return;
}
void md5_append(struct data* md)
{
data_addchar(md, 0x80);
while((md->len % 64) != 56){
data_addchar(md, (char)0);
}
}
int main(int argc, char** argv)
{
int fd = open(argv[1], O_RDONLY);
struct data* in = data_ffile(fd);
close(fd);
md5_append(in);
}
我对mmap
有基本的误解吗?>>
void * mmap(void * addr,size_t长度,int prot,int标志,int fd,off_t偏移量);我不完全了解使用MAP_PRIVATE标志时mmap的工作方式。我可以传递大于大小的长度吗?
我可以将长度大于文件fd的长度传递给mmap吗?之后,我可以读写超出文件大小但在长度范围内的内存吗?