Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Исключение ошибки страницы на х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 ошибки памяти

 

  Бит 2 Бит1 БитО
Value = 0 Value = 1 Ядро Пользователь Чтение Запись Страница отсутствует Ошибка защиты

Обработчик ошибки страницы

На обеих архитектурах функция 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. Это происходит в следующих строчках кода.


Ошибка страницы



 




Находится ли адрес в независимой области (address > =TASK_SIZE)

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;

down_read(& mm-> mmap_sem); vma = find_vma(mm, address); if (! vma) goto bad_area; if (vma-> vm_start < = address) goto good_area; if (! (vma-> vm_flags & VM_GROWSDOWN)) goto bad_area; if (error_code & 4) {

if (address + 32 < regs-> esp) goto bad_area;

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);


Ошибка страницы



 


^'" произошла ли ошибка < ^ в обработчике прерывания > v или потоке ядра?

Установка

Блокировки

Семафора mm


Находится ли адрес

В адресном пространстве

Текущей задачи?


 


Yes


No


 


       
   

No yr Можно ли нарастить ближайший регион для того чтобы вместить адрес?

bad_area_nosemaphore:


 


Поделиться:



Популярное:

Последнее изменение этой страницы: 2016-03-25; Просмотров: 843; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.021 с.)
Главная | Случайная страница | Обратная связь