copy_to_user的实现以及get_user_pages/kmap_atomic/kmalloc

转自 http://blog.csdn.net/eroswang/article/details/4130991

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来解锁

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`skb_release` 函数是 Linux 内核中用来释放 `skb` 数据结构(网络数据包缓冲区)的函数。它的定义在文件 `net/core/skbuff.c` 中。 下面是 `skb_release` 函数的代码及注释: ```c void skb_release(struct sk_buff *skb) { struct nf_hook_state state; unsigned int i; /* Call the packet destroy function for nf_hooks */ if (unlikely(nf_hooks_needed(skb))) nf_hook_state_init(&state, NFPROTO_UNSPEC, NF_HOOK_INVALID, NULL, skb, NULL, dev_net(skb->dev), 0); for (i = 0; i < NFPROTO_NUMPROTO; i++) nf_hook(NFPROTO(i), NF_INET_PRE_ROUTING, &state, skb, skb->dev, NULL, skb_dst(skb)->dev, NULL, skb->protocol); /* Call the destructor for each extension header. */ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { if (skb_shinfo(skb)->frags[i].page) kmap_atomic(skb_shinfo(skb)->frags[i].page); if (skb_shinfo(skb)->destructor[i]) skb_shinfo(skb)->destructor[i](skb); if (skb_shinfo(skb)->frags[i].page) kunmap_atomic(skb_shinfo(skb)->frags[i].page); } if (skb_shinfo(skb)->frag_list) kfree_skb_list(skb_shinfo(skb)->frag_list); /* Release the skb itself */ kmem_cache_free(skbuff_head_cache, skb); } ``` 该函数的作用是释放 `skb` 数据结构,它的主要步骤包括: 1. 如果 `skb` 上注册了网络钩子(`nf_hook`),则依次调用每个网络钩子的销毁函数(`nf_hook` 函数的第 4 个参数)。 2. 对于 `skb` 中的每个扩展头,调用其析构函数(`destructor`)进行清理,以释放扩展头占用的内存。 3. 如果 `skb` 中存在分段数据(`frag_list`),则释放分段数据占用的内存。 4. 最后,释放 `skb` 本身占用的内存。 需要注意的是,该函数只是释放 `skb` 数据结构本身占用的内存,但并不会释放 `skb` 引用的其他内存(例如数据包的内容、关联的网络设备等)。这些内存的释放由其他函数负责。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值