Функция find_vma()

We use cookies. Read the Privacy and Cookie Policy

Функция find_vma()

Функция find_vma() определена в файле mm/mmap.c.

Эта функция позволяет найти в заданном адресном пространстве ту первую область памяти, для которой значение поля vm_end больше заданного адреса addr. Другими словами, эта функция позволяет найти первую область памяти, которая содержит адрес addr или начинается с адреса, большего адреса addr. Если такой области памяти не существует, то функция возвращает значение NULL.

В противном случае возвращается указатель на соответствующую структуру vm_area_struct. Обратите внимание, что найденная область VMA может начинаться с адреса, большего адреса addr, и этот адрес не обязательно принадлежит найденной области памяти. Результат выполнения функции find_vma() кэшируется в поле map_cache дескриптора памяти. Поскольку очень велика вероятность того, что после одной операции с областью памяти последуют еще операции с ней же, то процент попаданий в кэш получается достаточно большим (на практике получаются значения порядка 30-40%). Проверка кэшированных результатов выполняется очень быстро. Если нужный адрес в кэше не найден, то выполняется поиск по всем областям памяти, связанным с заданным дескриптором. Этот поиск выполняется с помощью красно-черного дерева следующим образом.

struct vm_area_struct* find_vma(struct mm_struct *mm,

 unsigned long addr) {

 struct vm_area_struct *vma = NULL;

 if (mm) {

  vma = mm->mmap_cache;

  if (!(vma && vma->vm_end > addr && vma->vm_start <= addr)) {

   struct rb_node* rb_node;

   rb_node = mm->mm_rb.rb_node;

   vma = NULL;

   while (rb_node) {

    struct vm_area_struct* vma_tmp;

    vma_tmp =

     rb_entry(rb_node, struct vm_area_struct, vm_rb);

    if (vma_tmp->vm_end > addr) {

     vma = vma_tmp;

     if (vma_tmp->vm_start <= addr)

      break;

     rb_node = rb_node->rb_left;

    } else

     rb_node = rb_node->rb_right;

   }

   if (vma)

    mm->mmap_cache = vma;

  }

 }

 return vma;

}

Вначале выполняется проверка поля vma_cache на предмет того, содержит ли кэшированная область VMA необходимый адрес. Обратите внимание, что простая проверка того, является ли значение поля vm_end большим addr, не гарантирует что проверяемая область памяти является первой, в которой есть адреса, большие addr. Поэтому, для того чтобы кэш в этой ситуации оказался полезным, проверяемый адрес должен принадлежать кэшированной области памяти. К счастью, это как раз и соответствует случаю выполнения последовательных операций с одной и той же областью VMA.

Если кэш не содержит нужную область VMA, то функция должна выполнять поиск по красно-черному дереву. Это выполняется путем проверки узлов дерева. Если значение поля vma_end для области памяти текущего узла больше addr, то текущим становится левый дочерний узел, в противном случае — правый. Функция завершает свою работу, как только находится область памяти, которая содержит адрес addr. Если такая область VMA не найдена, то функция продолжает поиск по дереву и возвращает ту область памяти, которая начинается после адреса addr. Если вообще не найдена ни одна область памяти, то возвращается значение NULL.