Как узнать, помечена ли страница памяти только для чтения? - PullRequest
3 голосов
/ 02 ноября 2008

При использовании семантики копирования при записи для разделения памяти между процессами, как вы можете проверить, доступна ли страница памяти для записи или она помечена как доступная только для чтения? Можно ли это сделать, вызвав определенный код ассемблера, или прочитав определенное место в памяти, или через API операционной системы?

Ответы [ 4 ]

3 голосов
/ 02 ноября 2008

На Win32 лучше всего использовать VirtualQuery . Он возвращает MEMORY_BASIC_INFORMATION для страницы, на которую попадает адрес. Один из членов - Protect, что представляет собой некоторую комбинацию этих флагов, которые содержат возможные режимы защиты. Функция также сообщает вам, свободна ли память, выделена ли она, зарезервирована и является ли она частной, частью раздела изображения или общей памяти.

API операционной системы - лучший способ определить защиту страницы. Процессор считывает режим защиты из дескриптора страницы, который доступен только из режима ядра.

3 голосов
/ 02 ноября 2008

В Linux вы можете просмотреть / proc / pid / maps:

$ cat /proc/self/maps

002b3000-002cc000 r-xp 00000000 68:01 143009   /lib/ld-2.5.so
002cc000-002cd000 r-xp 00018000 68:01 143009   /lib/ld-2.5.so
002cd000-002ce000 rwxp 00019000 68:01 143009   /lib/ld-2.5.so
002d0000-00407000 r-xp 00000000 68:01 143010   /lib/libc-2.5.so
00407000-00409000 r-xp 00137000 68:01 143010   /lib/libc-2.5.so
00409000-0040a000 rwxp 00139000 68:01 143010   /lib/libc-2.5.so
0040a000-0040d000 rwxp 0040a000 00:00 0
00c6f000-00c70000 r-xp 00c6f000 00:00 0        [vdso]
08048000-0804d000 r-xp 00000000 68:01 379298   /bin/cat
0804d000-0804e000 rw-p 00004000 68:01 379298   /bin/cat
08326000-08347000 rw-p 08326000 00:00 0
b7d1b000-b7f1b000 r--p 00000000 68:01 226705   /usr/lib/locale/locale-archive
b7f1b000-b7f1c000 rw-p b7f1b000 00:00 0
b7f28000-b7f29000 rw-p b7f28000 00:00 0
bfe37000-bfe4d000 rw-p bfe37000 00:00 0        [stack]

Первый столбец - это диапазон адресов виртуальной памяти, второй столбец содержит разрешения (чтение, запись, выполнение и закрытый), столбцы 3-6 содержат смещение, основные и вспомогательные номера устройств, индекс и имя файлов, отображенных в память.

1 голос
/ 02 ноября 2008

Вы говорите о разнообразии разделяемой памяти, выделяемой через shmget (в Unix)? * 1001 Т.е. *

int shmget(key_t, size_t, int);

Если это так, вы можете запросить эту память, используя

int shmctl(int, int, struct shmid_ds *);

Например:

key_t key = /* your choice of memory api */
int flag = /* set of flags for your app */
int shmid = shmget(key, 4096, flag);

struct shmid_ds buf;
int result = shmctl(shmid, IPC_STAT, &buf);
/* buf.ipc_perm.mode contains the permissions for the memory segment */
1 голос
/ 02 ноября 2008

Если вы используете Win32, существуют вызовы IsBadReadPtr и IsBadWritePtr. Тем не менее, их использование не рекомендуется:

"По общему мнению, семейство функций IsBad (IsBadReadPtr, IsBadWritePtr и т. Д.) Не работает и не должно использоваться для проверки указателей."

Название Раймонда Чена об этом говорит само за себя: "IsBadXxxPtr действительно должен называться CrashProgramRandomly"

У Чена есть несколько полезных советов о том, как решить эту проблему здесь .

В результате вы не должны проверять подобные вещи во время выполнения. Код, чтобы вы знали, что вам вручают, и если это не то, что ожидается, воспринимайте это как ошибку. Если у вас действительно нет выбора, обратитесь к SEH для обработки исключения.

...