当前位置:  技术问答>linux和unix

关于内核中数据拷贝的几个问题,望解答。

    来源: 互联网  发布时间:2016-05-05

    本文导语:  有以下几个函数: unsigned long copy_to_user(void __user *to, const void *from, unsigned long count); unsigned long copy_from_user(void  *to, const void __user*from, unsigned long count); skb_copy_bits(const struct sk_buff *skb, int offset, void *t...

有以下几个函数:

unsigned long copy_to_user(void __user *to, const void *from, unsigned long count);

unsigned long copy_from_user(void  *to, const void __user*from, unsigned long count);

skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len);

在浏览它们相关的源代码时,发现skb_copy_bits实现的核心函数就是memcpy,而copy_to_user还有copy_from_user则用的是另外的一些实现。

我的疑问如下:

1.为什么copy_to_user和copy_from_user的实现不用memcpy?而取而代之的是一堆很复杂的实现,包括要把数据对齐之类的。

2.假设我要读取或者写入的数据的物理地址是连续的,我在使用上述函数实现数据拷贝时,能够拷贝的数据量大小有限制吗?

3.最后就是,我增大每次读取或者写入的数据量,也就是减小这三个函数的调用次数,但是传输的数据总量是相同的,这样能够减小系统的开销么?

|


这里所说的失效是指在内核态时,用户地址空间有可能没有被映射进相应的虚拟地址段,如果想要通过PAGE FAULT重新将其装载入内存,那么在内核态下,你就相当于把用户态的数据直接映射在了内核地址空间,这样做就带来了安全问题,你这样一映射,当返回到用户态时,用户态就直接访问到了0xC0000000以上的地址空间,这样就违反了内核态与用户态地址隔离的原则,同样会带来安全性设计的问题

实际上也存在用户态直接访问内核地址空间的情况,比如mmap方式,这种就是内核向应用层提供的一种接口,它主要是为了解决LZ所说的memcpy比copy_from_user效率更高的问题,假定内核设计者不用copy_from_user之类的策略,也就没有mmap接口的必要了,但是为什么内核设计者非得要使用这种策略呢?这要设计到内核的内核地址管理/进程切换/段页式内存等综合因素了,比较复杂,总之,内核绝对不能在用户无缘无故的情况下在其内核地址空间为其映射一段空间出来,所有的进程都共享一段内核地址空间,如果为每个进程都映射若干段,那么内核地址空间很快就被使用完了,而且若某个进程结束,还要设计到释放的问题

另一方面,当使用mmap方式时,其地址空间被归属于进程的VMA区域,也就是说这样分配的内存,当进程结束时,会被回收掉,而在内核态中所执行的kmalloc函数,是在内核堆中执行的映射,需要kfree释放,若不使用kfree,就算是所有进程结束完,这段内存依然不会被回收.

内核中有四种地址分配方式,其一是代码段/DATA段/BSS段,由内核初始化时映射,所有进程在其进入内核态时共享这段内存空间,普通情况下这段内存常驻内核虚拟页表映射而不会被释放(也有特殊情况,这里不作详述),其二,内核栈内存区(共8K的内核栈),每个进程都有自己的一个独占的内核栈区,这段地址空间也是常驻内存的,不会存在PAGE FAULT,其三,就是用kmallo在内核堆上分配的地址空间,跟应用层的malloc类似,不同的就是kmalloc是在内核地址空间分配的,这个地址空间同样由所有进程的内核态时共享,只能由内核态释放,同样不能进行PAGE FAULT,其四就是vmalloc/mmap之类的方式,它是在内核态时分配,提供给用户态访问,它跟kmalloc有点儿类似,但它的管理被归入了进程的VMA区,跟进程挂钩,它允许PAGE FAULT

综上所述,通常情况下内核态下的地址空间是不允许PAGE FAULT的(也有特殊情况,这里不作详述),PAGE FAULT是一种在用户态的策略,还有就是swap这的策略也是用于用户态的,正是基于这种策略,所以就一定需要copy_to_user之类的函数存在...............



|
楼上有人说反了。

1. memcpy要比copy_to_user和copy_from_user效率高, 但不能用。 因为用户空间的内存有可能会失效, copy_to_user和copy_from_user会多做一些检查。
2. 没有限制, 这跟物理地址是否连续无关。
3. 效果不大, 减小函数的调用次数只能避免一些检查, 要只是数倍级的优化应该看不出效果。

|
1.数据对齐等这些是为了提高效率,可以一块一块(一般是4字节)的copy而不用一bit一bit这样麻烦
2.不清楚.
3.读取一个大块连续数据自然比分n次读取n个不连续块数据效率要高.但是不要为了效率失掉可读性,简单性.

|
1)性能的考虑吧,x86上是汇编写的,ARM上是用memcpy。 要知道当数据量很大的话,用mempcy会很占CPU。
2)应该没有。
3)应该有个中间值,APUE的第三章文件i/o的  "I/O效率"一节 有个实验。
我觉得这个应该跟cache有关的。
当数据非常大的时候,个人认为,copy_to_user和copy_from_user只用来传递指针,通过mmap来做user space和kernel space的
映射,效率会好些,v4l2的output实现就是这样的。

|
楼上说的对,因为用户空间的内存可能由于swap而失效,memcpy在这种情况下是不能使用的。

|
1.为了提高copy时的效率
3.感觉减少读写次数,应该可以提高效率

|
顶!

|


good!

|
学习

|

    
 
 
 
本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • Linux内核中影响tcp三次握手的一些协议配置
  • Fedora Core 2自带的内核升级程序下载下来内核后,要不要再编译一遍内核?
  • TCP协议四次断连过程介绍及Linux内核协议栈中相关设置项
  • 进程内核栈和操作系统内核栈的关系
  • CentOS 6内核升级:下载编译启用新内核版本详细过程
  • Linux中内核线程不访问内核态地址空间?
  • Linux进程的内核栈和用户栈概念,相互关系及切换过程
  • 2.6内核下编译2.4内核
  • linux内核中的likely宏和unlikely宏介绍及用法
  • 谁能提供kgdb内核补丁内核模块的下载
  • CentOS 6.5 下载地址及如何升级内核(kernel)版本到 3.10.28
  • 编译新内核后怎么进入原来内核
  • Linux下c/c++开发之程序崩溃(Segment fault)时内核转储文件(core dump)生成设置方法
  • 请问linux中如何判断内核是否已经启动。(在内核中写程序)
  • docker使用的技术之Container内核原理介绍
  • 内核模块跟内核版本不匹配????????
  • 请教:如何安装新内核(rpm包)而不同原来得内核冲突?? 在线等待!!
  • linux为什么要升级内核?升级内核有何作用?
  • 内核升级后,如何在新的内核中加载显卡驱动?
  • 内核源码和结果make过的内核源码有什么区别
  • 不重新编译内核能修改内核函数吗?


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3