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


Находится ли адрес регионе памяти задачи?




Yes



expand_stack()?

good.area:


Рис. 4.15. Ошибка страницы 2

pgdjc = init__mm.pgd + index; 491 if (! pgd_present(*pgd_k)) goto no_context; pmd = pmd_offset(pgd, address); pmd_k = pmd_offset (pgd_k, address); if (! pmd_j? resent (*pmd_k) )

goto no_context; set_prad(pmd, *pmd_k); pte_k = pte_offset__kernel(pmd_k, address)

506 if (! pte_present(*pte_k))

507 goto no__context;

508 return;

509 }

Строки 473-509

Глобальная директория страницы текущего процесса связана (с помощью сгЗ) и сохранена в переменную pgd, а глобальная директория страницы ядра связана с pgd_k (аналогично переменным pmd и pte). Если проблемный адрес неверен для системы подкачки ядра, код переходит к метке no_context:. В противном случае текущий процесс использует pgd ядра.

Теперь посмотрим на метку good__area:. В этой точке мы знаем, что область памя­ти, хранящая проблемный адрес, находится в адресном пространстве процесса. Теперь нам нужно убедиться, что разрешение доступа верно. Рис. 4.17 показывает диаграмму этой работы.



Глава 4 • Управление памятью


 

 

 

 

 

 

 

 

 

 

vmallocjault N. N0      
       
^/Обновление таблицы страниць ^Присутствуют ли pgd/pmd/pter no_context:    
X  
         
  Yes ж    
  Ошибка станицы завершена      

Рис. 4.16. Метка vmallocjault

arch/i38б/mm/fault.с

2 90 good_area:

291 info.si_code = SEGV_ACCERR;

2 92 write = 0;

2 93 switch (error_code & 3) {

294 default: /* 3: write, present */

/* fall through */

3 00 case 2; /* write, not present */
301 if (! (vma> vm_flags & VM_WRITE))

3 02 goto bad_area;

303 write++;

3 04 break;

3 05 case 1: /* read, present */

3 06 goto bad_area;

3 07 case 0: /* read, not present */

308 if (! (vma-> vm_flags & (VM_READ | VM_EXEC)))

3 09 goto bad_area;

310 }

Строки 294-304

Если ошибка страницы произошла в записываемой области памяти (вспомните, что в этом случае самый левый бит, error__code, равен 1), мы проверяем, является ли область памяти доступной для записи. Если нет, мы получаем несоответствие разрешений и переходим к метке bad_area:. Если запись возможна, мы перехо­дим к строке case и вызываем handle_mm_fault () с локальной переменной, ус­тановленной в 1.


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



Строки 305-309

Если ошибка памяти вызвана доступом для чтения или выполнения и страница присутствует, мы переходим к метке bad_area:, так как это явное нарушение прав доступа. Если страницы нет, мы проверяем, имеет ли область памяти разрешение за чтение или выполнение. Если нет, мы переходим к метке bad__area:, так как, если бы мы нашли страницы, разрешение не позволило бы выполнить операцию. Если нет, мы переходим к следующему случаю и выполняем handle_mm_fault О с локальной переменной, установленной в 0.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

good.area: <   \ No      
Присутствует ли разрешение на доступ?    
bacLarea:    
У  
     
' Yes    
handle_mm_fault()  
' г  
Ошибка станицы завершена  
       

Рис. 4.17. Метка good area

Следующая метка помечает код, в который мы попадаем, когда проверка разрешения подтверждается. Этому случаю соответствует метка survive:.

arch/i38б/mm/fault.с survive:

318 switch (handle__mm_fault(mm, vma, address, write)) { case VM_FAULT_MINOR: tsk-> min_flt++; break; case VM_FAULT_MAJOR: tsk-> raaj_flt++; break; case VM_FAULT_SIGBUS: goto do_sigbus;



Глава 4 • Управление памятью


case VM_FAULT_OOM: goto out_of_memory; 329 default: BUG();

}

Строки 318-329

Функция handle_mm_f ault () вызывается для текущего описателя памяти (mm), т. е. описателя области проблемного адреса независимо от того, доступна ли эта об­ласть для записи или для чтения-исполнения. Конструкция switch перехватывает управление, если мы не смогли обработать ошибку, для того чтобы функция смогла нормально завершиться.

