Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1843466
  • 博文数量: 383
  • 博客积分: 10011
  • 博客等级: 上将
  • 技术积分: 4061
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-24 18:53
文章分类

全部博文(383)

文章存档

2011年(1)

2010年(9)

2009年(276)

2008年(97)

我的朋友

分类: LINUX

2008-12-30 15:47:55

   最近在和同学们一起学习Linux驱动开发方面的知识,在学习过程中经常会遇到一些关于内核的知识,牵扯到一些数据结构和函数, 在遇到时我们没有绕过去,而是直接去看源代码,在此期间收获了不少,发现内核写的确实很好很强大,要一下搞定它,那是痴心妄想,所以我从一些小的地方开 始,在遇到内核源码时就去读它。今天读到一个有用的函数:copy_to_user(),其在内核定义如下:


835 /**
 836 * copy_to_user: - Copy a block of data into user space.
 837 * @to: Destination address, in user space.
 838 * @from: Source address, in kernel space.
 839 * @n: Number of bytes to copy.
 840 *
 841 * Context: User context only. This function may sleep.
 842 *
 843 * Copy data from kernel space to user space.
 844 *
 845 * Returns number of bytes that could not be copied.
 846 * On success, this will be zero.
 847 */

 848 unsigned long
 849 copy_to_user(void __user *to, const void *from, unsigned long n)
 850 {
 851 if (access_ok(VERIFY_WRITE, to, n))
 852 n = __copy_to_user(to, from, n);
 853 return n;
 854 }


   相信稍微懂英语的人都能读懂前面的注释,其功能是将内核空间的内容复制到用户空间,所复制的内容是从from来,到to去,复制n个位。
 其中又牵扯到两个函数:access_ok()和__copy_to_user(),好我们继续往下深入,先来看看第一个函数access_ok()的源码:

85/**
  86 * access_ok: - Checks if a user space pointer is valid
  87 * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE. Note that
  88 * %VERIFY_WRITE is a superset of %VERIFY_READ - if it is safe
  89 * to write to a block, it is always safe to read from it.
  90 * @addr: User space pointer to start of block to check
  91 * @size: Size of block to check
  92 *
  93 * Context: User context only. This function may sleep.
  94 *
  95 * Checks if a pointer to a block of memory in user space is valid.
  96 *
  97 * Returns true (nonzero) if the memory block may be valid, false (zero)
  98 * if it is definitely invalid.
  99 *
 100 * Note that, depending on architecture, this function probably just
 101 * checks that the pointer is in the user space range - after calling
 102 * this function, memory access functions may still return -EFAULT.
 103 */

 104#ifdef CONFIG_MMU
 105#define access_ok(type,addr,size) (likely(__range_ok(addr,size) == 0))
 106#else
 107static inline int access_ok(int type, const void *addr, unsigned long size)
 108{
 109 extern unsigned long memory_start, memory_end;
 110 unsigned long val = (unsigned long)addr;
 111
 112 return ((val >= memory_start) && ((val + size) < memory_end));
 113}
 114#endif /* CONFIG_MMU */


    其功能是检查用户空间是否合法,它的第一个参数:type,有两种类型:VERIFY_READ 和VERIFY_WRITE,前者为可读,后者可写,注意:如果标志为可写(VERIFY_WRITE)时,必然可读!因为可写是可读的超集(% VERIFY_WRITE is a superset of %VERIFY_READ)。
   检查过程如下:addr为起始地址,size为所要复制的大小,那么从addr到addr+size则是所要检查的空间,如果它的范围在memory_start和memory_end之间的话,则返回真。至于memory_start详细信息,我没有读。
   到此为止,如果检查合法,那么OK,我们来实现真正的复制功能:__copy_to_user(),其源码定义如下:


80static inline __kernel_size_t __copy_to_user(void __user *to, const void *from,
  81 __kernel_size_t n)
  82{
  83 return __copy_user((void __force *)to, from, n);
  84}


    哈哈,又遇到一个函数:__copy_user(),这个函数才真正在做底层的复制工作。想继续深入的:看这里
()。
 我的分析到此为止。

 补充:    
    __copy_to_user()就是对__copy_user()的封装.其实, 在函数:copy_from_user()中,也调用了这个函数。也就是说这个函数实现了内核空间与用户空间的相互复制。


阅读(5647) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~