1. 程式人生 > >linux驅動學習之ioctl介面

linux驅動學習之ioctl介面

   這裡先用例子介紹一下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:1000
ioctl get2 result:1000
ioctl get1 result:-1
ioctl get2 result:-100
ioctl 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 <[email protected]> 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.


相關推薦

linux驅動學習ioctl介面

   這裡先用例子介紹一下ioctrl介面的使用, 應用層的ioctl函式傳入的cmd和arg引數會直接傳入驅動層的ioctl介面,ioctl介面的命令有一定規範詳細檢視ioctl-number.txt檔案,這裡命令的定義不在規範內,先看下面測試的例子,驅動只實現ioctr

嵌入式Linux驅動學習引導篇——為什麼要選擇嵌入式Linux驅動這個方向?

      醞釀了幾分鐘,依舊不知道如何開篇(這可能是工科男的一個通病吧)。索性隨意起來,想到哪寫到哪,這樣也許思維能變得更加活躍呢。      先交代一下背景,本人目前是國內某普通一本高校的一名大三學生,讀的專業是電氣工程及其自動化。轉程式猿也是目前大多數跨專業就業學生的首

嵌入式Linux驅動學習USART串列埠控制:基於AT91SAM9261EK

    普通微控制器的串列埠操作比較容易,但是基於Linux系統的串列埠操作難不難呢?其實,基於Linux作業系統的串列埠操作分為兩個部分:串列埠驅動部分(底層驅動與設備註冊)與串列埠的應用程式(使用者程式)。一般廠家或是Linux核心已經提供了基於開發板的串列埠驅動,只需

linux基礎學習圖形介面與命令列介面切換

首先,開機時進入到LINUX的圖形介面 緊接著,選中左上角的Applications----system tools-----terminal 選項 注意,使用者必須為ROOT,具備最高許可權

樹莓派linux驅動學習LED控制

#include <linux/miscdevice.h> #include <linux/delay.h> #include <asm/irq.h> #include <linux/kernel.h> #include <linux/module.h&g

linux驅動編寫中斷處理

類型 div 應該 urn 處理方式 com pre turn 申請 一、中斷 1、概念 學過單片機的應該非常清楚中斷的概念,也就是CPU在正常執行程序過程中,出現了突發事件(中斷事件),於是CPU暫停當前程序的執行,轉去處理突發事件。處理完畢後,CPU又返回被

linux驅動開發蜂鳴器驅動源碼分析(一)

linux 蜂鳴器 驅動 蜂鳴器的驅動源碼在/driver/char/buzzer/x210-buzzer.c文件中,源碼如下#include <linux/module.h> #include <linux/kernel.h> #include <linux

Linux系統學習Ln(軟連接和硬鏈接)

director 連接 鏈接 然而 符號連接 硬鏈接 信息 oinstall 不同 可簡單理解為,軟連接:創建的軟連接文件是源文件的快捷方式,刪除創建的軟連接文件,源文件不受影響,連接消失。 硬鏈接:兩個連體的文件,修改其中一個文件,另外一個文件也會隨之更改;刪除其中一個文

linux驅動開發framebuffer應用編程實踐(一)

linux驅動開發之framebuffer驅動 1、framebuffer應用編程 (1)打開設備文件 (2)獲取設備信息 宏定義的命令在/linux/fb.h中 不可變信息FSCREENINFO,使用ioctl參數有FBIOGET_FSCREENINFO宏名,表示用ioctl從

驅動學習gpiolib的建立過程

linux驅動 gpiolib1:gpiolib的學習重點(1)gpiolib的建立過程:gpiolib和虛擬地址映射類似,也是需要一個建立過程的,因此在學習的時候,我們需要明白gpiolib是什麽時候建立的,建立函數在哪被調用的。(2)gpiolib的使用方法:申請、使用、釋放(3)gpiolib的架構:涉

Linux命令學習—每天發一個命令—mkdir

linux 命令 mkdirLinux命令學習之—每天發一個命令—mkdirmkdir 命令用來創建指定的名稱的目錄,要求創建目錄的用戶在當前目錄中具有寫權限,並且指定的目錄名不能是當前目錄中已有的目錄。1.命令格式:mkdir [選項] 目錄...2.命令功能:通過 mkdir 命令可以實現在指定位置創建以

linux驅動系列程序反匯編

.html 動態庫 log end 作用 文件 二進制文件 調試 可執行文件 摘抄網頁:http://www.169it.com/article/330129798173630299.html 參考網頁:http://www.cppblog.com/liu1061/art

Linux學習

Linux這路Linux的文件系統層級結構標準FHS /etc=====和主機相關的系統配置文件 edit the configure /home===== 用戶家目錄 /usr======二層分層的目錄。默認是最大的。 /dev=====設備文件 /media======掛載點和可移動的設備, /

Linux實驗樓學習

.com rep thead ali 字典 過濾 del 添加用戶 技術 查看用戶 who am i or who mom likes who 命令其它常用參數 參數說明 -a 打印能打印的全部 -d 打印死掉的進程 -m 同am i,mom likes

linux命令學習:chmod

指令執行過程 rwx 屬於 col code linux系統中 相關 此外 相同   chmod命令用來變更文件或目錄的權限。在Linux系統家族裏,文件或目錄權限的控制分別以讀取R、寫入W、執行X3種一般權限來區分,另有3種特殊權限可供運用。用戶可以使用chmod指令去變

Linux命令學習shift命令

meta 就是 bash 網絡接口 sch 筆記本 結束 package PE 位置參數可以用shift命令左移。比如shift 3表示原來的$4現在變成$1,原來的$5現在變成$2等等,原來的$1、$2、$3丟棄,$0不移動。不帶參數的shift命令相當於shift

Linux系統學習 一:新手必須掌握的Linux命令1

網絡設備 agents daemon gen boot 3.0 media license bubuko 2018-10-03 16:04:12 一、常用系統工作命令 1、wget 命令 作用:用於在終端中下載網絡文件。 格式:wget [參數] 下載地址 參數及作用

docker系統學習docker介面管理

docker視覺化介面 dockerUI已廢棄,轉投Portainer專案 Portainer,輕量級管理介面,基本滿足中小單位需求 官方Github https://github.com/portainer/portainer Kitematic:這是個桌面應用,適用

linux驅動編寫poll機制

linux驅動編寫之poll機制 1. poll情景描述:              以按鍵驅動為例進行說明,用阻塞的方式開啟按鍵驅動檔案/dev/buttons,     應

初識Linux 驅動移植 dm9621網絡卡驅動移植

概述 將kernel移植到開發板並能正常載入和啟動核心後,發現網絡卡並沒有工作,因此將網絡卡作為第一個移植的實踐。這篇文章用於記錄移植dm9621網絡卡過程中遇到的問題以及如何定位問題並嘗試解決。 配置核心 在找到dm9621網絡卡驅動的原始碼後,需要將其新增