天天看點

核心函數 copy_to_user

835  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  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

其功能是檢查使用者空間是否合法,它的第一個參數:type,有兩種類型:VERIFY_READ 和VERIFY_WRITE,前者為可讀,後者可寫,注意:如果标志為可寫(VERIFY_WRITE)時,必然可讀!因為可寫是可讀的超集(% VERIFY_WRITE is a superset of %VERIFY_READ)。    檢查過程如下:addr為起始位址,size為所要複制的大小,那麼從addr到addr+size則是所要檢查的空間,如果它的範圍在memory_start和memory_end之間的話,則傳回真。到此為止,如果檢查合法,那麼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()中,也調用了這個函數。也就是說這個函數實作了核心空間與使用者空間的互相複制。

繼續閱讀