您的位置:首页 > 理论基础 > 计算机网络

ioctl()函数的用法、例子

2012-09-20 20:37 274 查看
来自百度百科,得说百度百科的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
4000
的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”啦~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息