1. 程式人生 > >ioctl()函式的用法、例子

ioctl()函式的用法、例子

來自百度百科,得說百度百科的c函式還是很全的...

表頭檔案:

#include<sys/ioctl.h>

功 能:

控制I/O裝置 ,提供了一種獲得裝置資訊和向裝置傳送控制引數的手段。用於向裝置發控制和配置命令 ,有些命令需要控制引數,這些資料是不能用read / write 讀寫的,稱為Out-of-band資料。也就是說,read / write 讀寫的資料是in-band資料,是I/O操作的主體,而ioctl 命令傳送的是控制資訊,其中的資料是輔助的資料。

用 法:

int ioctl(int handle, int cmd,[int *argdx, int argcx]);

返回值:

成功為0,出錯為-1
  

usr/include/asm-generic/ioctl.h中定義的巨集的註釋:

  #define _IOC_NRBITS 8                                                        //序數(number)欄位的字位寬度,8bits
  #define _IOC_TYPEBITS 8                                                    //幻數(type)欄位的字位寬度,8bits
  #define _IOC_SIZEBITS 14                                                   //大小(size)欄位的字位寬度,14bits
  #define _IOC_DIRBITS 2                                                                 //方向(direction)欄位的字位寬度,2bits
  #define _IOC_NRMASK ((1 << _IOC_NRBITS)-1)                       //序數字段的掩碼,0x000000FF
  #define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1)              //幻數字段的掩碼,0x000000FF
  #define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1)                 //大小欄位的掩碼,0x00003FFF
  #define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1)                     //方向欄位的掩碼,0x00000003
  #define _IOC_NRSHIFT 0                                                                             //序數字段在整個欄位中的位移,0
  #define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS)                 //幻數字段的位移,8
  #define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS)          //大小欄位的位移,16
  #define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS)               //方向欄位的位移,30
  

        /* Direction bits.*/
  #define _IOC_NONE 0U                                              //沒有資料傳輸
  #define _IOC_WRITE 1U                       //向裝置寫入資料,驅動程式必須從使用者空間讀入資料
  #define _IOC_READ 2U                        //從裝置中讀取資料,驅動程式必須向用戶空間寫入資料
  #define _IOC(dir,type,nr,size) \
  (((dir) << _IOC_DIRSHIFT) | \
  ((type) << _IOC_TYPESHIFT) | \
  ((nr) << _IOC_NRSHIFT) | \
  ((size) << _IOC_SIZESHIFT))

  /*used to create numbers*/
  //構造無引數的命令編號
  #define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
  //構造從驅動程式中讀取資料的命令編號
  #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
  //用於向驅動程式寫入資料命令
  #define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
  //用於雙向傳輸
  #define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
  

        /*used to decode ioctl numbers..*/
  //從命令引數中解析出資料方向,即寫進還是讀出
  #define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
  //從命令引數中解析出幻數type
  #define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
  //從命令引數中解析出序數number
  #define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
  //從命令引數中解析出使用者資料大小
  #define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)

  /* ...and for the drivers/sound files... */
  #define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT)
  #define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT)
  #define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
  #define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT)
  #define IOCSIZE_SHIFT (_IOC_SIZESHIFT)
  

程式例:
  #include <stdlib.h>
  #include <stdio.h>
  #include <sys/ioctl.h>
  int main(void) {
    int stat;
  /* use func 8 to determine if the default drive is removable */
    stat = ioctl(0, 8, 0, 0);
    if (!stat)
      printf("Drive %c is removable.\n", getdisk() + 'A');
    else
      printf("Drive %c is not removable.\n", getdisk() + 'A');
    return 0;
  }

int ioctl( int fd, int request, [ void *arg ] ) 第三個指標引數的詳解:
  第三個引數總是一個無符號型別的指標(代表它可以是任何型別的指標),但指標的型別依賴於request 引數。我們可以把和網路相關的請求劃分為6 類:
  1.套介面操作
  2.檔案操作
  3.介面操作
  4.ARP 快取記憶體操作
  5.路由表操作
  6.流系統

下表列出了網路相關ioctl請求的request 引數以及arg 地址必須指向的資料型別:

套介面操作:  

明確用於套介面操作的ioctl請求有三個, 它們都要求ioctl的第三個引數是指向某個整數的一個指標。  

SIOCATMARK: 如果本套介面的的度指標當前位於帶外標記,那就通過由第三個引數指向的整數返回一個非0 值;否則返回一個0 值。POSIX 以函式sockatmark 替換本請求。  

SIOCGPGRP : 通過第三個引數指向的整數返回本套介面的程序ID 或程序組ID ,該ID 指定針對本套介面的SIGIO 或SIGURG 訊號的接收程序。本請求和fcntl 的F_GETOWN 命令等效,POSIX 標準化的是fcntl 函式。  

SIOCSPGRP : 把本套介面的程序ID 或者程序組ID 設定成第三個引數指向的整數,該ID 指定針對本套介面的SIGIO 或SIGURG 訊號的接收程序,本請求和fcntl 的F_SETOWN 命令等效,POSIX 標準化的是fcntl 操作。

檔案操作:  

以下5 個請求都要求ioctl的第三個引數指向一個整數。  

FIONBIO : 根據ioctl的第三個引數指向一個0 或非0 值分別清除或設定本套介面的非阻塞標誌。本請求和O_NONBLOCK 檔案狀態標誌等效,而該標誌通過fcntl 的F_SETFL 命令清除或設定。  

FIOASYNC : 根據iocl 的第三個引數指向一個0 值或非0 值分別清除或設定針對本套介面的訊號驅動非同步I/O 標誌,它決定是否收取針對本套介面的非同步I/O 訊號(SIGIO )。本請求和O_ASYNC 檔案狀態標誌等效,而該標誌可以通過fcntl 的F_SETFL 命令清除或設定。  

FIONREAD : 通過由ioctl的第三個引數指向的整數返回當前在本套介面接收緩衝區中的位元組數。本特性同樣適用於檔案,管道和終端。  

FIOSETOWN : 對於套介面和SIOCSPGRP 等效。  

FIOGETOWN : 對於套介面和SIOCGPGRP 等效。

可見ioctl是一個應用十分廣泛的函式,如果想要進一步瞭解它,最好的方式當然還是“man”啦~