put_user()和get_user()用戶空間傳遞數據


一、往用戶空間傳遞數據

1.傳遞單個數據

put_user()可以向用戶空間傳遞單個數據。單個數據並不是指一個字節數據,對ARM而言, put_user一次性可傳遞一個char , short或者int型的數據,即1、2或者4字節。用put_user比用copy_to_user要快:

int put_user(x,p)
  • x 為內核空間的數據,
  • p 為用戶空間的指針。
  • 傳遞成功,返回 0,否則返回-EFAULT

put_user 一般在 ioctl 方法中使用,假如要往用戶空間傳遞一個 32 位的數據,可以這樣實現:

 

static int char_cdev_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
  int ret;
  u32 dat,
  switch(cmd)
  {
    case CHAR_CDEV_READ:
    ...其它操作
    dat = 數據;
    if (put_user(dat, (u32 *)arg) ) {
      printk("put_user err\n");
      return -EFAULT;
    }
  }
  ...其它操作
  return ret;
}

__put_user 是沒有進行地址驗證的版本。

2.傳遞多個數據

copy_to_user()可以一次性向用戶空間傳遞一個數據塊,函數原型如下:

static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n);
  • to 是內核空間緩沖區地址,
  • from 是用戶空間地址,
  • n 是數據字節數,
  • 返回值是不能被復制的字節數,返回 0 表示全部復制成功。

copy_to_user()一般在 read 方法中使用。假如驅動要將從設備讀到的 count 個數據送往用戶空間,可以這樣實現:

 

static ssize_t char_cdev_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
{
    unsigned char data[256] = {0};
    ....從設備獲取數據
    if (copy_to_user((void *)buf, data, count)) {
        printk("copy_to_user err\n");
    return -EFAULT;

    }
    return count;
}

__copy_to_user 是沒有進行地址驗證的版本。

 

二、從用戶空間獲取數據

1.獲取單個數據

調用get_user()可以從用戶空間獲取單個數據,單個數據並不是指一個字節數據,對ARM而言,get_user一次性可獲取一個char、short或者 int型的數據,即1、2或者4字節。用get_user比用get_from_user要快:

int get_user(x,p)
  • x為內核空間的數據
  • p為用戶空間的指針。
  • 獲取成功,返回0,否則返回-EFAULT.

get_user()一般也用在ioctl方法中。假如驅動需要從用戶空間獲取一個32位數,然后寫到某個寄存器中,可以這樣實現:

 

static int char_cdev_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
  int ret;
  u32 dat,
switch(cmd)
{
  case CHAR_CDEV_WRITE:
  if (get_user(dat, (u32 *)arg) ) {
  printk("get_user err\n");
  return -EFAULT;
}
  CHAR_CDEV_REG = dat;
  ...其它操作
}
  ...其它操作
  return ret;
}

__get_user 是沒有進行地址驗證的版本。

 

2.獲取多個數據

copy_from_user()可以一次性從用戶空間獲取一個數據塊。
函數原型如下:

static inline unsigned long _must_ check copy_from_user(void *to, const void_user*from, unsigned long n);
  • to是內核空間緩沖區地址,
  • from是用戶空間地址
  • n是數據字節數
  • 返回值是不能被復制的字節數,返回0表示全部復制成功。

copy_from_user()常用在 write方法中。如果驅動需要從用戶空間獲取count字節數據,用於操作設備,可以這樣實現:

 

static ssize_t char_cdev_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
{
    unsigned char data[256];

    if (copy_from_user(&data, buf, 256) ) {
    printk("copy_from_user err\n");
    return -EFAULT;
    }
    ...
}

__copy_from_user 是沒有進行地址驗證的版本。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM