Как я могу предварительно заблокировать и заблокировать страницы памяти, которые mmap'd с помощью MAP_PRIVATE?Linux

Ответить Пред. темаСлед. тема
Anonymous
 Как я могу предварительно заблокировать и заблокировать страницы памяти, которые mmap'd с помощью MAP_PRIVATE?

Сообщение Anonymous »

Я пишу Linux-приложение реального времени, в котором мне нужно предотвратить возникновение ошибок страниц после первоначального запуска моего приложения.
Моей первоначальной мыслью было просто вызвать mlockall( MCL_CURRENT | MCL_FUTURE);. Вызов этой функции не возвращает код ошибки, но если я проверю страницы своего процесса, то окажется, что есть еще много страниц, размер Locked: которых равен 0 (что, как я предполагаю, означает, что эти страницы все еще могут вызывать ошибку страницы). ).
$ cat /proc/
/smaps | grep -B 21 -A 2 "Locked: 0 kB" | grep -B 1 "^Size:" | grep -v "Size" | grep -v "^\-\-"
7effd0021000-7effd4000000 ---p 00000000 00:00 0
7effd4021000-7effd8000000 ---p 00000000 00:00 0
7effd80c6000-7effdc000000 ---p 00000000 00:00 0
7effddf02000-7effddfa0000 rw-s 00000000 00:05 368 /dev/some_char_device
7effddfa0000-7effde1a0000 rw-s f0000000 00:05 368 /dev/some_char_device
7effde1c1000-7effde1c2000 ---p 00000000 00:00 0
7effde1c6000-7effde1ca000 rw-s f7c00000 00:05 368 /dev/some_char_device
7effde1ca000-7effde1cb000 ---p 00000000 00:00 0
7effe221b000-7effe221c000 ---p 00000000 00:00 0
7effe2220000-7effe2223000 rw-s 00000000 00:05 90 /dev/another_char_device
7effe22df000-7effe22e0000 ---p 00013000 08:02 2234654 //shared_library1.so
7effe22fd000-7effe22fe000 ---p 0000c000 08:02 2231701 //shared_library2.so
7effe23fc000-7effe23fd000 ---p 0001c000 08:02 2234652 //shared_library3.so
7effe2e15000-7effe2e16000 ---p 00215000 08:02 1957 /usr/lib/x86_64-linux-gnu/libc.so.6
7effe2e40000-7effe2e41000 ---p 00011000 08:02 2234649 //shared_library4.so
7effe2f14000-7effe2f15000 ---p 00046000 08:02 2232115 //shared_library5.so
7effe321a000-7effe321b000 ---p 0021a000 08:02 855 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30
7effe3258000-7effe3259000 ---p 0001f000 08:02 2234643 //shared_library6.so
7effe327d000-7effe327e000 ---p 00021000 08:02 2234641 //shared_library7.so
7effe328a000-7effe328b000 ---p 00009000 08:02 2232116 //shared_library8.so
7effe348e000-7effe348f000 ---p 00102000 08:02 91759 //shared_library9.so
7effe34c6000-7effe34c8000 r--p 00000000 08:02 175 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7effe34f2000-7effe34fd000 r--p 0002c000 08:02 175 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7ffc1d1b0000-7ffc1d1b4000 r--p 00000000 00:00 0 [vvar]
7ffc1d1b4000-7ffc1d1b6000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]

Некоторые попытки и некоторые вопросы...
Попытка: переместить расположение mlockall в функцию инициализацииМоя основная функция имеет несколько вызовов dlopen. Раньше вызов mlockall выполнялся после вызовов dlopen. Перемещение вызова mlockall перед вызовами dlopen, похоже, блокирует память общих библиотек, которые загружаются после него. Однако он не блокирует память общих библиотек, загруженных перед вызовом mlockall (эти общие библиотеки связываются во время компиляции и указываются в исполняемом файле).
Почему MCL_CURRENT не блокирует уже загруженные библиотеки?
$ cat /proc//smaps | grep -B 21 -A 2 "Locked: 0 kB" | grep -B 1 "^Size:" | grep -v "Size" | grep -v "^\-\-"
7fef0c021000-7fef10000000 ---p 00000000 00:00 0
7fef10021000-7fef14000000 ---p 00000000 00:00 0
7fef140c6000-7fef18000000 ---p 00000000 00:00 0
7fef1875d000-7fef187fb000 rw-s 00000000 00:05 368 /dev/some_char_device
7fef187fb000-7fef189fb000 rw-s f0000000 00:05 368 /dev/some_char_device
7fef18a0a000-7fef18a0b000 ---p 00000000 00:00 0
7fef1ca2e000-7fef1ca2f000 ---p 00000000 00:00 0
7fef1ca33000-7fef1ca37000 rw-s f7c00000 00:05 368 /dev/some_char_device
7fef1ca37000-7fef1ca38000 ---p 00000000 00:00 0
7fef1ca3c000-7fef1ca3f000 rw-s 00000000 00:05 90 /dev/another_char_device
7fef1d615000-7fef1d616000 ---p 00215000 08:02 1957 /usr/lib/x86_64-linux-gnu/libc.so.6
7fef1da1a000-7fef1da1b000 ---p 0021a000 08:02 855 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30
7fef1dcea000-7fef1dceb000 ---p 00102000 08:02 91760 /
/shared_library9.so
7fef1dd22000-7fef1dd24000 r--p 00000000 08:02 175 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7fef1dd4e000-7fef1dd59000 r--p 0002c000 08:02 175 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7ffece1c4000-7ffece1c8000 r--p 00000000 00:00 0 [vvar]
7ffece1c8000-7ffece1ca000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]

Попытка: использовать madvise для предварительной настройки страниц
Я пытался вызвать эту функцию prefault (взято отсюда), но madvise кажется, возвращает код -1 или EPERM на страницах с разрешениями ---p. Если я правильно понимаю, эти страницы сопоставляются с помощью MAP_PRIVATE и должны размещаться в физической памяти только при записи (согласно шаблону копирования при записи). Однако madvise, похоже, не инициирует выделение, а вместо этого просто возвращает ошибку.
Как я могу предварительно отобразить страницы, сопоставленные с помощью MAP_PRIVATE? >

void prefault()
{
const pid_t pid = getpid();

FILE *fp;
char path[PATH_MAX];
char buf[4096];

(void)snprintf(path, sizeof(path), "/proc/%" PRIdMAX "/maps", (intmax_t)pid);

fp = fopen(path, "r");

volatile uint8_t val;

while (fgets(buf, sizeof(buf), fp)) {
void *start, *end, *offset;
int major, minor, n, ret;
uint64_t inode;
char prot[5];

n = sscanf(buf, "%p-%p %4s %p %x:%x %" PRIu64 " %s\n",
&start, &end, prot, &offset, &major, &minor,
&inode, path);

if (n < 7) { continue; /* bad sscanf data */ }
if (start >= end) { continue; /* invalid addresse range */ }

ret = madvise(start, (size_t)((uint8_t *)end - (uint8_t *)start), MADV_POPULATE_WRITE);
}

(void)fclose(fp);
}


Подробнее здесь: https://stackoverflow.com/questions/790 ... ap-private
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Linux»