달력

6

« 2025/6 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
2011. 10. 31. 16:20

메모리영역 다루기 OS이야기2011. 10. 31. 16:20

커널은 종종 주어진 주소가 어떤 메모리 영역안에 존재하는지의 여부와 같은 기준에 따라 프로세스 주소공강네 있는 어떤 메모리 영역을 찾아야 할 경우가 있다. 이러한 연산은 빈번히 발생하며 다음에서 살펴볼 mmap()의 기초를 다룬다.

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
:
Posted by НooпeУ


Code Start Code End