I have read many SO (and other) questions, but I couldn't find one that helped me. I want to mmap
two files at once and copy their content byte-by-byte (I know this seems ridiculous, but this is my minimal reproducibly example). Therefore I loop through every byte, copy it, and after the size of one page in my files, I munmap
the current page and mmap
the next page. Imo there should only ever be one page (4096 bytes) of each file be needed so there shouldn't be any memory problem.
Also, if the output file is too small, the memory is allocated via posix_fallocate
, which runs fine. I a lack of memory space in the hard drive can't be the problem either imo.
But as soon as I am going for a bit larger files with ~140 MB, I get the cannot allocate memory
error from the output-file that I am writing into. Do you guys have any idea how this is?
#include <sys/types.h>
#include <sys/mman.h>
#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <iostream>
#include <bitset>
#include <fcntl.h>
#include <sys/stat.h>
#include <math.h>
#include <errno.h>
using namespace std;
int main()
{
char file_input[] = "medium_big_file";
char file_output[] = "foo_output";
int fd_input = -1;
int fd_output = -1;
unsigned char *map_page_input, *map_page_output;
struct stat stat_input, stat_output;
if ((fd_input = open(file_input, O_RDONLY)) == -1 ||
(fd_output = open(file_output, O_RDWR|O_CREAT, 0644)) == -1) {
cerr << "Error on open()" << endl;
return EXIT_FAILURE;
}
// get file size via stat()
stat(file_input, &stat_input);
stat(file_output, &stat_output);
const size_t size_input = stat_input.st_size;
const size_t size_output = stat_output.st_size;
const size_t pagesize = getpagesize();
size_t page = 0;
size_t pos = pagesize;
if (size_output < size_input) {
if (posix_fallocate(fd_output, 0, size_input) != 0) {
cerr << "file space allocation didn't work" << endl;
return EXIT_FAILURE;
}
}
while(pos + (pagesize * (page-1)) < size_input) {
// check if input needs the next page
if (pos == pagesize) {
munmap(&map_page_input, pagesize);
map_page_input = (unsigned char*)mmap(NULL, pagesize, PROT_READ,
MAP_FILE|MAP_PRIVATE, fd_input, page * pagesize);
munmap(&map_page_output, pagesize);
map_page_output = (unsigned char*)mmap(NULL, pagesize,
PROT_READ|PROT_WRITE, MAP_SHARED, fd_output, page * pagesize);
page += 1;
pos = 0;
if (map_page_output == MAP_FAILED) {
cerr << "errno: " << strerror(errno) << endl;
cerr << "mmap failed on page " << page << endl;
return EXIT_FAILURE;
}
}
memcpy(&map_page_output[pos], &map_page_input[pos], 1);
pos += 1;
}
munmap(&map_page_input, pagesize);
munmap(&map_page_output, pagesize);
close(fd_input);
close(fd_output);
return EXIT_SUCCESS;
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…