Следующий блок кода описывает поток выполнения для метки bad_area и bad_area_no_semaphore. При переходе к этой точке нам известно следующее:

1. Породивший ошибку памяти адрес не является адресом пространства процесса, так как мы проверили его область памяти и не нашли там искомое.

2. Породивший ошибку адрес не находится в адресном пространстве процесса и регио­не, до которого оно может наращиваться.

3. Адрес, породивший ошибку памяти, находится в адресном пространстве процесса, но не имеет разрешения для доступа к памяти, соответствующего выполнению же­лаемого действия.

Теперь нам нужно определить, произведен ли доступ из режима ядра. Следующий код и рис. 4.18 демонстрирует поток выполнения этой метки.

arch/i38б/mm.fault.с

348 bad_area:

349 up_read (& mm- > mmap_s em);
350

351 bad_area_nosemaphore:

3 52 /* Доступ пользовательского режима порождает SIGSEGV */

3 53 if (error_code & 4) {

354 if (is_prefetch(regs/ address))

3 55 return;

3 57 tsk-> thread.cr2 = address;

3 58 t sk-> thread, err or__code = error_code;

3 59 tsk-> thread.trap_no = 14;

3 60 info.si_signo = SIGSEGV;

3 61 info.si_errno = 0;

3 62 /* info.si_code установлен выше */


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



3 63 info.si_addr = (void Maddress;

364 force_sig_info(SIGSEGV, & info, tsk);

3 65 return;

366 }

Строка 348

Функция up_jread () снимает блокировку чтения с семафора описателя памяти процесса. Обратите внимание, что мы просто перешли к метке bad_area после то­го, как поставили блокировку семафора описателя памяти и просмотрели его об­ласть памяти на предмет нахождения в адресном пространстве процесса нашего адреса. В противном случае мы переходим к метке bad_area_no_semaphore. Единственная разница между этими двумя случаями заключается в установке бло­кировки семафора.

Строки 351-353

Так как адрес не находится в адресном пространстве, мы проверяем, была ли ошиб­ка сгенерирована в пользовательском режиме. Если вы вспомните табл. 4.7, значе­ние error_code означает, что ошибка произошла в пользовательском режиме.

Строки 354-366

Мы определили, что ошибка произошла в пользовательском режиме, и поэтому нам нужно послать сигнал SIGSEGV (прерывание 14).

 

 

 

 

 

 

 

 

 

 

 

 

bad_area:   \ No      
       
У^ Выполнен ли доступ N. из пользовательского режима' no_context:    
'/  
         
  ^ Yes    
  Посылка SIGSEGV  
         
             

Рис. 4.18. Метка bad area

Следующий фрагмент кода описывает поток обработки метки no_context. Когда мы переходим в эту точку, мы знаем следующее:

• одна из таблиц страниц потеряна;

• доступ к памяти произведен в режиме ядра.



Глава 4 • Управление памятью


Рис. 4.19 иллюстрирует диаграмму потока метки no_context.

Arch/ i3 8 б /mm/ fault. с

388 no_context:

390 if (fixup_exception(regs))

return; 432 die(" Oops", regs, error_code);

bust_spinlocks(0);

do__exit (SIGKILL);

Строка 390

Функция f ixup_exception () использует eip, передаваемый для поиска в таб­лице исключений соответствующей инструкции. Если инструкция в таблице найде­на, она уже должна быть откомпилирована с помощью «скрытого» встроенного кода обработки. Обработчик ошибки страницы do_page_fault () использует код обработки ошибки как адрес возврата и переходит по этому адресу. Затем код может выставить флаг ошибки.

Строка 432

Если в таблице исключений нет вхождения для соответствующей инструкции, код выполняет переход по метке no_context и завершается выводом на экран oops.

 

 

 

 

 

 

 

 

 

 

 

 

 

no.context <   \, No      
Существует ли обработчик исключения в таблице исключений   Генерация ops ядра и завершение процесса  
?  
Yes      
Переход к обработчику исключения  
       
             

Рис. 4.19. Метка по context


Поделиться:



Популярное:

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


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