커널은 종종 주어진 주소가 어떤 메모리 영역안에 존재하는지의 여부와 같은 기준에 따라 프로세스 주소공강네 있는 어떤 메모리 영역을 찾아야 할 경우가 있다. 이러한 연산은 빈번히 발생하며 다음에서 살펴볼 mmap()의 기초를 다룬다.
find_vma()
다시 말해, 이 함수는 addr을 포함하거나 addr보다 큰 메모리 주소로 시작되는 첫번째 메모리 영역을 찾는다.
만약 그러한 메모리 영역이 존재하지 않을 겨웅에는 NULL을 반환한다.
만약 찾는다면 해당 vm_area_struct 구조체의 포인터가 반환된다.
함수 find_vma()의 결과는 메모리 서술자의 mmap_cache 필드에 캐시된다. 하나의 VMA에 대한 작업 있었다면, 다시 동일한 VMA에 대한 추가적인 연산이 뒤따를 확률이 크므로 이 캐시는 일정수준의 적중률을 갖는다. 캐시된 결과를 찾는 것은 빠르지만, 주어진 주소가 캐시에 없을 경우, 해당 메모리 서술자와 관련된 모든 메모리 영역을 검사해야 한다. 이 작업은 레드블랙 트리를 이용해 수행된다.
우선 mmap_cache를 점검하여 캐시된 VMA가 해당 주소를 포함하고 있는지를 검사한다.
vm_end필드가 addr보다 크다는 사실은 해당 VMA가 addr보다 큰 첫번째 VMA라는 것을 보장하지 못한다
따라서 이부분에 캐시가 쓸모가 있으려면, 주어진 addr이 VMA안에 위치해야 한다.
만약 캐시에 VMA가 없는 경우, 해당 함수는 redblack트리를 검색해야 한다. 즉, 만일 현재VMA의 vm_end가 addr보다 크다면 함수는 트리의 왼쪽 자시노드를 따라가고, 그렇지 않다면 오른쪽 자식노드를 따라간다. 함수는 addr를 포함하고 있는 VMA을 찾는 즉시 종료된다.
만일 그러한 VMA가 발견되지 않는다면, 함수는 계속해서 트리를 순회하여 addr이후에서 시작되는 첫 VMA를 반환한다. VMA를 찾지 못한경우에는 NULL이 반환된다.
find_vma()
다시 말해, 이 함수는 addr을 포함하거나 addr보다 큰 메모리 주소로 시작되는 첫번째 메모리 영역을 찾는다.
만약 그러한 메모리 영역이 존재하지 않을 겨웅에는 NULL을 반환한다.
만약 찾는다면 해당 vm_area_struct 구조체의 포인터가 반환된다.
함수 find_vma()의 결과는 메모리 서술자의 mmap_cache 필드에 캐시된다. 하나의 VMA에 대한 작업 있었다면, 다시 동일한 VMA에 대한 추가적인 연산이 뒤따를 확률이 크므로 이 캐시는 일정수준의 적중률을 갖는다. 캐시된 결과를 찾는 것은 빠르지만, 주어진 주소가 캐시에 없을 경우, 해당 메모리 서술자와 관련된 모든 메모리 영역을 검사해야 한다. 이 작업은 레드블랙 트리를 이용해 수행된다.
1568/* Look up the first VMA which satisfies addr < vm_end, NULL if none. */ 1569struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr) 1570{ 1571 struct vm_area_struct *vma = NULL; 1572 1573 if (mm) { 1574 /* Check the cache first. */ 1575 /* (Cache hit rate is typically around 35%.) */ 1576 vma = mm->mmap_cache; 1577 if (!(vma && vma->vm_end > addr && vma->vm_start <= addr)) { 1578 struct rb_node * rb_node; 1579 1580 rb_node = mm->mm_rb.rb_node; 1581 vma = NULL; 1582 1583 while (rb_node) { 1584 struct vm_area_struct * vma_tmp; 1585 1586 vma_tmp = rb_entry(rb_node, 1587 struct vm_area_struct, vm_rb); 1588 1589 if (vma_tmp->vm_end > addr) { 1590 vma = vma_tmp; 1591 if (vma_tmp->vm_start <= addr) 1592 break; 1593 rb_node = rb_node->rb_left; 1594 } else 1595 rb_node = rb_node->rb_right; 1596 } 1597 if (vma) 1598 mm->mmap_cache = vma; 1599 } 1600 } 1601 return vma; 1602}
우선 mmap_cache를 점검하여 캐시된 VMA가 해당 주소를 포함하고 있는지를 검사한다.
vm_end필드가 addr보다 크다는 사실은 해당 VMA가 addr보다 큰 첫번째 VMA라는 것을 보장하지 못한다
따라서 이부분에 캐시가 쓸모가 있으려면, 주어진 addr이 VMA안에 위치해야 한다.
만약 캐시에 VMA가 없는 경우, 해당 함수는 redblack트리를 검색해야 한다. 즉, 만일 현재VMA의 vm_end가 addr보다 크다면 함수는 트리의 왼쪽 자시노드를 따라가고, 그렇지 않다면 오른쪽 자식노드를 따라간다. 함수는 addr를 포함하고 있는 VMA을 찾는 즉시 종료된다.
만일 그러한 VMA가 발견되지 않는다면, 함수는 계속해서 트리를 순회하여 addr이후에서 시작되는 첫 VMA를 반환한다. VMA를 찾지 못한경우에는 NULL이 반환된다.
'OS이야기' 카테고리의 다른 글
페이지 캐시 (0) | 2011.11.01 |
---|---|
fread() / fwrite() (0) | 2011.10.31 |
VMA연산 (0) | 2011.10.25 |
mm_struct 구조체와 커널 스레드 (0) | 2011.10.25 |
메모리 서술자의 할당 (0) | 2011.10.25 |