달력

1

« 2025/1 »

  • 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
  • 31
2012. 1. 3. 22:46

kmap() 함수 OS이야기2012. 1. 3. 22:46

가상 메모리에서는 1G/3G이다.
물리메모리에서는 아키텍처 상, 1G까지는 직접 접근이 가능하다. 하지만 그 이후 메모리에서는 직접 접근이 불가능하다. 따라서 896 ~ 1024MB까지를 HighMem와 매핑시켜서 접근이 가능하도록 한다.
당연히, 직접접근이 가능한 쪽은 커널이 사용하겟지

kmap은 HighMem에 접근하기 위해 필요한 함수이다.

21void *kmap(struct page *page)
  22{
  23        might_sleep();
  24        if (!PageHighMem(page))
  25                return page_address(page);
  26        return kmap_high(page);
  27}
  28EXPORT_SYMBOL(kmap);
  29

void *page_address(const struct page *page)
 341{
 342        unsigned long flags;
 343        void *ret;
 344        struct page_address_slot *pas;
 345
 346        if (!PageHighMem(page))
 347                return lowmem_page_address(page);
 348
 349        pas = page_slot(page);
 350        ret = NULL;
 351        spin_lock_irqsave(&pas->lock, flags);
 352        if (!list_empty(&pas->lh)) {
 353                struct page_address_map *pam;
 354
 355                list_for_each_entry(pam, &pas->lh, list) {
 356                        if (pam->page == page) {
 357                                ret = pam->virtual;
 358                                goto done;
 359                        }
 360                }
 361        }
 362done:
 363        spin_unlock_irqrestore(&pas->lock, flags);
 364        return ret;
 365}
 366
 367EXPORT_SYMBOL(page_address);

 735static __always_inline void *lowmem_page_address(const struct page *page)
 736{
 737        return __va(PFN_PHYS(page_to_pfn(page)));
 738}
 739
 
void *kmap_high(struct page *page)
 207{
 208        unsigned long vaddr;
 209
 210        /*
 211         * For highmem pages, we can't trust "virtual" until
 212         * after we have the lock.
 213         */
 214        lock_kmap();
 215        vaddr = (unsigned long)page_address(page);
 216        if (!vaddr)
 217                vaddr = map_new_virtual(page);
 218        pkmap_count[PKMAP_NR(vaddr)]++;
 219        BUG_ON(pkmap_count[PKMAP_NR(vaddr)] < 2);
 220        unlock_kmap();
 221        return (void*) vaddr;
 222}
 223
 224EXPORT_SYMBOL(kmap_high);

http://osinside.net/linuxMM/kmap_k.html


정리하면, kmap()은 struct page *를 인자로 받는데, 그것이 NORMAL 일수도 있고, High일수도 있다.
NORMAL이면 바로 해당 페이지가 있는지만 검사한 후 , 리턴받을 수 있다.
HIGHMEM 페이지의 경우, 부팅시간에 할당되었던 kmap 페이지 테이블에 쓰지 않은 entry가
있는지 검사한다. 이 검색은 간단하게 차례로 pkmap_count의 엔트리를 조사하며 0을
찾는다. 만약 없다면, 다른 프로세스가 페이지를 unmap할 때까지 sleep한다.
사용되지 않은 엔트리를 찾았다면, 매핑하고자 하는 그 페이지의 물리 주소를 삽입하고, pkmap_count
참조계수를 증가시킨다. 그리고 호출자에게 가상주소르르 반환한다.
또한 그 page 구조체가 매핑된 주소를 의미하도록 page->virtual를 갱신
 

'OS이야기' 카테고리의 다른 글

LRU/k  (0) 2012.01.03
mm_struct, vm_area_struct  (0) 2012.01.03
bio  (0) 2012.01.03
프로세스의 .text, .data, .lib 구하기  (0) 2012.01.02
proc  (0) 2011.12.31
:
Posted by НooпeУ


Code Start Code End