использование системного вызова mmap - PullRequest
1 голос
/ 09 декабря 2011

Я слышал об использовании системного вызова mmap для объединения двух блоков памяти в один непрерывный с флагом MAP_ANONYMOUS, но я не могу найти простой пример использования этого трюка.

Пример в Википедии, в котором реализован оптимизированный кольцевой буфер, для меня слишком сложен ( Статья с кольцевым буфером ).

Можете ли вы привести пример использования флага MAP_ANONYMOUS?

1 Ответ

2 голосов
/ 10 января 2012

Судя по пояснениям, которые вы предоставили в своих комментариях, вы пытаетесь ошибиться в двух вещах, которые не имеют ничего общего друг с другом.

void *part1 = malloc(100);
void *part2 = malloc(250);

Вы хотите манипулировать виртуальной памятью, чтобы эти два блока памяти были адресуемы как 350 непрерывных байтов памяти.

Это невозможно. Прежде всего, блоки памяти, которые у вас есть, в общем случае не будут ни выровнены, ни размером страницы. Вы можете манипулировать виртуальной памятью только в выровненных по размеру страницах. Во-вторых, даже если вам очень повезло, и они выровнены по размеру страницы и по размеру страницы, они, вероятно, происходят из области кучи (область ниже brk()). Я не думаю, что вы можете переназначить или удалить эту область памяти, используя mremap() или munmap(). (Существуют альтернативные реализации malloc(), которые получают память от mmap() и не будут подвержены этой проблеме, но они все еще подвержены первой проблеме.

Но, допустим, у вас есть два блока памяти, которые выровнены по размеру страницы, по размеру страницы и переназначены, и вы хотите переназначить их так, чтобы они были смежными. Скорее всего, вы получили эти блоки из mmap() в первую очередь. Затем вы можете переназначить их на соседние адреса, используя mremap(). Имейте в виду, что mremap() зависит от Linux. Я не знаю о портативном способе сделать это. В псевдокоде:

/* Map some useless memory just to get the kernel to reserve a range
   of addresses for us which will be big enough for both blocks */
address = mmap(NULL, blocksize1+blocksize2, ..., MAP_ANONYMOUS, ...);

/* remap the first block to the the first address in this new range */
mremap(block1, blocksize1, blocksize1, MREMAP_MAYMOVE|MREMAP_FIXED, address);
/* remap the second block to go right after the first block */
mremap(block2, blocksize2, blocksize2, MREMAP_MAYMOVE|MREMAP_FIXED,
        address+blocksize1);
...