Вот мое предположение.Я предполагаю, что вторая программа просто расширяет внутреннюю структуру данных, описывающую одно отображение, чтобы включить еще одну страницу.Первый мог бы сделать это, но вместо этого он должен был бы расширяться в обратном направлении, и я держу пари, что код специального случая для объединяющихся отображений даже не проверяет это.,Будет некоторое количество отображений, используемых для разделяемых библиотек и т. П., Поэтому вам будет доступно менее 65536 отображений.И 65536 - это размер, который многие ядра используют для структуры данных.
Я бы предложил посмотреть /proc/<pid>/maps
и посмотреть, сколько карт указано в каждом случае, когда программа спит.Чтобы облегчить это, вы можете распечатать результат getpid()
при печати сообщения «Готово».
Я не могу воспроизвести вашу проблему напрямую, поэтому кажется, что обратный случай был обработанправильно в моей системе.Вывод uname -a
в моей системе таков:
Linux a_hostname.somewhere 2.6.35.11-83.fc14.x86_64 #1 SMP Mon Feb 7 07:06:44 UTC 2011 x86_64 x86_64 x86_64 GNU/Linux
Но эта программа повторяет вашу проблему:
#include <iostream>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#define PER_PAGE_SIZE 4096
#define MMAP(fd,offset) mmap (NULL,PER_PAGE_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_NORESERVE,fd,offset)
int main()
{
using ::std::cout;
using ::std::endl;
int j = 0;
int fd = open("dat.tmp",O_RDWR);
char catcmd[] = "cat /proc/99999/maps_padding";
for(int i = 131071 ; i >= 0; i-=2){
++j;
void* r = MMAP(fd,i*4096);
if(r == MAP_FAILED){
cout << j << ", " << strerror(errno) << '\n';
break;
}
}
::std::snprintf(catcmd, sizeof(catcmd), "cat /proc/%d/maps", getpid());
cout.flush();
::std::system(catcmd);
cout << "done " << j << endl;
sleep(5);
}
Как вы можете видеть, если вы пропустите на 2 при переходев обратном направлении проблема все еще возникает.И вывод cat /proc/<pid>/maps
из звонка на system
показывает, что на самом деле существуют тысячи отдельных карт.
Если я перестану пропускать 2 и просто вернусь назад, я получу 2 карты, одна большаяи еще один не такой большой.Ядро объединяет смежные карты в одну карту, если может.
В качестве еще одного подтверждающего доказательства того, что ваша проблема, как я описываю, есть хорошее обсуждение /proc/sys/vm/max_map_count
.Установка этой переменной позволяет вам изменить количество карт, и по умолчанию установлено значение 65530.