您的位置:首页 > 运维架构

copy_to_user的实现以及get_user_pages/kmap_atomic/kmalloc

2011-10-20 16:36 387 查看
转自 /article/2022122.html

copy_to_user的实现:

copy_to_user

__copy_to_user

__copy_to_user_inatomic

__put_user_size

__put_user_asm/__copy_to_user_ll

__copy_to_user_ll or __copy_user

一般很少使用__copy_to_user, 而是使用__copy_user()...__copy_user():是直接使用用户空间的指针来完成拷贝工作的!!!只有没有在用户上下文是才使用下面的方法:

get_user_pages并没有直接使用用户态地址,它是先根据用户空间的地址得到对应的page(内存物理地址),又把这个page kmap_atomic了一下了

然后再进行memcpy

请看

Arch/i386/lib/usercopy.c

__copy_to_user_ll()

retval = get_user_pages(current, current->mm,

(unsigned long)to, 1, 1, 0, &pg, NULL);

......

maddr = kmap_atomic(pg, KM_USER0);

memcpy(maddr + offset, from, len);

kunmap_atomic(maddr, KM_USER0);

而kmap_atomic的实现分两种情况:

1. 当用户的page在低端内存时,内核已经对其进行了一一映射,直接可以使用,即,直接:return page->virtual;

2. 当用户的page在高端内存时,由于内核并没有对其进行一一映射,这时就需要建立临时映射了...

-------------------

kmalloc是基于slab实现的,当slab中没有空闲的object可以分配时,它会向buddy system请求新的物理页cache_grow -> kmem_getpages -> alloc_page_node, 得到物理页后,就将这个物理页所对应的kernel virtual address返回给slab.因为slab allocator只使用low memory,所以这个virtual addr就是phy_addr + PAGE_OFFSET。这里并没有对page
table的操作,kernel就直接使用这个virtual address来访问物理内存,因为映射在初始化的时候早就做好了。

kmalloc()返回的指针就是这个virtual address + 偏移量(指向slab中不同的object).

如果在kernel中访问high memory的话,就需要通过kmap_atomic把这个物理页map到kernel的虚拟空间后,才能访问。

get_user_pages是用来将用户空间的页(pages)映射(锁)入内存,并得到它们的页结构(struct page)指针。

page_cache_release(

pdx->DmaInfo[channel].PageList[i]

);

用到get_user_pages函数还需page_cache_release来解锁
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: