精华内容
下载资源
问答
  • copy_to_user
    千次阅读
    2020-01-26 19:03:03

            在编写linux驱动程序的时候会用到copy_to_user()和copy_from_user()这两个函数。那这两个函数的作用是什么呢?为了便于理解,我们先来了解一下用户空间和内核空间。

            在linux系统中,每个进程的运行空间分为内核空间和用户空间。之所以划分成这两个空间,是因为在 CPU 的所有指令中,有些指令是非常危险的,如果错用,将导致系统崩溃,比如清内存、设置时钟等。如果允许所有的程序都可以使用这些指令,那么系统崩溃的概率将大大增加。所以,CPU 将指令分为特权指令和非特权指令,对于那些危险的指令,只允许操作系统及其相关模块使用,普通应用程序只能使用那些不会造成灾难的指令。这样将进程的运行空间分为内核空间和用户空间,会大大降低系统崩溃的可能性。

            对于32位系统,每个进程拥有 4G 的地址空间,较低的 3G 字节(从虚拟地址 0x00000000 到 0xBFFFFFFF)由进程使用,称为用户空间。而最高的 1G 字节(从虚拟地址 0xC0000000 到 0xFFFFFFFF)由内核使用,称为内核空间。由于两个空间是独立的,要实现内核空间与用户空间的数据传递就会用到copy_to_user()和copy_from_user()这两个函数。

            copy_to_user()这个函数的完整形态为

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

    这个函数的作用是将内核空间的数据复制到用户空间。其中
    to:目标地址(用户空间)
    from:源地址(内核空间)
    n:将要拷贝数据的字节数
    返回:成功返回0,失败返回没有拷贝成功的数据字节数

     

     

            copy_from_user()这个函数的完整形态为

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

    这个函数的作用是将用户空间的数据复制到内核空间。其中

    to:目标地址(内核空间)
    from:源地址(用户空间)
    n:将要拷贝数据的字节数
    返回:成功返回0,失败返回没有拷贝成功的数据字节数

    使用这个两个函数就可以实现内核空间和用户空间的数据交互了。

    更多相关内容
  • copy_to_user/copy_from_user参数解析

    千次阅读 2021-12-29 15:29:36
    copy_to_user解析 copy_to_user是在进行驱动相关程序设计的时候,要经常遇到的函数。由于内核空间与用户空间的内存不能直接互访,因此借助函数copy_to_user()完成内核空间到用户空间的复制,函数copy_from_user()...

    copy_to_user/copy_from_user解析

    copy_to_user和copy_from_user是在进行驱动相关程序设计的时候,要经常遇到的函数。由于内核空间与用户空间的内存不能直接互访,因此借助函数copy_to_user()完成内核空间到用户空间的复制,函数copy_from_user()完成用户空间到内核空间的复制。

    首先,我们来看一下这个函数的在源码文件中是如何定义的:

    copy_to_user
    Name
    copy_to_user --  Copy a block of data into user space.
    Synopsis
    
    unsigned long copy_to_user (void __user * to, const void * from, unsigned long n);
    
    Arguments
    
    to
    
    Destination address, in user space.
    from
    
    Source address, in kernel space.
    n
    
    Number of bytes to copy.
    Context
    
    User context only. This function may sleep.
    Description
    
    Copy data from kernel space to user space.
    
    Returns number of bytes that could not be copied. On success, this will be zero.
    

    从注释中就可以看出,这个函数的主要作用就是从内核空间拷贝一块儿数据到用户空间,由于这个函数有可能睡眠,所以只能用于用户空间。它有如下三个参数,

       To 目标地址,这个地址是用户空间的地址;
    
       From 源地址,这个地址是内核空间的地址;
    
       N 将要拷贝的数据的字节数。
    

    如果数据拷贝成功,则返回零;否则,返回没有拷贝成功的数据字节数。

    copy_from_user
    Name
    copy_from_user --  Copy a block of data from user space.
    Synopsis
    
    unsigned long copy_from_user (void * to, const void __user * from, unsigned long n);
    
    Arguments
    
    to
    
    Destination address, in kernel space.
    from
    
    Source address, in user space.
    n
    
    Number of bytes to copy.
    Context
    
    User context only. This function may sleep.
    Description
    
    Copy data from user space to kernel space.
    
    Returns number of bytes that could not be copied. On success, this will be zero.
    
    If some data could not be copied, this function will pad the copied data to the requested size using zero bytes.
    

    从注释中就可以看出,这个函数的主要作用就是从用户空间拷贝一块儿数据到内核空间,由于这个函数有可能睡眠,所以只能用于内核空间。它有如下三个参数,

       To 目标地址,这个地址是内核空间的地址;
    
       From 源地址,这个地址是用户空间的地址;
    
       N 将要拷贝的数据的字节数。
    

    如果数据拷贝成功,则返回零;否则,返回没有拷贝成功的数据字节数。

    展开全文
  • 简单的linux驱动,copy_to_user, copy_from_user 测试
  • ssize_t xxx_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos); ssize_t xxx_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos); 等函数中,filp...

    字符设备驱动驱动的读,写。如:
    ssize_t xxx_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos);
    ssize_t xxx_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos);
    等函数中,filp是文件结构体指针,buf是用户空间内存的地址,该地址在内核空间不能直接读写,count是
    要读写的字节数,f_pos是读的位置相对于文件开头的偏移。

    copy_from_user()和copy_to_user()函数的作用:由于内核空间与用户空间的内存不能直接互访,因此借助
    函数copy_to_user()完成内核空间到用户空间的复制,函数copy_from_user()完成用户空间到内核空间的复制。

     源码:linux/arch/i386/lib/usercopy.c

     copy_to_user: - Copy a block of data into user space.
     @to:   Destination address, in user space.
     @from: Source address, in kernel space.
     @n:    Number of bytes to copy.
     unsigned long    copy_to_user(void __user *to, const void *from, unsigned long n)

     {

              if (access_ok(VERIFY_WRITE, to, n))

                      n = __copy_to_user(to, from, n);
              return n;
      }


     copy_from_user: - Copy a block of data from user space.
     @to:   Destination address, in kernel space.
     @from: Source address, in user space.
     @n:    Number of bytes to copy.

      unsigned long   copy_from_user(void *to, const void __user *from, unsigned long n)
      {
              if (access_ok(VERIFY_READ, from, n))
                     n = __copy_from_user(to, from, n);
              else
                      memset(to, 0, n);
             return n;
      }
     


    其中access_ok(VERIFY_READ, from, n)检查当前需要访问的地址空间,有没有被其他空间访问,
    如果当前进程被允许访问地址addr处的内存,函数返回真(1),否则为假(0)。

     源码定义:linux/include/asm-m32r/uaccess.h
     #define access_ok(type,addr,size) (likely(__range_ok(addr,size) == 0))
     #else
     static inline int access_ok(int type, const void *addr, unsigned long size)
     {
             extern unsigned long memory_start, memory_end;
             unsigned long val = (unsigned long)addr;
     
             return ((val >= memory_start) && ((val + size) < memory_end));
     }
    

      
      其中__copy_to_user(to, from, n);__copy_from_user(to, from, n);才函数实现部分。
      

    源码:linux/include/asm-frv/uaccess.h
      static inline unsigned long __must_check
     __copy_to_user(void __user *to, const void *from, unsigned long n)
     {
            might_sleep();
             return __copy_to_user_inatomic(to, from, n);
     }
     #define __copy_to_user_inatomic(to, from, n)    (memcpy(____force(to), (from), (n)), 0)


     static inline unsigned long
     __copy_from_user(void *to, const void __user *from, unsigned long n)
      {
            might_sleep();
             return __copy_from_user_inatomic(to, from, n);
      }
     #define __copy_from_user_inatomic(to, from, n)  (memcpy((to), ____force(from), (n)), 0)


     函数源码定义在:linux/arch/alpha/lib/memcpy.c
     原型:extern void *memcpy(void *dest, void *src, unsigned int count);
      功能:由src所指内存区域复制count个字节到dest所指内存区域。
      说明:src和dest所指内存区域不能重叠,函数返回指向dest的指针
      
      注:上述系列函数均返回不能复制的字节数,因此,完全复制成功,返回值0。
      且__copy_to_user()和__copy_from_user()如果直接调用的时候,不会调用
      access_ok(VERIFY_READ, from, n)检查函数,也就是不会检查当前需要访问的空间,
      有没有被其他空间访问。

    而get_user(),put_user()的作用:
    复制的内存是简单类型,如char,int ,long等,则可以使用简单的put_user()和get_user()
    get_user --  Get a simple variable from user space.
    put_user --  Write a simple value into user space.

    源码定义:linux/include/asm-i386/uaccess.h
      #define put_user(x,ptr)                                         \
     ({      int __ret_pu;                                           \
              __typeof__(*(ptr)) __pu_val;                            \
              __chk_user_ptr(ptr);                                    \
              __pu_val = x;                                           \
              switch(sizeof(*(ptr))) {                                \
              case 1: __put_user_1(__pu_val, ptr); break;             \
              case 2: __put_user_2(__pu_val, ptr); break;             \
              case 4: __put_user_4(__pu_val, ptr); break;             \
             case 8: __put_user_8(__pu_val, ptr); break;             \
              default:__put_user_X(__pu_val, ptr); break;             \
              }                                                       \
              __ret_pu;                                               \
      })


     在put_user(x,ptr)定义如下:
     x:用户内存空间的整型变量
     ptr:用户空间的地址
     
     下面只对put_user()函数分析:
     

     # define __chk_user_ptr(x) (void)0   取得ptr指向的0地址,然后
     __pu_val = x;可以得到x的偏移地址,这样就可以指向x。

     #define container_of(ptr, type, member) ({                      \
              const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
              (type *)( (char *)__mptr - offsetof(type,member) );})

     和这个宏定义很类似。
     
     该代码switch()执行的代码:

       #define __put_user_1(x, ptr) __asm__ __volatile__("call __put_user_1":"=a" (__ret_pu):"0" ((typeof(*(ptr)))(x)), "c" (ptr))
      #define __put_user_2(x, ptr) __asm__ __volatile__("call __put_user_2":"=a" (__ret_pu):"0" ((typeof(*(ptr)))(x)), "c" (ptr))
      #define __put_user_4(x, ptr) __asm__ __volatile__("call __put_user_4":"=a" (__ret_pu):"0" ((typeof(*(ptr)))(x)), "c" (ptr))
      #define __put_user_8(x, ptr) __asm__ __volatile__("call __put_user_8":"=a" (__ret_pu):"A" ((typeof(*(ptr)))(x)), "c" (ptr))
     #define __put_user_X(x, ptr) __asm__ __volatile__("call __put_user_X":"=a" (__ret_pu):"c" (ptr))


     get_user()原理相同,请自己分析。
     
     而__get_user(),__put_user()函数与上面一样,只是不会调用
      access_ok(VERIFY_READ, from, n)检查函数,也就是不会检查当前需要访问的空间,
      有没有被其他空间访问。

    展开全文
  • 一、Copy_to_user 功能:用于将内核空间的数据拷贝到用户空间。 函数原型:unsigned long copy_to_user(void __user *to, const void *from, unsigned long n); *to是用户空间的指针, *from是内核空间指针, n...

    一、copy_to_user
    功能:用于将内核空间的数据拷贝到用户空间。
    函数原型:unsigned long copy_to_user(void __user *to, const void *from, unsigned long n);

    *to是用户空间的指针,
    *from是内核空间指针,
    n表示从内核空间向用户空间拷贝数据的字节数

    如果数据拷贝成功,则返回零;否则,返回没有拷贝成功的数据字节数。

    二、copy_from_user
    功能:用于将用户空间的数据传送到内核空间。
    函数原型:unsigned long copy_from_user(void * to, const void __user * from, unsigned long n)

    第一个参数to是内核空间的数据目标地址指针,
    第二个参数from是用户空间的数据源地址指针,
    第三个参数n是数据的长度。

    如果数据拷贝成功,则返回零;否则,返回没有拷贝成功的数据字节数。
    此函数将from指针指向的用户空间地址开始的连续n个字节的数据发送到to指针指向的内核空间地址

    例子:

    	struct as2056_rmsg *rmsg = NULL;
    	char *buffer = NULL;
    	
    	//申请内存空间存放数据,
    	//申请的空间大小跟as2056_rmsg 结构体一样
    	rmsg = kmalloc(sizeof(struct as2056_rmsg), GFP_KERNEL); //切记,要申请内存空间才能使用
    	 
    	if(rmsg == NULL) {
    		printk("error: allo\n");
    		return -EFAULT;
    	}
    	
    	//从用户空间拷贝as2056_rmsg 结构体指向的数据到内核空间的指针rmsg当中,成功则返回零;
    	//否则,返回没有拷贝成功的数据字节数。
    	ret = copy_from_user(rmsg, (struct as2056_rmsg *)arg, sizeof(struct as2056_rmsg)); 
    	 if(ret) {
    		kfree(rmsg);
            printk("copy write mesg from user error, ret = %d\n", ret);
            return -EFAULT;
        }
    
    
    	//申请内存空间存放数据,申请的空间大小跟rmsg->rlen一致
    	buffer = kmalloc(rmsg->rlen, GFP_KERNEL); //切记,要申请内存空间才能使用
    	if(buffer == NULL) {
    		kfree(rmsg);
    		printk("error: allo\n");
    		return -EFAULT;
    	}
    	//从内核空间buffer拷贝数据到用户空间rmsg->buf,成功则返回零;
    	//否则,返回没有拷贝成功的数据字节数。
    	ret = copy_to_user(rmsg->buf, buffer, rmsg->rlen); 
    	if(ret) {
    		kfree(buffer);
    		kfree(rmsg);
            printk("copy data to user failed = %d\n", ret);
            return -EFAULT;
        }
    
    展开全文
  • get_user/put_usercopy_from_user/copy_to_user都是用于用户空间与内核空间的数据交换,区别在于: 1.get_user/put_user用于简单类型的拷贝,例如int、long;copy_from_user/copy_to_user用于拷贝大量数据,类似...
  • copy_to_user()和copy_from_user() 由于内核空间与用户空间的内存不能直接互访, 因此借助函数 copy_from_user()完成用户空间到内核空间的复制, 函数copy_to_user()完成内核空间到用户空间的复制。 copy_from_...
  • linux内核中的copy_to_usercopy_from_user

    千次阅读 2018-11-12 10:19:06
    Kernel version:2.6.14 CPU architecture:ARM920T ...在学习Linux内核驱动的时候,经常会碰到copy_from_usercopy_to_user这两个函数,设备驱动程序中的ioctl函数就经常会用到。这两个函数负责在用户空间和内核...
  • 1、copy_to_user & copy_from_user 函数原型 long copy_to_user(void __user *to, const void *from, unsigned long n) long copy_from_user(void *to, const void __user * from, unsigned long n) (1)copy_...
  • copy_to_usercopy_form_user函数分析

    千次阅读 2018-07-21 14:46:19
    学习驱动比较常用的两个函数,copy_to_usercopy_form_user。   因为传参都是传的地址,单因为内核空间不能直接访问用户空间的内存,所以内核空间要使用用户空间参数。必须进行地址转换。而这连个函数就是负责把...
  • 文章目录一、定义二、例子三、问题1.隐式声明函数‘copy_from_user’ ...copy_to_user( buf, rwbuf, count); 【作用】:从内核空间复制到用户空间 【头文件】: #include <linux/uaccess.h> // co...
  • 我使用功能copy_to_user(void user *to, const void *from, unsigned long n)将数据从内核空间复制到用户空间缓冲区。我们可以在#include < asm/uaccess.h >头文件中找到此功能。我使用通用的Linux内核版本...
  • static inline int copy_to_user(void __user *to, const void... return(CHOOSE_MODE_PROC(copy_to_user_tt, copy_to_user_skas, to, from, n)); } 从 上面可以推测把 to 是目标地址 from 是源地址 n 是大小 ...
  • 谈一谈copy_from_usercopy_to_user

    万次阅读 多人点赞 2018-12-23 23:36:28
    copy_from_usercopy_to_user这两个函数相信做内核开发的人都非常熟悉,分别是将用户空间的数据拷贝到内核空间以及将内核空间中的数据拷贝到用户空间。这两个函数一般用于系统调用中,前者将用户空间参数拷贝到内核...
  • copy_to_usercopy_from_user函数

    千次阅读 2018-06-20 22:31:47
     copy_to_user:从内核空间复制数据到用户空间 copy_from_user:从用户空间复制数据到内核空间。 在进行驱动相关程序设计时,经常会用到这两个函数,因为底层驱动显然是内核空间,调用驱动的是用户空间。 具体函数...
  • 为什么要用copy_from_user/copy_to_user?

    千次阅读 2018-05-10 09:27:16
    如果应用程序传入了一个参数user_arg,指向的是用户空间的地址。那么我们在内核态里能否直接从这个地址读取数据呢?答案是肯定的,因为内核能够看到进程的整个地址空间,属于这个进程的所有page在此进程的page table...
  • ssize_t xxx_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos); ssize_t xxx_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos); 等函数中,f
  • 感觉里面有点东西,粗暴的理解一下:(两个函数都是写在内核里面的,to是发送数据给用户,from是从用户接收)copy_to_user函数原型static inline long copy_to_user(void __user *to,const void *from, unsigned ...
  • copy_to_usercopy_from_user都有可能引起阻塞,当包含用户数据的页被换出到硬盘上而不是在物理内存上的时候,这种情况就会发生。此时,进程就会休眠,直到缺页处理程序将该页从硬盘重新换回物理内存 ...
  • linux内核中的copy_to_usercopy_from_user(一) Kernel version:2.6.14 CPU architecture:ARM920T Author:ce123(http://blog.csdn.net/ce123) 1.copy_from_user 在学习Linux内核驱动的时候,经常会...
  • linux中copy_to_user()和copy_from_user()函数

    千次阅读 2019-03-31 13:49:45
    由于内核空间与用户空间的内存不能直接互访, 因此借助函数 copy_from_user()完成用户空间...copy_from_user()和 copy_to_user()的原型如下所示: unsigned long copy_from_user(void *to, const void __user *fr...
  • linux内核:copy_to_usercopy_from_user

    千次阅读 2021-12-15 23:32:13
    copy_to_usercopy_from_user 在linux内核中,我们将用户态数据拷贝到内核或者将用户态数据拷贝到内核,使用的是copy_from_usercopy_to_user。 但是在有些情况下,我们直接使用memcpy也不会出现错误,可以正常...
  • 隐式声明函数‘raw_copy_to_user’的问题 其实一般来说都是隐式声明函数‘copy_to_user’的问题,这类问题你就看看有没有引用正确的头文件, 例如有些是<asm/uaccess.h>, 有些是<linux/uaccess.h>, 你...
  • error: implicit declaration of function ‘copy_to_user’ [-Werror=implicit-function-declaration] copy_to_user(buf,(void *)(pDev-&gt;myData+*ppos),size); error: implicit declaration of f...
  • https://yq.aliyun.com/articles/30152设备读操作如果该操作为空,将使得read系统调用返回负EINVAL失败,正常返回实际读取的字节数ssize_t (*read)(struct file *filp, char __user *buf, size_t count, lofft *f_...
  • implicit declaration of function “copy_to_user”, 原因很简单是缺少头文件。 添加头文件即可: #include <linux/uaccess.h> 报错: 解决: PS:有的网友提到添加#in...
  • copy_from_usercopy_to_user这两个函数相信做内核开发的人都非常熟悉,分别是将用户空间的数据拷贝到内核空间以及将内核空间中的数据拷贝到用户空间。这两个函数一般用于系统调用中,前者将用户空间参数拷贝到内核...
  • Linux Kerne copy_to_usercopy_from_user
  • copy_to_user copy_from_user返回值

    万次阅读 2016-06-29 11:36:35
    copy_to_user 内核空间与用户空间数据传递的通道是copy_to_usercopy_from_user,刚开始使用时对他们的返回值非常困惑。 按照”常理”,返回值应该是copy成功了多少个Bytes。但是在kernel里面,他们的语义是...
  • copy_to_user()和copy_from_user()的使用

    万次阅读 2016-07-11 15:23:48
    driver和user之间经常需要数据传输,使用copy_to_user()和copy_from_user()来实现driver到useruser到driver的数据传送。 函数原型: unsigned long copy_to_user(void *to, const void __user *from,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 300,695
精华内容 120,278
关键字:

copy_to_user