merge_segments— это интересная функция, которая сливает смежные области VMA в одну область VMA с большим охватом. Таким образом, если одна область VMA покрывает (вполне очевидно, что вымышленный) диапазон от 0x100 до 0x200, а другая покрывает диапазон от 0x200 до 0x300 и они имеют одинаковые признаки защиты, то функция merge_segments заменяет их обе одной областью VMA, которая покрывает диапазон от 0x100 до 0x300. (Отметим, что слово «segments» в имени функции не говорит о том, что мы используем сегменты процессора — это не так.)
Параметрами функции merge_segments являются: объект struct mm_struct, содержащий интересующие нас области VMA, а также начальный и конечный адреса, в пределах которых может оказаться возможным слияние.
find_vma_prev (строка ) находит первую область VMA, для которой значение vm_end следует за предоставленным значением start_addr, поэтому это первая область VMA, которая может содержать start_addr. Напомним также, что функция find_vma_prev возвращает также указатель на предыдущую область VMA в параметре prev1 (NULL, если запросу удовлетворяет первая же область VMA).
Входит в цикл, в котором будут рассмотрены все области VMA, перекрывающие заданный диапазон. В этом цикле функция merge_segments пытается слить каждый сегмент с предшествующим, который всегда можно определить с помощью prev.
Основная часть этого условия if относительно проста, но последняя проверка, вероятно, сложнее. Она проверяет смежность prev и mpnt, т.е. отсутствие неотображенной памяти между концом prev и началом mpnt. Даже если она обнаруживает, что vm_end одной области равен vm_start другой, это пока не значит, что эти две области являются смежными — помните, что vm_end на единицу больше последнего адреса, принадлежащего VMA. Строки с до предписывают аналогичное свойство для файлов и разделяемой памяти, обработанных функцией mmap: конец одной области должен быть равен началу следующей.
Функция merge_segments нашла смежные области VMA, которые она может слить. Она удаляет mpnt из списка областей VMA (и возможно также из дерева) и вкладывает это значение в prev. Отметим, что эта функция не демонтирует дерево, даже если число областей VMA снова становится меньше значения AVL_MIN_MAP_COUNT.
Если исчезнувшая область VMA была частью файла, обработанного функцией mmap, функция merge_segments удаляет ее ссылку на этот файл.