linux驅動學習之ioctl介面

來源:互聯網
上載者:User

   這裡先用例子介紹一下ioctrl介面的使用, 應用程式層的ioctl函數傳入的cmd和arg參數會直接傳入驅動層的ioctl介面,ioctl介面的命令有一定規範詳細查看ioctl-number.txt檔案,這裡命令的定義不在規範內,先看下面測試的例子,驅動只實現ioctrl介面並使用ioctl修改和讀取核心中的一個整型參數為例,使用兩個不同方式讀取(值傳遞和地址傳遞)。

 

 應用程式測試代碼main.c

#include <stdio.h>#include <fcntl.h>#include <sys/types.h>#include <unistd.h>#include <sys/ioctl.h>#define IOCTL_RESET 100 /*重設命令*/#define IOCTL_GET1  101 /*讀取命令值返回*/#define IOCTL_GET2  102 /*讀取命令地址返回*/#define IOCTL_SET1  103 /*設定命令值傳入*/#define IOCTL_SET2  104 /*設定命令地址傳入*/int main (int *argc,char**argv){  int  fs;int val;  fs=open("/dev/moduledev60",O_RDWR);  if(fs<0)  {    printf("open fail\n");    return -1;  }  ioctl(fs,IOCTL_SET1,1000);                               //使用值傳入設定參數  printf("ioctl get1 result:%d\n",ioctl(fs,IOCTL_GET1));   //使用傳回值讀取參數  ioctl(fs,IOCTL_GET2,&val);                               //使用地址讀取參數   printf("ioctl get2 result:%d\n",val);          /*當設定參數是負數時 使用傳回值讀參數會出錯 由於ioctl返回負數會被核心認為錯誤*/  ioctl(fs,IOCTL_SET1,-100);                               //使用值傳入設定參數  printf("ioctl get1 result:%d\n",ioctl(fs,IOCTL_GET1));   //使用傳回值讀取參數  ioctl(fs,IOCTL_GET2,&val);                               //使用地址讀取參數   printf("ioctl get2 result:%d\n",val);    /*使用地址傳入設定參數*/  val=5555;  ioctl(fs,IOCTL_SET2,&val);  printf("ioctl get1 result:%d\n",ioctl(fs,IOCTL_GET1));   close(fs);  return 0;}

驅動主要部分 fileops.c

#define IOCTL_RESET 100 /*重設命令*/#define IOCTL_GET1  101 /*讀取命令值返回*/#define IOCTL_GET2  102 /*讀取命令地址返回*/#define IOCTL_SET1  103 /*設定命令值傳入*/#define IOCTL_SET2  104 /*設定命令地址傳入*/int drive_param=0;int fileops_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){  printk(KERN_ALERT "fileops_ioctl  \n");  switch(cmd)  {    case IOCTL_RESET:  drive_param=0;  break;case IOCTL_GET1:  return drive_param;  break;case IOCTL_GET2://  __put_user(drive_param,(int __user *)arg);      if(copy_to_user((int __user*)arg,&drive_param,4)) return -ENOTTY;      break;case IOCTL_SET1:  drive_param=arg;  break;case IOCTL_SET2://  __get_user(drive_param,(int __user *)arg);      if(copy_from_user(&drive_param,(int __user*)arg,4))return -ENOTTY;      break;    }  return 0;}

傳送單個值時使用 __put_user __get_user要比copy相對快,  注意 __put_user,__get_user 應當只用在已經使用 access_ok 校正過的地址.copy_from_user和copy_to_user跟蹤代碼會發現已經加了access_ok的校正。

執行結果

ioctl get1 result:1000ioctl get2 result:1000ioctl get1 result:-1ioctl get2 result:-100ioctl get1 result:5555

會發現使用值返回負數-100時,驅動介面內返回-100應用程式的ioctl返回的是-1,使用地址傳遞參數則正確讀取。

下面是部分ioctl-number.tx的內容

If you are adding new ioctl's to the kernel, you should use the _IO macros defined in <linux/ioctl.h>:    _IO    an ioctl with no parameters    _IOW   an ioctl with write parameters (copy_from_user)    _IOR   an ioctl with read parameters  (copy_to_user)    _IOWR  an ioctl with both write and read parameters.'Write' and 'read' are from the user's point of view, just like the system calls 'write' and 'read'.  For example, a SET_FOO ioctl would be _IOW, although the kernel would actually read data from user space;a GET_FOO ioctl would be _IOR, although the kernel would actually write data to user space.The first argument to _IO, _IOW, _IOR, or _IOWR is an identifying letter or number from the table below.  Because of the large number of drivers,many drivers share a partial letter with other drivers.If you are writing a driver for a new device and need a letter, pick an unused block with enough room for expansion: 32 to 256 ioctl commands.You can register the block by patching this file and submitting the patch to Linus Torvalds.  Or you can e-mail me at <mec@shout.net> and I'll register one for you.The second argument to _IO, _IOW, _IOR, or _IOWR is a sequence number to distinguish ioctls from each other.  The third argument to _IOW,_IOR, or _IOWR is the type of the data going into the kernel or coming out of the kernel (e.g.  'int' or 'struct foo').  NOTE!  Do NOT use sizeof(arg) as the third argument as this results in your ioctl thinking it passes an argument of type size_t.Some devices use their major number as the identifier; this is OK, as long as it is unique.  Some devices are irregular and don't follow any convention at all.Following this convention is good because:(1) Keeping the ioctl's globally unique helps error checking: if a program calls an ioctl on the wrong device, it will get an  error rather than some unexpected behaviour.(2) The 'strace' build procedure automatically finds ioctl numbers  defined with _IO, _IOW, _IOR, or _IOWR.(3) 'strace' can decode numbers back into useful names when the  numbers are unique.(4) People looking for ioctls can grep for them more easily when  this convention is used to define the ioctl numbers.(5) When following the convention, the driver code can use generic  code to copy the parameters between user and kernel space.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.