Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология Образование Политология Производство Психология Стандартизация Технологии |
Исключение ошибки страницы на х86
Обработчик ошибки страницы х86 do_page_f ault () вызывается в результате аппаратного прерывания 14. Это прерывание происходит, когда процессор обнаруживает, что верны следующие условия: 1. Подкачка включена, и в директории страницы очищен бит присутствия, или данный адрес нужен для элемента таблицы страницы. 2. Подкачка включена, и текущий уровень привилегий ниже, чем необходимо для доступа к затребованной странице. При возникновении этого прерывания процессор сохраняет информацию двух видов: 1. Природу ошибки в нижних 4 битах слова, переданного в стек. [Бит 3 функцией do_page_f ault () не используется.] См. значения, соответствующие битам в табл. 4.7. 2. 32-битовый линейный адрес, породивший исключение в сг2. Ошибка страницы Параметр regs функции do_page_fault () является структурой, содержащей системные регистры и параметр error_code, использующий 3-битовое поле для описания источника ошибки. Таблица 4.7. error_code ошибки памяти
Обработчик ошибки страницы На обеих архитектурах функция do_page__f ault () использует только что полученную информацию и выполняет одно из нескольких действий. Соответствующие фрагменты кода выполняют серию сложных проверок и заканчиваются одним из следующих случаев: • с помощью handle_nim_f ault () находится адрес, вызвавший ошибку; • выполняется дамп oops (no_context: ) bad_page_f ault () для PowerPC; • ошибка сегментации (bad_area: ) bad_page_f ault () для PowerPC; • вызывающей функции возвращается ошибка (f ixup). arch/i38б/mm/fault.с 212 asmlinkage void do_page_fault{struct pt__regs *regs, unsigned long error__code) 213 { 214 struct task_struct *tsk; 215 struct mm_struct *mm; 216 struct vm_area_struct * vma; 217 unsigned long address; 218 unsigned long page; 219 int write; 220 siginfo_t info; 221
222 /* получение адреса */ 223 _asm_(" movl %%cr2, %0" : " =r" (address)); 232 tsk = current; 234 info.si_code = SEGV_MAPERR; Глава 4 • Управление памятью Строка 223 Адрес, по которому произошла ошибка страницы, сохраняется в управляющем регистре сг2. Выполняется чтение линейного адреса, и адрес присваивается локальной переменной. Строка 232 Указатель на task_struct tsk устанавливается указывающим на текущую структуру task_struct. Теперь мы готовы приступить к дальнейшему поиску адреса, где возникла ошибка страницы. Рис. 4.14 иллюстрирует работу следующих строк кода: Arch/i3 8б/mm/fault.с 246 if (unlikely(address > = TASK_SIZE)) { 247 if (! (error_code & 5)) 248 goto vmalloc_fault;
253 goto bad_area_.nosemaphore; 254 } 257 mm = tsk-> mm Строки 246-248 Этот код проверяет, находится ли адрес, в котором произошла ошибка, в модуле ядра (т. е. в независимой области памяти). Адреса независимой области памяти обладают собственным линейным адресом > = TASK_SIZE. Если так, выполняется проверка того, что биты 0 и 2 error_code не установлены. Вспомните табл. 4.7, которая демонстрировала ошибки, возникающие при попытке доступа к несуществующей странице ядра. Если условие выполнилось, значит, в ядре произошла ошибка страницы и вызывается код в метке vmalloc__f ault:. Строки 253 Если мы сюда попали, это означает, что, несмотря на то что доступ выполнялся к независимой области памяти, он произошел в пользовательском режиме и вызвал ошибку защиты или оба эти события. В этом случае мы переходим к метке bad_area__semaphore:. Строки 257 Устанавливает локальную переменную mm таким образом, чтобы она указывала на описатель памяти текущей задачи. Если текущая задача является потоком ядра, ее значением будет NULL. Это происходит в следующих строчках кода. Ошибка страницы
No Следующий фрагмент кода Yes
No bad_area_nosemaphore: Yes vmallocjault: Рис. 4.14. Ошибка страницы 1 В этом месте мы определяем, что ошибка страницы не произошла в независимой области памяти. Рис. 4.15 иллюстрирует работу следующих строк кода: arch/i38б/mm/fault.с 262 if (in_atomic() ||! ram) 2 63 goto bad__area_nosemaphore;
283 } 254 if (expand_stack(vma, address)) Глава 4 • Управление памятью 285 goto bad_area; Строки 262-263 В этом блоке кода мы проверяем, не произошла ли ошибка во время обработки прерывания или в пространстве ядра. Если это так, мы переходим к метке bad_area__semaphore:. Строка 265 В этой точке мы выполняем поиск в области памяти текущего процесса и поэтому блокируем для чтения семафор описателя памяти. Строки 267-269 Добравшись сюда, мы знаем, что адрес, породивший ошибку страницы, не находится в потоке ядра или в обработчике прерывания и поэтому нам нужно выполнить поиск этого адреса в областях памяти других ближайших процессов. Если он там не обнаружится, мы переходим к метке bad__area:. Строки 270-271 Если мы нашли верный регион внутри адресного пространства процесса, мы переходим к метке good__area:. Строки 272-273 Если мы обнаружили, что регион неверен, мы проверяем, может ли ближайший регион быть увеличен, для того чтобы вместить страницу. Если нет, мы переходим к метке bad_area:. Строки 274-284 В противном случае проблемный адрес является результатом стековой операции. Если увеличение стека не помогает, переходим к метке bad_area:. Теперь мы перейдем к объяснению того, куда ведет каждая метка. Мы начнем с метки vmalloc_f ault, показанной на рис. 4.16. arch/i38б/mm/fault.с 473 vmalloc_fault: { int index = pgd_index(address); pgd_t *pgd, *pgd_k; pmd_t * pmd, *pmd_k; pte_t *pte_k; asm(*movl %%сг3; %0": " =гй (pgd)); pgd = index + (pgd_t *)______ va(pgd); Ошибка страницы
Установка Блокировки Семафора mm Находится ли адрес В адресном пространстве Текущей задачи?
Yes No
bad_area_nosemaphore:
Популярное:
|
Последнее изменение этой страницы: 2016-03-25; Просмотров: 843; Нарушение авторского права страницы