от
Я попытался создать отображение
MAP_GROWSDOWN
с ожиданием, что оно будет расти автоматически. Как указано на странице руководства:   MAP_GROWSDOWN      Этот флаг используется для стеков. Это указывает системе виртуальной памяти ядра, что отображение должно распространяться вниз в   объем памяти. Обратный адрес на одну страницу меньше области памяти   это фактически создается в виртуальном адресном пространстве процесса.   Если дотронуться до адреса на странице «guard» под отображением, произойдет   отображение для увеличения на страницу. Этот рост может повторяться до   отображение растет с точностью до страницы верхнего конца следующего нижнего   сопоставление, после чего прикосновение к странице «охранник» приведет к   
SIGSEGV
сигнал. Поэтому я написал следующий пример для проверки роста отображения:
#ifndef _GNU_SOURCE
    #define _GNU_SOURCE
#endif
#include 
#include 
#include 
#include 
#include 
#include 

int main(void){
    char *mapped_ptr = mmap(NULL, 4096,
                            PROT_READ | PROT_WRITE,
                            MAP_ANONYMOUS | MAP_PRIVATE | MAP_STACK | MAP_GROWSDOWN,
                            

Поэтому я получил SEGV
вместо того, чтобы увеличивать отображение. Что это значит, растя здесь?              

Ваш ответ

Отображаемое имя (по желанию):
Конфиденциальность: Ваш электронный адрес будет использоваться только для отправки уведомлений.
Анти-спам проверка:
Чтобы избежать проверки в будущем, пожалуйста войдите или зарегистрируйтесь.

2 Ответы

0 голосов
от
Заменить:
volatile char *c_ptr_1 = mapped_ptr 

С

volatile char *c_ptr_1 = mapped_ptr;
Так как:   Адрес возврата на одну страницу ниже области памяти, которая фактически создается в виртуальном адресном пространстве процесса. Если дотронуться до адреса на странице «guard» под отображением, отображение увеличится на страницу. Обратите внимание, что я протестировал решение, и оно работает, как и ожидалось, в ядре 4.15.0-45-generic.     
0 голосов
от
Прежде всего, вы не хотите
MAP_GROWSDOWN
, и это не то, как работает стек основных потоков. Анализ отображения памяти процесса с помощью pmap. [стек] Ничто не использует это, и почти ничто не должно использовать это. Материал на странице руководства, в котором говорится, что он «используется для стеков», неверен и его следует исправить. Я подозреваю, что это может быть ошибка (потому что ничто не использует это так, обычно никто не заботится или даже замечает, если это ломается.) Ваш код работает для меня, если я изменю вызов
mmap
, чтобы отобразить более 1 страницы. В частности, я попробовал
4096 * 100
. Я использую Linux 5.0.1 (Arch Linux) на голом железе (Skylake).
/proc/PID/smaps
показывает флаг
gd
. И затем (при однократном шаге asm) запись
maps
действительно меняется на более низкий начальный адрес, но тот же конечный адрес, поэтому он буквально растет вниз, когда я начинаю с сопоставления 400k. Это дает начальное выделение 400 КБ выше адреса возврата, которое увеличивается до 404 КБ при запуске программы. (Размер для отображения
_GROWSDOWN
не является пределом роста или чем-то в этом роде.) https://bugs.centos.org/view.php?id=4767 может быть связано; что-то изменилось между версиями ядра в CentOS 5.3 и 5.5. И / или это было связано с работой на виртуальной машине (5.3), а не с ростом и отказом от голого металла (5.5). Я упростил C, чтобы использовать
ptr[ и т. Д.

int main(void){
    volatile char *ptr = mmap(NULL, 4096*100,
                            PROT_READ | PROT_WRITE,
                            MAP_ANONYMOUS | MAP_PRIVATE | MAP_STACK | MAP_GROWSDOWN,
                            

Компиляция с gcc  дает asm, который хорошо подходит для одного шага.



Кстати, разные слухи об удалении флага из glibc явно ошибочны. Этот источник компилируется, и ясно, что он также поддерживается ядром, а не игнорируется. (Хотя поведение, которое я вижу с размером 4096 вместо 400 кБ, в точности соответствует тому, что флаг молча игнорируется. Однако gd
VmFlag все еще присутствует в
smaps
, поэтому он не игнорируется на этом этапе.) Я проверил, и было место для его роста, не приближаясь к другому отображению. Итак, IDK, почему он не вырос, когда отображение GD было всего 1 страницей. Я попробовал пару раз, и он каждый раз работал с ошибками. С большим начальным отображением это никогда не нарушалось. Оба раза были с сохранением возвращаемого значения mmap (первой страницы собственно сопоставления), затем хранилище на 4095 байт ниже этого.     
Добро пожаловать на сайт ByNets, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...