Первое, что нужно отметить, это то, что shpgperproc
является настраиваемым загрузчиком, поэтому его можно установить только во время загрузки с помощью соответствующей директивы в loader.conf
, и после этого он доступен только для чтения.
Второе, что следует отметить, это то, что он определен в <arch>/<arch>/pmap.c
, который обрабатывает зависящие от архитектуры части подсистемы vm. В частности, его фактически нет в amd64 pmap.c
— его убрали сравнительно недавно, и я расскажу об этом чуть ниже. Однако он присутствует для других архитектур (i386, arm, ...) и используется одинаково на каждой архитектуре; а именно, это выглядит следующим образом:
void
pmap_init(void)
{
...
TUNABLE_INT_FETCH("vm.pmap.shpgperproc", &shpgperproc);
pv_entry_max = shpgperproc * maxproc + cnt.v_page_count;
и больше нигде не используется. pmap_init()
вызывается только один раз: во время загрузки как часть инициализации подсистемы vm. maxproc
— это просто максимальное количество процессов, которые могут существовать (т. е. kern.maxproc
), а cnt.v_page_count
— это просто количество доступных физических страниц памяти (т. е. vm.stats.v_page_count
).
pv_entry
— это в основном просто виртуальное отображение физической страницы (или, точнее, struct vm_page
, поэтому, если два процесса совместно используют страницу и оба сопоставляют их, для каждого сопоставления будет отдельная структура pv_entry
. Таким образом, заданная страница (struct vm_page
) которые необходимо очистить или выгрузить, или что-то, требующее обновления таблицы страниц hw, список соответствующих отображаемых виртуальных страниц можно легко найти, просмотрев соответствующий список pv_entry
s (в качестве примера взгляните на i386/i386/pmap.c:pmap_remove_all()
).
Использование pv_entry
s делает некоторые операции VM более эффективными, но текущая реализация (по крайней мере, для i386), по-видимому, выделяет статический объем пространства (см. pv_maxchunks
, который устанавливается на основе pv_entry_max
) для pv_chunk
s, которые используются для управления pv_entry
s. Если ядро не может выделить pv_entry
после освобождения неактивных, оно паникует.
Таким образом, мы хотим установить pv_entry_max
в зависимости от того, сколько pv_entry
нам нужно для места; ясно, что нам нужно как минимум столько, сколько есть страниц ОЗУ (отсюда и cnt.v_page_count
). Затем мы хотим учесть тот факт, что многие страницы будут многократно виртуально отображаться разными процессами, поскольку для каждого такого сопоставления необходимо выделить pv_entry
. Таким образом, shpgperproc
, значение которого по умолчанию равно 200 для всех арок, — это просто способ масштабирования. В системе, где многие страницы будут совместно использоваться процессами (скажем, на сильно загруженном веб-сервере с запущенным apache), вполне возможно исчерпать pv_entry
s, поэтому нужно увеличить его.
person
mark.johnston
schedule
06.05.2012