关于copy_to_user和copy_from_user的学习小结

花了一天时间,希望能理解这两个接口和内核空间下对用户空间数据的拷贝问题,可惜事与愿违,虽有收获,还是留下了很多问题。


遗留的问题

首先,关于内核空间下是不允许发生页面错误的疑惑:

1.内核的内存空间本身就具有虚拟性的概念,那么当内核的内存区需要换页时,该如何实现的呢?2.这样的规定是基于什么原因设定的?是操作系统设计时安全性,性能考虑,还是CPU体系结构上就做出了这样的设定?或者说假设可以页错误,那么接下来的问题是无法合理实现还是存在严重的性能或安全隐患?(这个问题可能是有点钻牛角尖了,但找不到答案就是放不下)3.换页过程具体流程(等到MMU学习时勿忘)


其次,关于copy_to_user和copy_from_user接口:

copy_to_user接口的注释中有:“* Context: User contextonly. 即只能在用户空间(上下文)中运行,但调用这个接口肯定都是内核代码,那么这个空间切换是何时在何处完成的,一直未能找出答案。


一点心得——如何更好的阅读内核代码

在查找copy_to_user及其子函数的代码时,发现这些接口在整个内核树有多达10多种实现方式,这时,更多的是靠对内核树的理解,直接到相应的目录和文件下查找代码。例如查找copy_to_user定义处,内核中就十来种实现,那么此时应该明确,copy_to_user是与CPU体系结构相关的,那么就应该直接到arch/X86/lib下寻找,这样反而要快的多。


知识点

关于__attribute__:

       在copy_to_user接口的入口处,对目的指针有一个__user的修饰符,其定义是:# define __user__attribute__((noderef, address_space(1)))

如何理解这个语句呢?对linux内核中compiler.h文件的分析这篇文章非常棒的总结了__attribute__的一些用法。其实归根结底,__user仍是帮助编译器更好的检查所声明的变量。

       以上,__attribute__大多作为变量,结构体的修饰符,实际上,其也可修饰函数。在函数属性方面,作用也基本是帮助编译器更好的检查错误或去掉某些没有必要的编译警告。主要可以参考Using GNU C __attribute__


关于likely(x)和unlikely(x):

这两个宏对条件(逻辑)表达式X的返回值不做任何影响,只是对之后的分支预测做出优化。若程序员预计程序运行时,X的取值更可能为1(真),则用likely;若为0(假),则用unlikely,使分支代码安排在判断语句之后,减掉一个跳转语句的执行。

另外,这两个宏是GCC的内建宏,可以从其宏定义中的__builtin看出:

#definelikely(x)       __builtin_expect(!!(x), 1)
    #define unlikely(x)    __builtin_expect(!!(x), 0)

 

关于利用do{}while(0)封闭宏的技巧:

might_sleep()宏在非DEBUG版本下的声明:

# define might_sleep() do { might_resched(); }while (0)

其中do{}while(0),是为了对外界封闭声明的代码块。注意,一般的,while(0)后没有分号!至于这种方法比简单的打对大括号,安全在哪里,目前还找不出例子,但至少感觉上这种方法是要比一对大括号要强的。


关于EXPORT_SYMBOL

粗略的看了下,主要查阅的是谈EXPORT_SYMBOL使用这篇文章。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值