Поток разыменования сегментов, зачем нужен ?

Тема в разделе "WASM.NT.KERNEL", создана пользователем Sheph, 14 апр 2008.

  1. Sheph

    Sheph New Member

    Публикаций:
    0
    Регистрация:
    24 янв 2008
    Сообщения:
    89
    Всем доброго времени суток, хотелось бы прояснить ситуацию с потоком разыменования сегментов в винде, насколько я понимаю дела обстоят так:

    В ядре есть глобальная переменная MmUnusedSegmentList, которая представляет собой список объектов CONTROL_AREA (или LARGE_CONTROL_AREA в случае per-session контрольной области), объект SEGMENT которых предназначен для удаления. Объекты CONTROL_AREA попадают в этот список в общем случае когда:

    if ((ControlArea->NumberOfMappedViews == 0) &&
    (ControlArea->NumberOfSectionReferences == 0) &&
    (ControlArea->u.Flags.BeingDeleted == 0)) {

    Такие проверки производятся при каждом декрементировании переменной NumberOfMappedViews и NumberOfSectionReferences, этим занимается функция MiCheckControlArea (заносит контрольные области в этот список). Уничтожение самих сегментов производит функция MiRemoveUnusedSegments, которая вызывается только в одном месте, из функции MiDereferenceSegmentThread. MiDereferenceSegmentThread – этот системный поток, который занимается удалением неиспользуемых в данный момент сегментов из памяти (и ещё расширением страничных файлов), освобождая тем самым место в страничном файле. Делает он это по требованию ОС. ОС выставляет событие MmUnusedSegmentCleanup, поток ждёт этого события и получив его, удаляет ненужные сегменты, освобождая место в страничном файле. Возникает вопрос, зачем для всего этого нужен отдельный поток ? Почему нельзя удалять сегменты, на которые нет ссылок в момент проверки, т.е прямо в функции MiCheckControlArea ?
     
  2. Sheph

    Sheph New Member

    Публикаций:
    0
    Регистрация:
    24 янв 2008
    Сообщения:
    89
    Наткнулся ещё вот на что:
    Код (Text):
    1.             if (ControlArea->NumberOfPfnReferences == 0) {
    2.  
    3.                 //
    4.                 // There are no views and no physical pages referenced
    5.                 // by the Segment, dereference the Segment object.
    6.                 //
    и
    Код (Text):
    1. ULONG NumberOfPfnReferences;        // valid + transition prototype PTEs
    Этот код из MiCheckControlArea и если NumberOfPfnReferences == 0, то сама MiCheckControlArea удалит сегмент и не будет заносит его в список MmUnusedSegmentList !, для последующего удаления из MiDereferenceSegmentThread. Т.е, получается что если у сегмента есть валидные или transition PTE, то удалять сразу его нельзя, а если все его PTE невалидные и не transition, то можно. Но почему ? Ссылок же на сегмент всё-равно нет, можно ж просто слить все изменённые PTE в файл (если сегмент поддерживается не страничным файлом) и удалить его...
     
  3. Sheph

    Sheph New Member

    Публикаций:
    0
    Регистрация:
    24 янв 2008
    Сообщения:
    89
    Поразмыслив, появилось мнение почему так сделано (хотя и не очень убедительное):
    Допустим у нас поток имеют доступ к сегменту через секцию (или субсекцию, пока в этом ещё не разобрался через что именно производится работа с сегментом), т.е спроецировал он секцию, NumberOfMappedViews стало = 1, потом проекцию удалил, т.е NumberOfMappedViews = 0 и, скорее всего, NumberOfPfnReferences != 0, т.к он совсем недавно работал с секцией и наверняка какие-то страницы ещё лежат в физической памяти. Теперь допустим он мапит секцию заново и в этом случае всё очень просто, сегмент ещё лежит в памяти, нужно просто дать на него ссылку, не нужно выделять новый сегмент, плюс к этому даже страницы остались в физ. памяти, можно сново к ним обратиться и это не займёт много времени. А если бы сегмент удалялся сразу, то при каждом повторном мапиньи секции пришлось бы создавать сегмент и т.д. Но опять таки, как часто программы открывают и закрывают один и тот же файл для проецирования, это же глупо. Неужели только ради того чтобы оптимизировать подобную ситуацию разработчики винды придумали этот MiDereferenceSegmentThread и т.д.