[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

mmap investigations



Hi team!

As previously discussed with Michael Vogt on #debian-apt, I've done some investigation
about mmap() and related, and I have following results:

1) mmap() call actually doesn't map whole memory (mmap() has successfully mmap'ed 23 GiB,
of course I have no such amounts of memory on my desktop); process memory are untouched at
all;
2) mmap() call doesn't grow a file attached to it, file size stays untouched directly
after mmap();
3) when writing to mmap'ed region, file size become maximum of offsets that were used for
writing.

These investigations incited me to wonder if we... can simply do mmap(2GiB -1) amount of
memory, without any troubles?!

I have attached C source file, use "gcc -std=gnu99 -Wall -O2 -Wextra bigmmap.c -o bigmmap"
to compile it. Please confirm my results...

-- 
Eugene V. Lyubimkin aka JackYF, Ukrainian C++ developer.
#define _LARGEFILE64_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char* argv[])
{
	if (argc != 2)
	{
		printf("One parameter (number of pages to mmap) required.\n");
		return 1;
	}
	int page_size = sysconf(_SC_PAGE_SIZE);
	unsigned long mmap_size = atol(argv[1]) * page_size;
	printf("Mapping %zd MiB.\n", mmap_size / 1024 / 1024);
	const char filename[] = "binfile";
	int fd = open(filename, O_CREAT | O_RDWR);
	if (fd == -1)
	{
		printf("Cannot open %s.\n", filename);
		return 2;
	}
	/*
	lseek64(fd, mmap_size-1, SEEK_SET);
	write(fd, "\0", 1);
	lseek64(fd, 0, SEEK_SET);
	*/
	void* base = mmap(NULL, mmap_size, PROT_WRITE | PROT_WRITE, MAP_SHARED, fd, 0);
	if (base == MAP_FAILED)
	{
		printf("Cannot mmap :-(\n");
		return 3;
	}
	printf("Bound address: %p\n", base);

	// main loop
	size_t mpos = -1;
	size_t step = 2;
	for (size_t i = 0; i < mmap_size/page_size; i += step)
	{
		usleep(50);
		off_t offset = lseek64(fd, page_size*step, SEEK_CUR);
		write(fd, "\0", 1);
		size_t newpos = offset/1024/1024;
		if (mpos != newpos)
		{
			printf("\rNow at %zd MiB...", newpos);
			fflush(stdout);
			mpos = newpos;
		}
	}

	munmap(base, mmap_size);
	close(fd);
	printf("Done\n");
	return 0;
}

Attachment: signature.asc
Description: OpenPGP digital signature


Reply to: