ioctl 订阅
在计算机中,ioctl(input/output control)是一个专用于设备输入输出操作的系统调用,该调用传入一个跟设备有关的请求码,系统调用的功能完全取决于请求码。举个例子,CD-ROM驱动程序可以弹出光驱,它就提供了一个对应的Ioctl请求码。设备无关的请求码则提供了内核调用权限。ioctl这名字第一次出现在Unix第七版中,他在很多类unix系统(比如Linux、Mac OSX等)都有提供,不过不同系统的请求码对应的设备有所不同。Microsoft Windows在Win32 API里提供了相似的函数,叫做DeviceIoControl。 展开全文
在计算机中,ioctl(input/output control)是一个专用于设备输入输出操作的系统调用,该调用传入一个跟设备有关的请求码,系统调用的功能完全取决于请求码。举个例子,CD-ROM驱动程序可以弹出光驱,它就提供了一个对应的Ioctl请求码。设备无关的请求码则提供了内核调用权限。ioctl这名字第一次出现在Unix第七版中,他在很多类unix系统(比如Linux、Mac OSX等)都有提供,不过不同系统的请求码对应的设备有所不同。Microsoft Windows在Win32 API里提供了相似的函数,叫做DeviceIoControl。
信息
属    性
控制I/O设备
特    点
特性进行控制
中文名
ioctl
功    能
进行管理的函数
ioctl介绍
ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。它的调用个数如下:其中fd是用户程序打开设备时使用open函数返回的文件标示符,cmd是用户程序对设备的控制命令,至于后面的省略号,那是一些补充参数,一般最多一个,这个参数的有无和cmd的意义相关。  ioctl函数是文件结构中的一个属性分量,就是说如果你的驱动程序提供了对ioctl的支持,用户就可以在用户程序中使用ioctl函数来控制设备的I/O通道。
收起全文
精华内容
下载资源
问答
  • ioctl用法详解
    2020-12-10 23:49:00

    与网络接口有关的ioctl调用使用的command参数通常看起来像

    SIOCxIFyyyy的形式,这里x要

    么是S(设定set,写write),要么是G(得到get,读read)。在getifinfo.c程序中就使用了这种形式的command参数来读

    IP地址,硬件地址,广播地址和得到与网络接口有关的一些标志(flag)。在这些ioctl调用中,第三个参数是ifreq结构,它在/usr

    /include/linux/if.h中定义。在某些情况下,

    ioctrl调用可能会使用到在sockios.h之外的新的定义,例如,WaveLAN无线网络卡会保存有关无线网络信号强度的信息,这对用户的程序可

    能有用。但用户怎么得到这种信息呢?我们的第一个本能是在sockios.h中定义新的ioctl命令,例如SIOCGIFWVLNSS(它的英文缩写表

    示WaveLAN的信号强度)。但不幸的是,这种命令不是对所有其他的网络接口(例如:loopback环回接口)有意义,而且不应当允许对于

    WAVLAN卡以外的网络接口使用ioctl命令。那么,我们需要的是这样一种机制:它能够定义一种与网络接口相关的ioctl命令。幸运的是,在

    Linux操作系统中已经为实现这个目的内建了一种挂钩(hook)机制。当你再次看sockios.h文件时,你将发现每一种设备已经预先定义了

    SIOCDEVPRIVATE的ioctl命令。而它的实现将留给开发相应驱动程序的人去完成。

    通常,一个用户程序使用ioctl

    (sockid,SIOCDEVPRIVATE,(char*)&ifr)来调用与某种设备(指像WaveLAN那样的特殊设备)相关的

    ioctl命令,这里ifr是struct ifreq

    ifr形式的变量。用户程序应当在ifr.ifr_name中填充与这个设备相关的名字,例如,假设WaveLAN使用的接口号为eth1。一般的,一个

    用户程序还需要与内核互相交换ioctl的command参数和结果,这可以通过ifr.ifr_data这个变量来实现,例如,想得到WaveLAN中

    表示信号强度的信息时,可以通过返回这个变量来实现。Linux的源代码已经包括了两种设备de4x5和ewrk3,它们定义并且实现了特定的ioctl

    调用。这两个设备的源代码在de4x5.h,de4x5.c,ewrk3.h,ewrk3.c中(在

    /usr/src/linux/drivers/net/目录中)。这两种设备都定义了它们特有的结构(struct ewrk3_ioctl 和

    struct

    de4x5_ioctl)来方便用户程序和设备驱动之间交换信息。每次调用ioctl前,用户程序应当在相应的结构变量中设定合适的初值,并且将

    ifr.ifr_data指向该值。

    在我们进一步讨论ewrk3和de4x5的代码前,让我们仔细看看ioctl调用是如何一步步地实现的。所有

    的和接口相关的ioctl请求 (SIOCxIFyyyy 和

    SIOCDEVPRIVATE)将会调用dev_ioctl()(在/usr/src/linux/net/core/dev.c中)。但这只是一个包装

    器(wrapper),实际的动作将由dev_ifsioc()(也在dev.c中)来实现。差不多dev_ioctl()这个函数所做的所有工作只是检

    查这个调用是否已经有了正当的权限(例如,改变路由表需要有root的权限)。而dev_ifsioc()这个函数首先要做的一些事情包括得到与

    ifr.ifr_name相匹配的设备的结构(在/usr/include/linux/netdevice.h中定义)。但这是在实现特定的接口命令

    (例如:SIOCGIFADDR)之后。这些特定的接口命令被放置到一个巨大的switch语句之中。其中SIOCDEVPRIVATE命令和其他的在

    0x89F0到0x89FF之间的代码将出现在switch语句中的一个分支——default语句中。内核会检查表示设备的结构变量中,是否已经定义了

    一个与设备相关的ioctl句柄(handler)。这里的句柄是一个函数指针,它在表示设备的结构变量中do_ioctl部分。如果已经设置了这个句

    柄,那么内核将会执行它。

    所以,如果要实现一个与设备相关的ioctl命令,所要做的只是编写一个与这个设备相关的ioctl句柄,并且将表示

    个设备的结构变量中do_ioctl部分指向这个句柄。对于ewrk3这个设备,它的句柄是ewrk3_ioctl()(在ewrk3.c里面)并且相应

    的表示该设备的结构变量由ewrk3_init()来初始化。在ewrk3_ioctl()的代码中清晰的指出ifr.ifr_data是用作设备驱动程

    序和用户程序之间交换信息的。注意,这部分的内存可以双向的交流信息。例如,在ewrk3的驱动程序代码中,if.ifr_data的头两个字节是用来表

    示特殊的动作(例如,EWRK3_SET_PROM,EWRK3_CLR_PROM),而这个动作是符合使用者(驱动程序实现了多个与设备相关的、由

    SIOCDEVPRIVATE调用的命令)的要求的。另外,ifr.ifr_data中第5个字节指向的缓冲区(buffer)被用来交换其他的信息

    (如:当使用EWRK3_SET_HWADDR和EWRK3_GET_HWADDR时为硬件地址)

    在你深入ewrk3_ioctl()时,请注意

    一般情况下一个用户进程不能直接访问内核所在的内存。为此,驱动开发者可以使用两个特殊的函数

    memcpy_tofs()和memcpy_fromfs()。内核函数memcpy_tofs(arg1, arg2, arg3)

    从地址arg2(用户空间)向地址arg1(内核空间)拷贝arg3个字节。类似的,memcpy_fromfs(arg1,arg2,arg3)从地址

    arg2(用户空间)向地址arg1(内核空间)拷贝arg3个字节。在这些调用之前,verify_area()将会检查这个进程是否拥有合适的访问权

    限。另外,注意使用printk()函数可以输出debug信息。这个函数与printf()函数类似,但不能处理浮点类型的数。内核代码不能够使用

    printf()函数。printk()函数产生的结果将记录在/usr/adm/messages里。如果想知道更多的关于这些函数的或者与它们相关的

    信息,可以参考《Linux Kernel Hacker’s Guide》(在Linux文档网站的首页) 这本书中Supporting

    Functions部分。

    使用ioctl与内核交换数据

    1. 前言

    使用ioctl系统调用是用户空间向内核交换数据的常用方法之一,从ioctl这个名称上看,本意是针对I/O设备进

    行的控制操作,但实际并不限制是真正的I/O设备,可以是任何一个内核设备即可。

    2. 基本过程

    在内核空间中ioctl是很多内核操作结构的一个成员函数,如文件操作结构struct

    file_operations(include/linux/fs.h)、协议操作结构struct

    proto_ops(include/linux/net.h)等、tty操作结构struct

    tty_driver(include/linux/tty_driver.h)等,而这些操作结构分别对应各种内核设备,只要在用户空间打开这些设备,

    如I/O设备可用open(2)打开,网络协议可用socket(2)打开等,获取一个文件描述符后,就可以在这个描述符上调用ioctl(2)来向内核

    交换数据。

    3. ioctl(2)

    ioctl(2)函数的基本使用格式为:

    int ioctl(int

    fd, int cmd, void *data)

    第一个参数是文件描述符;cmd是操作命令,一般分为GET、SET以及其他类型命令,GET

    是用户空间进程从内核读数据,SET是用户空间进程向内核写数据,cmd虽然是一个整数,但是有一定的参数格式的,下面再详细说明;第三个参数是数据起始

    位置指针,

    cmd命令参数是个32位整数,分为四部分:

    dir(2b) size(14b) type(8b) nr(8b)

    细定义cmd要包括这4个部分时可使用宏_IOC(dir,type,nr,size)来定义,而最简单情况下使用_IO(type,

    nr)来定义就可以了,这些宏都在include/asm/ioctl.h中定义

    本文cmd定义为:

    #define

    NEWCHAR_IOC_MAGIC   'M'

    #define NEWCHAR_SET    _IO(NEWCHAR_IOC_MAGIC,

    0)

    #define NEWCHAR_GET    _IO(NEWCHAR_IOC_MAGIC, 1)

    #define

    NEWCHAR_IOC_MAXNR   1

    要定义自己的ioctl操作,可以有两个方式,一种是在现有的内核代码中直接添加相关代码进行支持,比如想通过socket描述符进行

    ioctl操作,可在net/ipv4/af_inet.c中的inet_ioctl()函数中添加自己定义的命令和相关的处理函数,重新编译内核即可,

    不过这种方法一般不推荐;第二种方法是定义自己的内核设备,通过设备的ioctl()来操作,可以编成模块,这样不影响原有的内核,这是最通常的做法。

    4.

    内核设备

    为进行ioctl操作最通常是使用字符设备来进行,当然定义其他类型的设备也可以。在用户空间,可使用mknod命令建立一个

    字符类型设备文件,假设该设备的主设备号为123,次设备号为0:

    mknode /dev/newchar c 123 0

    如果是编程的

    话,可以用mknode(2)函数来建立设备文件。

    建立设备文件后再将该设备的内核模块文件插入内核,就可以使用open(2)打开

    /dev/newchar文件,然后调用ioctl(2)来传递数据,最后用close(2)关闭设备。而如果内核中还没有插入该设备的模

    块,open(2)时就会失败。

    由于内核内存空间和用户内存空间不同,要将内核数据拷贝到用户空间,要使用专用拷贝函数

    copy_to_user();要将用户空间数据拷贝到内核,要使用copy_from_user()。

    要最简单实现以上功能,内核模块只需要实

    现设备的open, ioctl和release三个函数即可,

    下面介绍程序片断:

    static int

    newchar_ioctl(struct inode *inode, struct file *filep,

    unsigned

    int cmd, unsigned long arg);

    static int newchar_open(struct inode

    *inode, struct file *filep);

    static int newchar_release(struct inode

    *inode, struct file *filep);

    // 定义文件操作结构,结构中其他元素为空

    struct

    file_operations newchar_fops =

    {

    owner: THIS_MODULE,

    ioctl:

    newchar_ioctl,

    open: newchar_open,

    release: newchar_release,

    };

    //

    定义要传输的数据块结构

    struct newchar{

    int a;

    int b;

    };

    #define

    MAJOR_DEV_NUM 123

    #define DEVICE_NAME "newchar"

    打开设备,非常简单,就是增加

    模块计数器,防止在打开设备的情况下删除模块,

    当然想搞得复杂的话可进行各种限制检查,如只允许指定的用户打开等:

    static int

    newchar_open(struct inode *inode, struct file *filep)

    {

    MOD_INC_USE_COUNT;

    return

    0;

    }

    关闭设备,也很简单,减模块计数器:

    static int newchar_release(struct inode *inode,

    struct file *filep)

    {

    MOD_DEC_USE_COUNT;

    return 0;

    }

    进行ioctl调用的基本处理函数

    static int newchar_ioctl(struct inode *inode,

    struct file *filep,

    unsigned int cmd, unsigned long arg)

    {

    int

    ret;

    // 首先检查cmd是否合法

    if (_IOC_TYPE(cmd) != NEWCHAR_IOC_MAGIC)

    return -EINVAL;

    if (_IOC_NR(cmd) > NEWCHAR_IOC_MAXNR) return

    -EINVAL;

    // 错误情况下的缺省返回值

    ret = EINVAL;

    switch(cmd)

    {

    case

    KNEWCHAR_SET:

    // 设置操作,将数据从用户空间拷贝到内核空间

    {

    struct newchar nc;

    if(copy_from_user(&nc, (const char*)arg, sizeof(nc)) != 0)

    return -EFAULT;

    ret = do_set_newchar(&nc);

    }

    break;

    case

    KNEWCHAR_GET:

    // GET操作通常会在数据缓冲区中先传递部分初始值作为数据查找条件,获取全部

    //

    数据后重新写回缓冲区

    // 当然也可以根据具体情况什么也不传入直接向内核获取数据

    {

    struct newchar

    nc;

    if(copy_from_user(&nc, (const char*)arg, sizeof(nc)) != 0)

    return -EFAULT;

    ret = do_get_newchar(&nc);

    if(ret ==

    0){

    if(copy_to_user((unsigned char *)arg, &nc,

    sizeof(nc))!=0)

    return -EFAULT;

    }

    }

    break;

    }

    return

    ret;

    }

    模块初始化函数,登记字符设备

    static int __init _init(void)

    {

    int

    result;

    // 登记该字符设备,这是2.4以前的基本方法,到2.6后有了些变化,

    //

    是使用MKDEV和cdev_init()来进行,本文还是按老方法

    result =

    register_chrdev(MAJOR_DEV_NUM, DEVICE_NAME, &newchar_fops);

    if

    (result < 0) {

    printk(KERN_WARNING __FUNCTION__ ": failed register

    character device for /dev/newchar\n");

    return result;

    }

    return

    0;

    }

    模块退出函数,登出字符设备

    static void __exit _cleanup(void)

    {

    int

    result;

    result = unregister_chrdev(MAJOR_DEV_NUM, DEVICE_NAME);

    if

    (result < 0)

    printk(__FUNCTION__ ": failed unregister character

    device for /dev/newchar\n");

    return;

    }

    module_init(_init);

    module_exit(_cleanup);

    5.

    结论

    用ioctl()在用户空间和内核空间传递数据是最常用方法之一,比较简单方便,而且可以在同一个ioctl中对不同的命令传送不

    同的数据结构,本文只是为描述方便而在不同命令中使用了相同的数据结构。

    更多相关内容
  • IOCTL驱动程序 关于如何为Linux创建IOCTL驱动程序的简单示例。 这可以用于简单的测试目的: 从内核模式访问特殊寄存器以在用户模式下获得结果。 例如,CP15处理器的Arm寄存器。 访问某些内存映射区域 ... 此仓库...
  • IMX8 mini mipi 摄像头报错: VIDIOC_QUERYCTRL: Inappropriate ioctl for device) 需要在内核的驱动代码中去实现相关函数。
  • ioctl_example.zip

    2021-05-04 17:35:17
    Linux 设备驱动i octl 例程,以LED设备驱动为例进行程序设计。
  • linux3.16 驱动 unlocked_ioctl实现
  • imx6ull gpio driver 使用gpiolib库 ioctl 控制处理io输入输出操作 。。。
  • linux ioctlioctl command

    2021-02-17 12:34:23
    在linux驱动中经常用到的函数为open、read、write用于对设备进行读取和写入数据,但是除了上述功能之外还有另外一个重要的功能ioctl,很多时候用户程序需要根据自己的需求配置所操纵的硬件,比如修改波特兰,获取...

    在linux驱动中经常用到的函数为open、read、write用于对设备进行读取和写入数据,但是除了上述功能之外还有另外一个重要的功能ioctl,很多时候用户程序需要根据自己的需求配置所操纵的硬件,比如修改波特兰,获取设备信息等,可以通过ioctl方法来进行与该设备的驱动进行交互,ioctl是在用户层可以之间与内核驱动打交道最直接的方式,但是其自身也有一些缺点。

    ioctl整个可以分为用户和内核两个部分。

    系统调用ioctl

    用户层主要是通过使用ioctl系统调用函数来直接控制设备相关配置,可以使用man 查看其函数原型:

    int ioctl(int fd, unsigned long request,...)

    对该函数解释如下:

    The ioctl() system call manipulates the underlying device parameters of special files. In particular, many operating char acteristics of character special files(e.g., terminals) may be controlled with ioctl() requests.

    函数参数:

    int fd:打开的文件描述符...

    unsigned long request: 在旧的版本中称之为ioctl command,之后进行了修改称置为 a device-dependent request code,主要为ioctl的命令字段,拥有固定的格式,包含系统预定义命令以及每个驱动设备特有的自定义命令字段

     ...:表示为一个可选参数,并不是数目不一定的一串参数,习惯上使用char *argp来定义,而在这里只是为了在编译时防止编译器进行类型检查。其参数的具体形式依赖于要完成的控制命令,也就是第二个参数某些控制命令不需要参数,某些需要一个整数参数,而一些则需要一个指针参数。使用指针可以向ioctl调用传递任意数据,这样设备可以与用户空间交换任意的数据。

    内核unlocked_ioctl

    在前面《linux 内核inode VS file提到struct file 是一种进程资源,在每个进程中每打开一个文件将会创建一个file结构,通过文件描述符将file结构在进行资源task中进行管理所有当前进程打开的文件,而针对驱动文件而言,当使用ioctl操作该设备时,实际上是调用的struct file_operations结构中的unlocked_ioctl,每个驱动设备严格意义上需要实现自己特有的ioctl命令相对应的实现,该回调函数定义如下:

    long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long)

    实际上系统调用ioctl最终就是调用的struct file_operations中的unlocked_ioctl回调函数。

    ioctl command命令字段

    在编写ioctl代码之前,需要选择对应不同命令的编号。多数程序源的第一本能是从0或者1开始选择一组小的编号。然而,有许多理由要求不能这样选择命令编号。为了防止对错误的设备使用正确的命令,命令号应该在系统范围内唯一,这种错误匹配并不是不会发生,程序可能发现自己正在试图对FIFO和audio等这类非串行设备输入流改波特率。如果每一个ioctl 命令都是唯一的,应用程序进行这种操作时就会得到一个EINVAL错误,而不是无意间成功地完成了意想不到的caoz。

    kernel经过多个版本的演进,ioctl command为一个32位无符号整型,将其划分位4个字段,其划分方式如下:

    •  nr: number序列号,用于表示该命令字段内的序列号
    • type: 类型也有称幻数,同一个ioctl内的所有命令字段的type 都相同。
    • size: 所涉及到用户数据大小,即系统调用ioctl传递的数据大小
    • direction: 数据的传递方向。

     nr(number)

    为一个8bit大小的位宽,一般是由驱动开发人员自己定义

    type

    8bit 大小,该数据为全局唯一

    size

    用户数据的大小,这个字段的宽度与体系结构有关,通常是13位或者14位。内核并不会检查这个位字段,对该字段的正确使用可以帮助我们检测用户空间的错误,并且如果我们从不改变相关数据项大小,这个字段还可以帮助我们实现向后兼容

    direction

    数据传输方向,为了操作方便,内核在include\uapi\asm-generic\ioctl.h定义了几个特殊的宏:

    #ifndef _IOC_NONE
    # define _IOC_NONE	0U
    #endif
    
    #ifndef _IOC_WRITE
    # define _IOC_WRITE	1U
    #endif
    
    #ifndef _IOC_READ
    # define _IOC_READ	2U
    #endif
    

    数据传输是从应用程序的角度说明,比如_IOC_READ意味着是从设备中读取数据,所以驱动程序必须向用户空间写入数据。如果该命令即可读也可写则可以使用逻辑AND操作:_IOC_READ|_IOC_WRITE

    ioctl command常见宏

    内核在include\uapi\asm-generic\ioctl.h文件中定义了几个基本常见宏:

    #define _IOC_NRBITS	8
    #define _IOC_TYPEBITS	8
    
    
    #ifndef _IOC_SIZEBITS
    # define _IOC_SIZEBITS	14
    #endif
    
    #ifndef _IOC_DIRBITS
    # define _IOC_DIRBITS	2
    #endif
    
    #define _IOC_NRMASK	((1 << _IOC_NRBITS)-1)
    #define _IOC_TYPEMASK	((1 << _IOC_TYPEBITS)-1)
    #define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
    #define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)
    
    #define _IOC_NRSHIFT	0
    #define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
    #define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
    #define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)

    其中根据上述的几个宏定义了一个基本的ioctl命令宏_IOC

    #define _IOC(dir,type,nr,size) \
    	(((dir)  << _IOC_DIRSHIFT) | \
    	 ((type) << _IOC_TYPESHIFT) | \
    	 ((nr)   << _IOC_NRSHIFT) | \
    	 ((size) << _IOC_SIZESHIFT))

    dir为数据方向,type为命令类型,nr为命令序列号, size为数据大小,为了进一步操作方便,内核又在_IOC宏上定义了几个宏:

    #define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
    #define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
    #define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
    #define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
    #define _IOR_BAD(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
    #define _IOW_BAD(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
    #define _IOWR_BAD(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))

    _IO为既不是读也不是写命令类型

    _IOR为 read 命令类型

    _IOW为write命令类型

    上述几个宏内部又添加了size大小检查

    _IOXX_BAD类型宏没有size大小检查。

    ioctl command分配情况

    在内核\Documentation\userspace-api\ioctl\ioctl-number.rst文件中列出了其使用情况,以下是在linux-5.10.11版本中ioctl commnand已分配情况:

    Code(Type)Seq#(hex)IncludeFile
    0x0000-1Flinux/fs.hconflict!
    0x0000-1Fscsi/scsi_ioctl.hconflict!
    0x0000-1Flinux/fb.hconflict!
    0x0000-1Flinux/wavefront.hconflict!
    0x02alllinux/fd.h 
    0x03alllinux/hdreg.h 
    0x04D2-DClinux/umsdos_fs.hDead
    0x06alllinux/lp.h 
    0x09alllinux/raid/md_u.h 
    0x1000-0Fdrivers/char/s390/vmcp.h 
    0x1010-1Farch/s390/include/uapi/sclp_ctl.h 
    0x1020-2Farch/s390/include/uapi/asm/hypfs.h 
    0x12alllinux/fs.h
    linux/blkpg.h
     
    0x1ballInfiniBandSubsystem  <http://infiniband.sourceforge.net/>
    0x20alldrivers/cdrom/cm206.h 
    0x22allscsi/sg.h 
    '!'00-1Fuapi/linux/seccomp.h 
    '#'00-3F IEEE 1394 Subsystem      Block for the entire subsystem
    '$'00-0Flinux/perf_counter.h,linux/perf_event.h
    '%'00-0Finclude/uapi/linux/stm.hSystem <mailto:alexander.shishkin@linux.intel.com>
    '&'00-07drivers/firewire/nosy-user.h 
    '1'00-1Flinux/timepps.hPPS <ftp://ftp.de.kernel.org/pub/linux/daemons/ntp/PPS/>
    '2'01-04linux/i2o.h 
    '3'00-0Fdrivers/s390/char/raw3270.hconflict!
    '3'00-1Flinux/suspend_ioctls.h,
    kernel/power/user.c
    conflict!
    '8'allSNP8023advanced <mailto:mcr@solidum.com>
    ';'64-7Flinux/vfio.h 
    '@'00-0Flinux/radeonfb.hconflict!
    '@'00-0Fdrivers/video/aty/aty128fb.cconflict!
    'A'00-1Flinux/apm_bios.hconflict!
    'A'00-0Flinux/agpgart.h,
    drivers/char/agp/compat_ioctl.h
    conflict!
    'A'00-7Fsound/asound.hconflict!
    'B'00-1Flinux/cciss_ioctl.hconflict!
    'B'00-0Finclude/linux/pmu.hconflict!
    'B'C0-FFadvancedbbus
    'C'alllinux/soundcard.hconflict!
    'C'01-2Flinux/capi.hconflict!
    'C'F0-FFdrivers/net/wan/cosa.hconflict!
    'D'allarch/s390/include/asm/dasd.h 
    'D'40-5Fdrivers/scsi/dpt/dtpi_ioctl.h 
    'D'05drivers/scsi/pmcraid.h 
    'E'alllinux/input.hconflict!
    'E'00-0Fxen/evtchn.hconflict!
    'F'alllinux/fb.hconflict!
    'F'01-02drivers/scsi/pmcraid.hconflict!
    'F'20drivers/video/fsl-diu-fb.hconflict!
    'F'20drivers/video/intelfb/intelfb.hconflict!
    'F'20linux/ivtvfb.hconflict!
    'F'20linux/matroxfb.hconflict!
    'F'20drivers/video/aty/atyfb_base.cconflict!
    'F'00-0Fvideo/da8xx-fb.hconflict!
    'F'80-8Flinux/arcfb.hconflict!
    'F'DDvideo/sstfb.hconflict!
    'G'00-3Fdrivers/misc/sgi-gru/grulib.hconflict!
    'H'00-7Flinux/hiddev.hconflict!
    'H'00-0Flinux/hidraw.hconflict!
    'H'01linux/mei.hconflict!
    'H'02linux/mei.hconflict!
    'H'03linux/mei.hconflict!
    'H'00-0Fsound/asound.hconflict!
    'H'20-40sound/asound_fm.hconflict!
    'H'80-8Fsound/sfnt_info.hconflict!
    'H'10-8Fsound/emu10k1.hconflict!
    'H'10-1Fsound/sb16_csp.hconflict!
    'H'10-1Fsound/hda_hwdep.hconflict!
    'H'40-4Fsound/hdspm.hconflict!
    'H'40-4Fsound/hdsp.hconflict!
    'H'90sound/usb/usx2y/usb_stream.h 
    'H'00-0Fuapi/misc/habanalabs.hconflict!
    'H'A0uapi/linux/usb/cdc-wdm.h 
    'H'C0-F0net/bluetooth/hci.hconflict!
    'H'C0-DFnet/bluetooth/hidp/hidp.hconflict!
    'H'C0-DFnet/bluetooth/cmtp/cmtp.hconflict!
    'H'C0-DFnet/bluetooth/bnep/bnep.hconflict!
    'H'F1linux/hid-roccat.h<mailto:erazor_de@users.sourceforge.net>
    'H'F8-FAsound/firewire.h 
    'I'alllinux/isdn.hconflict!
    'I'00-0Fdrivers/isdn/divert/isdn_divert.hconflict!
    'I'40-4Flinux/mISDNif.hconflict!
    'J'00-1Fdrivers/scsi/gdth_ioctl.h 
    'K'alllinux/kd.h 
    'L'00-1Flinux/loop.hconflict!
    'L'10-1Fdrivers/scsi/mpt3sas/mpt3sas_ctl.hconflict!
    'L'20-2Flinux/lightnvm.h 
    'L'E0-FFlinux/ppdd.hencrypted <http://linux01.gwdg.de/~alatham/ppdd.html>
    'M'alllinux/soundcard.hconflict!
    'M'01-16mtd/mtd-abi.hconflict!
     anddrivers/mtd/mtdchar.c 
    'M'01-03drivers/scsi/megaraid/megaraid_sas.h 
    'M'00-0Fdrivers/video/fsl-diu-fb.hconflict!
    'N'00-1Fdrivers/usb/scanner.h 
    'N'40-7Fdrivers/block/nvme.c 
    'O'00-06mtd/ubi-user.hUBI
    'P'alllinux/soundcard.hconflict!
    'P'60-6Fsound/sscape_ioctl.hconflict!
    'P'00-0Fdrivers/usb/class/usblp.cconflict!
    'P'01-09drivers/misc/pci_endpoint_test.cconflict!
    'Q'alllinux/soundcard.h 
    'R'00-1Flinux/random.hconflict!
    'R'01linux/rfkill.hconflict!
    'R'C0-DFnet/bluetooth/rfcomm.h 
    'S'alllinux/cdrom.hconflict!
    'S'80-81scsi/scsi_ioctl.hconflict!
    'S'82-FFscsi/scsi.hconflict!
    'S'00-7Fsound/asequencer.hconflict!
    'T'alllinux/soundcard.hconflict!
    'T'00-AFsound/asound.hconflict!
    'T'allarch/x86/include/asm/ioctls.hconflict!
    'T'C0-DFlinux/if_tun.hconflict!
    'U'allsound/asound.hconflict!
    'U'00-CFlinux/uinput.hconflict!
    'U'00-EFlinux/usbdevice_fs.h 
    'U'C0-CFdrivers/bluetooth/hci_uart.h 
    'V'alllinux/vt.hconflict!
    'V'alllinux/videodev2.hconflict!
    'V'C0linux/ivtvfb.hconflict!
    'V'C0linux/ivtv.hconflict!
    'V'C0media/davinci/vpfe_capture.hconflict!
    'V'C0media/si4713.hconflict!
    'W'00-1Flinux/watchdog.hconflict!
    'W'00-1Flinux/wanrouter.hconflict!
    'W'00-3Fsound/asound.hconflict!
    'W'40-5Fdrivers/pci/switch/switchtec.c 
    'W'60-61linux/watch_queue.h 
    'X'allfs/xfs/xfs_fs.h,
    fs/xfs/linux-2.6/xfs_ioctl32.h,
    include/linux/falloc.h,
    linux/fs.h,
    conflict!
    'X'allfs/ocfs2/ocfs_fs.hconflict!
    'X'01linux/pktcdvd.hconflict!
    'Y'alllinux/cyclades.h 
    'Z'14-15drivers/message/fusion/mptctl.h 
    '['00-3Flinux/usb/tmc.hUSB <mailto:gregkh@linuxfoundation.org>
    'a'alllinux/atm*.h,
    linux/sonet.h
     <http://lrcwww.epfl.ch/>
    'a'00-0Fdrivers/crypto/qat/qat_common/adf_cfg_common.hconflict!
    'b'00-FF conflict! bit3 <mailto:natalia@nikhefk.nikhef.nl>
    'c'alllinux/cm4000_cs.hconflict!
    'c'00-7Flinux/comstats.hconflict!
    'c'00-7Flinux/coda.hconflict!
    'c'00-1Flinux/chio.hconflict!
    'c'80-9Farch/s390/include/asm/chsc.hconflict!
    'c'A0-AFarch/x86/include/asm/msr.hconflict!
    'd'00-FFlinux/char/drm/drm.hconflict!
    'd'02-40pcmcia/ds.hconflict!
    'd'F0-FFlinux/digi1.h 
    'e'alllinux/digi1.hconflict!
    'f'00-1Flinux/ext2_fs.hconflict!
    'f'00-1Flinux/ext3_fs.hconflict!
    'f'00-0Ffs/jfs/jfs_dinode.hconflict!
    'f'00-0Ffs/ext4/ext4.hconflict!
    'f'00-0Flinux/fs.hconflict!
    'f'00-0Ffs/ocfs2/ocfs2_fs.hconflict!
    'f'13-27linux/fscrypt.h 
    'f'81-8Flinux/fsverity.h 
    'g'00-0Flinux/usb/gadgetfs.h 
    'g'20-2Flinux/usb/g_printer.h 
    'h'00-7F conflict! Charon <mailto:zapman@interlan.net>
    'h'00-1Flinux/hpet.hconflict!
    'h'80-8Ffs/hfsplus/ioctl.c 
    'i'00-3Flinux/i2o-dev.hconflict!
    'i'0B-1Flinux/ipmi.hconflict!
    'i'80-8Flinux/i8k.h 
    'j'00-3Flinux/joystick.h 
    'k'00-0Flinux/spi/spidev.hconflict!
    'k'00-05video/kyro.hconflict!
    'k'10-17linux/hsi/hsi_char.hHSI
    'l'00-3Flinux/tcfs_fs.htransparent http://web.archive.org/web/%2A/http://mikonos.dia.unisa.it/tcfs
    'l'40-7Flinux/udf_fs_i.hin http://sourceforge.net/projects/linux-udf/
    'm'00-09linux/mmtimer.hconflict!
    'm'alllinux/mtio.hconflict!
    'm'alllinux/soundcard.hconflict!
    'm'alllinux/synclink.hconflict!
    'm'00-19drivers/message/fusion/mptctl.hconflict!
    'm'00drivers/scsi/megaraid/megaraid_ioctl.hconflict!
    'n'00-7Flinux/ncp_fs.hand
    'n'80-8Fuapi/linux/nilfs2_api.hNILFS2
    'n'E0-FFlinux/matroxfb.hmatroxfb
    'o'00-1Ffs/ocfs2/ocfs2_fs.hOCFS2
    'o'00-03mtd/ubi-user.hconflict!
    'o'40-41mtd/ubi-user.hUBI
    'o'01-A1`linux/dvb/*.h`DVB
    'p'00-0Flinux/phantom.hconflict!
    'p'00-1Flinux/rtc.hconflict!
    'p'40-7Flinux/nvram.h 
    'p'80-9Flinux/ppdev.huser-space <mailto:tim@cyberelk.net>
    'p'A1-A5linux/pps.hLinuxPPS <mailto:giometti@linux.it>
    'q'00-1Flinux/serio.h 
    'q'80-FFlinux/telephony.h
    linux/ixjuser.h
    Internet PhoneJACK, Internet LineJACK
    http://web.archive.org/web/%2A/http://www.quicknet.net
    'r'00-1Flinux/msdos_fs.hand
    's'alllinux/cdk.h 
    't'00-7Flinux/ppp-ioctl.h 
    't'80-8Flinux/isdn_ppp.h 
    't'90-91linux/toshiba.htoshiba
    'u'00-1Flinux/smb_fs.hgone
    'u'20-3Flinux/uvcvideo.hUSB
    'u'40-4flinux/udmabuf.huserspace
    'v'00-1Flinux/ext2_fs.hconflict!
    'v'00-1Flinux/fs.hconflict!
    'v'00-0Flinux/sonypi.hconflict!
    'v'00-0Fmedia/v4l2-subdev.hconflict!
    'v'20-27arch/powerpc/include/uapi/asm/vas-api.hVAS
    'v'C0-FFlinux/meye.hconflict!
    'w'allCERNSCI
    'y'00-1F packet based user level communications
     <mailto:zapman@interlan.net>
    'z'00-3F CAN bus card conflict!
     <mailto:hdstich@connectu.ulm.circular.de>
    'z'40-7F CAN bus card conflict!
    <mailto:oe@port.de>
    'z'10-4Fdrivers/s390/crypto/zcrypt_api.hconflict!
    '|'00-7Flinux/media.h 
    0x8000-1Flinux/fb.h 
    0x8900-06arch/x86/include/asm/sockios.h 
    0x890B-DFlinux/sockios.h 
    0x89E0-EFlinux/sockios.hSIOCPROTOPRIVATE
    0x89E0-EFlinux/dn.hPROTOPRIVATE
    0x89F0-FFlinux/sockios.hSIOCDEVPRIVATE
    0x8Balllinux/wireless.h 
    0x8C00-3F WiNRADiO driver
    <http://www.winradio.com.au/>
    0x9000drivers/cdrom/sbpcd.h 
    0x9200-0Fdrivers/usb/mon/mon_bin.c 
    0x9360-7Flinux/auto_fs.h 
    0x94allfs/btrfs/ioctl.hBtrfs
     andlinux/fs.hsome
    0x9700-7Ffs/ceph/ioctl.hCeph
    0x9900-0F 537-Addinboard driver
    <mailto:buk@buks.ipn.de>
    0xA0alllinux/sdp/sdp.hIndustrial Device Project
     <mailto:kenji@bitgate.com>
    0xA10linux/vtpm_proxy.hTPM
    0xA380-8F Port ACL  in development:
    <mailto:tlewis@mindspring.com>
    0xA390-9Flinux/dtlk.h 
    0xA400-1Fuapi/linux/tee.hGeneric
    0xAA00-3Flinux/uapi/linux/userfaultfd.h 
    0xAB00-1Flinux/nbd.h 
    0xAC00-1Flinux/raw.h 
    0xAD00  Netfilter device in development:
    <mailto:rusty@rustcorp.com.au>
    0xAE00-1Flinux/kvm.hKernel-based Virtual Machine
    <mailto:kvm@vger.kernel.org>
    0xAE40-FFlinux/kvm.hKernel-based Virtual Machine
    <mailto:kvm@vger.kernel.org>
    0xAE20-3Flinux/nitro_enclaves.hNitro
    0xAF00-1Flinux/fsl_hypervisor.hFreescale
    0xB0all  RATIO devices in development:
     <mailto:vgo@ratio.de>
    0xB100-1F  PPPoX
     <mailto:mostrows@styx.uwaterloo.ca>
    0xB300linux/mmc/ioctl.h 
    0xB400-0Flinux/gpio.h<mailto:linux-gpio@vger.kernel.org>
    0xB500-0Fuapi/linux/rpmsg.h<mailto:linux-remoteproc@vger.kernel.org>
    0xB6alllinux/fpga-dfl.h 
    0xB7alluapi/linux/remoteproc_cdev.h<mailto:linux-remoteproc@vger.kernel.org>
    0xC000-0Flinux/usb/iowarrior.h 
    0xCA00-0Fuapi/misc/cxl.h 
    0xCA10-2Fuapi/misc/ocxl.h 
    0xCA80-BFuapi/scsi/cxlflash_ioctl.h 
    0xCB00-1F CBM serial IEC bus in development:
    <mailto:michael.klein@puffin.lb.shuttle.de>
    0xCC00-0Fdrivers/misc/ibmvmc.hpseries
    0xCD01linux/reiserfs_fs.h 
    0xCF02fs/cifs/ioctl.c 
    0xDB00-0Fdrivers/char/mwave/mwavepub.h 
    0xDD00-3F ZFCP device driver see drivers/s390/scsi/
     <mailto:aherrman@de.ibm.com>
    0xE500-3Flinux/fuse.h 
    0xEC00-01drivers/platform/chrome/cros_ec_dev.hChromeOS
    0xF300-3Fdrivers/usb/misc/sisusbvga/sisusb.hsisfb (in development)
     <mailto:thomas@winischhofer.net>
    0xF6all  LTTng Linux Trace Toolkit Next Generation
     <mailto:mathieu.desnoyers@efficios.com>
    0xFDalllinux/dm-ioctl.h 
    0xFEalllinux/isst_if.h 
    展开全文
  • ioctl函数详解

    2021-05-13 01:27:20
    1.介绍Linux网络程序与内核交互的方法是通过ioctl来实现的,ioctl与网络协议栈进行交互,可得到网络接口的信息,网卡设备的映射属性和配置网络接口.并且还能够查看,修改,删除ARP高速缓存的信息,所以,我们有必要...

    1.介绍

    Linux网络程序与内核交互的方法是通过ioctl来实现的,ioctl与网络协议栈进行交互,可得到网络接口的信息,网卡设备的映射属性和配置网络接口.并且还能够查看,修改,删除ARP高速缓存的信息,所以,我们有必要了解一下ioctl函数的具体实现.

    2.相关结构体与相关函数

    #include

    int ioctl(int d,int request,....);

    参数:

    d-文件描述符,这里是对网络套接字操作,显然是套接字描述符

    request-请求码

    省略的部分对应不同的内存缓冲区,而具体的内存缓冲区是由请求码request来决定的,下面看一下具体都有哪些相关缓冲区。

    (1)网络接口请求结构ifreq

    struct ifreq{#define IFHWADDRLEN 6 //6个字节的硬件地址,即MACunion{char ifrn_name[IFNAMESIZ];//网络接口名称}ifr_ifrn;union{struct sockaddr ifru_addr;//本地IP地址struct sockaddr ifru_dstaddr;//目标IP地址struct sockaddr ifru_broadaddr;//广播IP地址struct sockaddr ifru_netmask;//本地子网掩码地址struct sockaddr ifru_hwaddr;//本地MAC地址short ifru_flags;//网络接口标记int ifru_ivalue;//不同的请求含义不同struct ifmap ifru_map;//网卡地址映射int ifru_mtu;//最大传输单元 char ifru_slave[IFNAMSIZ];//占位符char ifru_newname[IFNAMSIZE];//新名称void __user* ifru_data;//用户数据struct if_settings ifru_settings;//设备协议设置}ifr_ifru;}#define ifr_name ifr_ifrn.ifrn_name;//接口名称#define ifr_hwaddr ifr_ifru.ifru_hwaddr;//MAC#define ifr_addr ifr_ifru.ifru_addr;//本地IP#define ifr_dstaddr ifr_ifru.dstaddr;//目标IP#define ifr_broadaddr ifr_ifru.broadaddr;//广播IP#define ifr_netmask ifr_ifru.ifru_netmask;//子网掩码#define ifr_flags ifr_ifru.ifru_flags;//标志#define ifr_metric ifr_ifru.ifru_ivalue;//接口侧度#define ifr_mtu ifr_ifru.ifru_mtu;//最大传输单元#define ifr_map ifr_ifru.ifru_map;//设备地址映射#define ifr_slave ifr_ifru.ifru_slave;//副设备#define ifr_data ifr_ifru.ifru_data;//接口使用#define ifr_ifrindex ifr_ifru.ifru_ivalue;//网络接口序号#define ifr_bandwidth ifr_ifru.ifru_ivalue;//连接带宽#define ifr_qlen ifr_ifru.ifru_ivalue;//传输单元长度#define ifr_newname ifr_ifru.ifru_newname;//新名称 #define ifr_seeting ifr_ifru.ifru_settings;//设备协议设置

    如果想获得网络接口的相关信息,就传入ifreq结构体.

    (2)网卡设备属性ifmap

    struct ifmap{//网卡设备的映射属性unsigned long mem_start;//开始地址unsigned long mem_end;//结束地址unsigned short base_addr;//基地址unsigned char irq;//中断号unsigned char dma;//DMAunsigned char port;//端口}

    (3)网络配置接口ifconf

    struct ifconf{//网络配置结构体是一种缓冲区int ifc_len;//缓冲区ifr_buf的大小union{char__user *ifcu_buf;//绘冲区指针struct ifreq__user* ifcu_req;//指向ifreq指针}ifc_ifcu;};#define ifc_buf ifc_ifcu.ifcu_buf;//缓冲区地址#define ifc_req ifc_ifcu.ifcu_req;//ifc_req地址

    (4)ARP高速缓存操作arpreq

    /**ARP高速缓存操作,包含IP地址和硬件地址的映射表操作ARP高速缓存的命令字 SIOCDARP,SIOCGARP,SIOCSARP分别是删除ARP高速缓存的一条记录,获得ARP高速缓存的一条记录和修改ARP高速缓存的一条记录struct arpreq{struct sockaddr arp_pa;//协议地址struct sockaddr arp_ha;//硬件地址int arp_flags;//标记struct sockaddr arp_netmask;//协议地址的子网掩码char arp_dev[16];//查询网络接口的名称}

    3. 请求码request

    类别Request说明数据类型

    口SIOCATMARK

    SIOCSPGRP

    SIOCGPGRP是否位于带外标记

    设置套接口的进程ID或进程组ID

    获取套接口的进程ID或进程组IDint

    int

    int

    件FIONBIN

    FIOASYNC

    FIONREAD

    FIOSETOWN

    FIOGETOWN设置/清除非阻塞I/O标志

    设置/清除信号驱动异步I/O标志

    获取接收缓存区中的字节数

    设置文件的进程ID或进程组ID

    获取文件的进程ID或进程组IDint

    int

    int

    int

    int

    口SIOCGIFCONF

    SIOCSIFADDR

    SIOCGIFADDR

    SIOCSIFFLAGS

    SIOCGIFFLAGS

    SIOCSIFDSTADDR

    SIOCGIFDSTADDR

    SIOCGIFBRDADDR

    SIOCSIFBRDADDR

    SIOCGIFNETMASK

    SIOCSIFNETMASK

    SIOCGIFMETRIC

    SIOCSIFMETRIC

    SIOCGIFMTU

    SIOCxxx获取所有接口的清单

    设置接口地址

    获取接口地址

    设置接口标志

    获取接口标志

    设置点到点地址

    获取点到点地址

    获取广播地址

    设置广播地址

    获取子网掩码

    设置子网掩码

    获取接口的测度

    设置接口的测度

    获取接口MTU

    (还有很多取决于系统的实现)struct ifconf

    struct ifreq

    struct ifreq

    struct ifreq

    struct ifreq

    struct ifreq

    struct ifreq

    struct ifreq

    struct ifreq

    struct ifreq

    struct ifreq

    struct ifreq

    struct ifreq

    struct ifreq

    ARPSIOCSARP

    SIOCGARP

    SIOCDARP创建/修改ARP表项

    获取ARP表项

    删除ARP表项struct arpreq

    struct arpreq

    struct arpreq

    由SIOCADDRT

    SIOCDELRT增加路径

    删除路径struct rtentry

    struct rtentry

    流I_xxx

    4. 相关例子

    (1)网络接口信息选项获取填充struct ifreq的ifr_name

    #include #include #include #include #include #include #include #include #include /**ioctl函数是与内核交互的一种方法,使用ioctl函数与内核协议栈进行交互ioctl函数可操作I/O请求,文件请求与网络接口请求网络接口请求的几个结构体:struct ifreq{#define IFHWADDRLEN 6 //6个字节的硬件地址,即MACunion{char ifrn_name[IFNAMESIZ];//网络接口名称}ifr_ifrn;union{struct sockaddr ifru_addr;//本地IP地址struct sockaddr ifru_dstaddr;//目标IP地址struct sockaddr ifru_broadaddr;//广播IP地址struct sockaddr ifru_netmask;//本地子网掩码地址struct sockaddr ifru_hwaddr;//本地MAC地址short ifru_flags;//网络接口标记int ifru_ivalue;//不同的请求含义不同struct ifmap ifru_map;//网卡地址映射int ifru_mtu;//最大传输单元 char ifru_slave[IFNAMSIZ];//占位符char ifru_newname[IFNAMSIZE];//新名称void __user* ifru_data;//用户数据struct if_settings ifru_settings;//设备协议设置}ifr_ifru;}#define ifr_name ifr_ifrn.ifrn_name;//接口名称#define ifr_hwaddr ifr_ifru.ifru_hwaddr;//MAC#define ifr_addr ifr_ifru.ifru_addr;//本地IP#define ifr_dstaddr ifr_ifru.dstaddr;//目标IP#define ifr_broadaddr ifr_ifru.broadaddr;//广播IP#define ifr_netmask ifr_ifru.ifru_netmask;//子网掩码#define ifr_flags ifr_ifru.ifru_flags;//标志#define ifr_metric ifr_ifru.ifru_ivalue;//接口侧度#define ifr_mtu ifr_ifru.ifru_mtu;//最大传输单元#define ifr_map ifr_ifru.ifru_map;//设备地址映射#define ifr_slave ifr_ifru.ifru_slave;//副设备#define ifr_data ifr_ifru.ifru_data;//接口使用#define ifr_ifrindex ifr_ifru.ifru_ivalue;//网络接口序号#define ifr_bandwidth ifr_ifru.ifru_ivalue;//连接带宽#define ifr_qlen ifr_ifru.ifru_ivalue;//传输单元长度#define ifr_newname ifr_ifru.ifru_newname;//新名称 #define ifr_seeting ifr_ifru.ifru_settings;//设备协议设置struct ifmap{//网卡设备的映射属性unsigned long mem_start;//开始地址unsigned long mem_end;//结束地址unsigned short base_addr;//基地址unsigned char irq;//中断号unsigned char dma;//DMAunsigned char port;//端口}struct ifconf{//网络配置结构体是一种缓冲区int ifc_len;//缓冲区ifr_buf的大小union{char__user *ifcu_buf;//绘冲区指针struct ifreq__user* ifcu_req;//指向ifreq指针}ifc_ifcu;};#define ifc_buf ifc_ifcu.ifcu_buf;//缓冲区地址#define ifc_req ifc_ifcu.ifcu_req;//ifc_req地址(1)获得配置选项SIOCGIFCONF获得网络接口的配置情况 需要填充struct ifreq中ifr_name变量(2)其它选项获取填充struct ifreq的ifr_name**/int main(int argc,char*argv[]){int s;int err;s=socket(AF_INET,SOCK_DGRAM,0);if(s<0){perror("socket error");return;}//传入网络接口序号,获得网络接口的名称struct ifreq ifr;ifr.ifr_ifindex=2;//获得第2个网络接口的名称 err=ioctl(s,SIOCGIFNAME,&ifr);if(err){perror("index error");}else{printf("the %dst interface is:%s\n",ifr.ifr_ifindex,ifr.ifr_name);}//传入网络接口名称,获得标志memcpy(ifr.ifr_name,"eth0",5);err=ioctl(s,SIOCGIFFLAGS,&ifr);if(!err){printf("SIOCGIFFLAGS:%d\n",ifr.ifr_flags);}//获得MTU和MACerr=ioctl(s,SIOCGIFMTU,&ifr);if(!err){printf("SIOCGIFMTU:%d\n",ifr.ifr_mtu);}//获得MAC地址err=ioctl(s,SIOCGIFHWADDR,&ifr);if(!err){unsigned char* hw=ifr.ifr_hwaddr.sa_data;printf("SIOCGIFHWADDR:%02x:%02x:%02x:%02x:%02x:%02x\n",hw[0],hw[1],hw[2],hw[3],hw[4],hw[5]);}//获得网卡映射参数 命令字SIOCGIFMAPerr=ioctl(s,SIOCGIFMAP,&ifr);if(!err){printf("SIOCGIFMAP,mem_start:%d,mem_end:%d,base_addr:%d,ifr_map:%d,dma:%d,port:%d\n",ifr.ifr_map.mem_start,ifr.ifr_map.mem_end,ifr.ifr_map.base_addr,ifr.ifr_map.irq,ifr.ifr_map.dma,ifr.ifr_map.port);}//获得网卡序号err=ioctl(s,SIOCGIFINDEX,&ifr);if(!err){printf("SIOCGIFINDEX:%d\n",ifr.ifr_ifindex);}//获取发送队列的长度err=ioctl(s,SIOCGIFTXQLEN,&ifr);if(!err){printf("SIOCGIFTXQLEN:%d\n",ifr.ifr_qlen);}//获取网络接口IPstruct sockaddr_in *sin=(struct sockaddr_in*)&ifr.ifr_addr;//保存的是二进制IPchar ip[16];//字符数组,存放字符串memset(ip,0,16);err=ioctl(s,SIOCGIFADDR,&ifr);if(!err){inet_ntop(AF_INET,&sin->sin_addr.s_addr,ip,16);//转换的字符串保存到ip数组中,第二个参数是要转换的二进制IP指针,第三个参数是转换完成存放IP的缓冲区,最后一个参数是缓冲区的长度printf("SIOCGIFADDR:%s\n",ip);}//查询目标IP地址err=ioctl(s,SIOCGIFDSTADDR,&ifr);if(!err){inet_ntop(AF_INET,&sin->sin_addr.s_addr,ip,16);printf("SIOCGIFDSTADDR:%s\n",ip);}//查询子网掩码err=ioctl(s,SIOCGIFNETMASK,&ifr);if(!err){inet_ntop(AF_INET,&sin->sin_addr.s_addr,ip,16);printf("SIOCGIFNETMASK:%s\n",ip);}//设置IP地址,设置网络接口inet_pton(AF_INET,"222.27.253.108",&sin->sin_addr.s_addr);//将字符串IP转换成二进制err=ioctl(s,SIOCSIFADDR,&ifr);//发送设置本机ip地址请求命令if(!err){printf("check IP-----"); memset(&ifr,0,sizeof(ifr));memcpy(ifr.ifr_name,"eth0",5);ioctl(s,SIOCGIFADDR,&ifr);inet_ntop(AF_INET,&sin->sin_addr.s_addr,ip,16);printf("%s\n",ip);}//得到接口的广播地址memset(&ifr,0,sizeof(ifr));memcpy(ifr.ifr_name,"eth0",5);ioctl(s,SIOCGIFBRDADDR,&ifr);struct sockaddr_in *broadcast=(struct sockaddr_in*)&ifr.ifr_broadaddr;//转换成字符串inet_ntop(AF_INET,&broadcast->sin_addr.s_addr,ip,16);//inet_ntop将二进制IP转换成点分十进制的字符串printf("BROADCAST IP:%s\n",ip);close(s);}运行结果:

    [root@localhost ~]# ./ioctl-testthe 2st interface is:eth0SIOCGIFFLAGS:4163SIOCGIFMTU:1500SIOCGIFHWADDR:00:13:d4:36:98:34SIOCGIFMAP,mem_start:0,mem_end:0,base_addr:60416,ifr_map:201,dma:0,port:0SIOCGIFINDEX:2SIOCGIFTXQLEN:1000SIOCGIFADDR:222.27.253.108SIOCGIFDSTADDR:222.27.253.108SIOCGIFNETMASK:255.255.255.0check IP-----222.27.253.108BROADCAST IP:222.27.253.255

    (2)查看arp高速缓存信息

    #include #include #include #include #include #include #include #include #include /**ARP高速缓存操作,包含IP地址和硬件地址的映射表操作ARP高速缓存的命令字 SIOCDARP,SIOCGARP,SIOCSARP分别是删除ARP高速缓存的一条记录,获得ARP高速缓存的一条记录和修改ARP高速缓存的一条记录struct arpreq{struct sockaddr arp_pa;//协议地址struct sockaddr arp_ha;//硬件地址int arp_flags;//标记struct sockaddr arp_netmask;//协议地址的子网掩码char arp_dev[16];//查询网络接口的名称}**///根据IP地址查找硬件地址int main(int argc,char*argv[]){int s;int err;struct arpreq arpreq;struct sockaddr_in *addr=(struct sockaddr_in*)&arpreq.arp_pa;//IP地址s=socket(AF_INET,SOCK_DGRAM,0);if(s<0){perror("socket error");}addr->sin_family=AF_INET;addr->sin_addr.s_addr=inet_addr(argv[1]);//转换成二进制IPif(addr->sin_addr.s_addr==INADDR_NONE){printf("IP地址格式错误\n");}strcpy(arpreq.arp_dev,"eth0");err=ioctl(s,SIOCGARP,&arpreq);if(err==-1){perror("arp");return;}unsigned char* hw=(unsigned char*)&arpreq.arp_ha.sa_data;//硬件地址printf("%s\n",argv[1]);printf("%02x:%02x:%02x:%02x:%02x:%02x\n",hw[0],hw[1],hw[2],hw[3],hw[4],hw[5]);close(s);return 0;}

    运行结果:

    [root@localhost ~]# ./ioctl-arp 222.27.253.1222.27.253.100:0f:e2:5f:3c:8c查看网关的MAC.在查看ARP高速缓存时要传入IP地址与接口信息.而获得接口信息要传入接口名ifr_name,如eth0.

    总结:

    本文主要介绍了获得网络接口请求信息,获得网卡设备映射属性,配置网络接口,获得ARP高速缓存等.其它ioctl函数还能对操作文件,操作I/O,操作路由等。最后,对于网络接口的操作与ARP高速缓存的操作分别给出了实例

    展开全文
  • 该资源包括最基础的字符设备驱动程序,包括三个文档,其中两个文档包括驱动测试程序。实现了open(),release(),read(),write()和ioctl()等五个函数的在字符设备驱动程序中的应用
  • Linux编程之ioctl

    2021-01-12 08:17:30
    在和设备驱动程序通信时,ioctl是很常用的一个调用,常用来配置、查询或者修改设备的配置。反过来说,编写驱动程序时,ioctl也是经常要实现的一个接口,以便应用程序可以方便地控制设备驱动。 应用程序中的ioctl ...

    在和设备驱动程序通信时,ioctl是很常用的一个调用,常用来配置、查询或者修改设备的配置。反过来说,编写驱动程序时,ioctl也是经常要实现的一个接口,以便应用程序可以方便地控制设备驱动。

    应用程序中的ioctl

    ioctl函数的原型如下:

           #include <sys/ioctl.h>
    
           int ioctl(int fd, unsigned long request, ...);

    可以看出该函数是一个可变参数的函数。第一个参数是一个文件描述符,通常用open调用来打开。在Linux中,一切皆文件,哪怕你调用open打开一个设备,也得到一个文件描述符。这一切要归功于内核里的VFS(虚拟文件系统)。第二个参数request是控制代码,或者说是控制命令、请求代码都可以。根据第二个参数的不同,后面所带的参数个数和类型都可能不一样。

    内核中的ioctl

    当引用进程调用ioctl时,Linux内核中实现的系统调用被调用。系统调用是Linux的一种标准机制,在不同的CPU体系结构中的具体实现方式可能不一样。ioctl系统调用定义于内核源码的fs/ioctl.c中,其定义如下:

    SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
    {
    	struct fd f = fdget(fd);
    	int error;
    
    	if (!f.file)
    		return -EBADF;
    
    	error = security_file_ioctl(f.file, cmd, arg);
    	if (error)
    		goto out;
    
    	error = do_vfs_ioctl(f.file, fd, cmd, arg);
    	if (error == -ENOIOCTLCMD)
    		error = vfs_ioctl(f.file, cmd, arg);
    
    out:
    	fdput(f);
    	return error;
    }

    从ioctl系统调用的源码可以看出,它首先会调用do_vfs_ioctl,如果do_vfs_ioctl不支持这个控制命令,则调用vfs_ioctl

    do_vfs_ioctl函数的源码可点击链接直接查看,它主要处理一些文件系统通用的控制命令,如FIOASYNC等,详细控制命令列表可查看该函数源码。另外,该函数还会判断文件节点是不是常规文件,如果是则调用file_ioctl函数。后者也处理一些跟文件相关的控制命令。

    对于设备驱动的控制命令,一般do_vfs_ioctl并不会直接处理,而是调用vfs_ioctl,该函数代码如下:

    long vfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
    {
    	int error = -ENOTTY;
    
    	if (!filp->f_op->unlocked_ioctl)
    		goto out;
    
    	error = filp->f_op->unlocked_ioctl(filp, cmd, arg);
    	if (error == -ENOIOCTLCMD)
    		error = -ENOTTY;
     out:
    	return error;
    }
    EXPORT_SYMBOL(vfs_ioctl);

    可见,该函数最终会调用到filp>f_op->unlocked_ioctl函数。这里filp时一个文件对象,在open是创建。每个文件对象都又一个文件操作接口,即f_op。如果一个设备驱动程序支持虚拟文件系统VFS,那么它就会注册一个文件操作接口,即f_op,而这个接口中包含几个基本函数,如open、close、read、write、ioctl等。因此,通过这个调用,最终调用到了设备驱动程序的unlocked_ioctl函数。

    以/dev/urandom设备为例,它是一个字符型设备,其源码位于drivers/char/random.c。它的文件操作接口定义如下:

    const struct file_operations urandom_fops = {
    	.read  = urandom_read,
    	.write = random_write,
    	.unlocked_ioctl = random_ioctl,
    	.compat_ioctl = compat_ptr_ioctl,
    	.fasync = random_fasync,
    	.llseek = noop_llseek,
    };

    而该文件操作接口的注册则是在注册/dev/urandom设备是一起注册的。不过新内核的代码为了提高效率,把多个设备一起作为内存设备注册。具体代码位于drivers/char/mem.c

    具体到ioctl接口,其实现如下:

    static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
    {
    	int size, ent_count;
    	int __user *p = (int __user *)arg;
    	int retval;
    
    	switch (cmd) {
    	case RNDGETENTCNT:
    		/* inherently racy, no point locking */
    		ent_count = ENTROPY_BITS(&input_pool);
    		if (put_user(ent_count, p))
    			return -EFAULT;
    		return 0;
    	case RNDADDTOENTCNT:
    		if (!capable(CAP_SYS_ADMIN))
    			return -EPERM;
    		if (get_user(ent_count, p))
    			return -EFAULT;
    		return credit_entropy_bits_safe(&input_pool, ent_count);
    	case RNDADDENTROPY:
    		if (!capable(CAP_SYS_ADMIN))
    			return -EPERM;
    		if (get_user(ent_count, p++))
    			return -EFAULT;
    		if (ent_count < 0)
    			return -EINVAL;
    		if (get_user(size, p++))
    			return -EFAULT;
    		retval = write_pool(&input_pool, (const char __user *)p,
    				    size);
    		if (retval < 0)
    			return retval;
    		return credit_entropy_bits_safe(&input_pool, ent_count);
    	case RNDZAPENTCNT:
    	case RNDCLEARPOOL:
    		/*
    		 * Clear the entropy pool counters. We no longer clear
    		 * the entropy pool, as that's silly.
    		 */
    		if (!capable(CAP_SYS_ADMIN))
    			return -EPERM;
    		input_pool.entropy_count = 0;
    		return 0;
    	case RNDRESEEDCRNG:
    		if (!capable(CAP_SYS_ADMIN))
    			return -EPERM;
    		if (crng_init < 2)
    			return -ENODATA;
    		crng_reseed(&primary_crng, NULL);
    		crng_global_init_time = jiffies - 1;
    		return 0;
    	default:
    		return -EINVAL;
    	}
    }

    应用程序ioctl示例

    下面的例子通过ioctl获取/dev/urandom的熵池的大小,然后通过ioctl清除熵池。由于ioctl的命令代码是每个设备自定义的,因此针对每个设备的ioctl需要包含该设备的头文件。下面的例子中就是<linux/random.h>。需要注意的是清除熵池的操作需要管理员权限,因此运行时应该用sudo来运行。

    #include <sys/ioctl.h>
    #include <sys/stat.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <linux/random.h>
    
    int main(int argc, char *argv[])
    {
    	int ent_cnt;
    	int fd = open("/dev/urandom", O_RDONLY);
    	if (fd < 0) {
    		perror("open");
    	} else {
    		if (ioctl(fd, RNDGETENTCNT, &ent_cnt) < 0) {
    			perror("ioctl");
    		} else {
    			printf("entropy count (bits): %d\n", ent_cnt);
    		}
    		if (ioctl(fd, RNDCLEARPOOL) < 0) {
    			perror("ioctl");
    		}
    		if (ioctl(fd, RNDGETENTCNT, &ent_cnt) < 0) {
    			perror("ioctl");
    		} else {
    			printf("entropy count (bits) after clear: %d\n", ent_cnt);
    		}
    		close(fd);
    	}
    	return 0;
    }

    编译并运行该程序,可得到如下结果。

    gcc -o rnd_ioctl rnd_ioctl.c
    sudo ./test_ioctl
    entropy count (bits): 2249
    entropy count (bits) after clear: 0

    驱动程序ioctl示例

    下面这个例子演示如何在驱动程序中实现ioctl接口。

    创建一个目录dummy,然后在下面创建dummy_main.c,为驱动程序源代码。驱动程序的入口用module_init指定,在安装驱动程序时入口被调用;驱动程序的卸载函数则用module_exit指定,卸载驱动时调用。这个驱动程序要做的事情很简单,就是注册一个dummy设备/dev/dummy,并且支持一个ioctl命令DUMMY_COUNT。这个ioctl命令的作用就是获取对/dev/dummy设备进行ioctl命令的次数。因为任何应用程序都可以对这个设备做ioctl,因此用一个原子变量来累计。其详细代码如下所示。注意在这个驱动程序中,在注册文件操作接口时,并没有指定open以及release等操作函数,但这不代表该设备没有这两个操作函数。所有支持文件系统操作接口的设备都必须实现open函数。在这个例子中,/dev/dummy设备是miscdevice设备,而miscdevice设备又属于字符类设备,内核中对字符类设备都提供默认的open和release操作函数实现。如果你的驱动程序不覆盖这个实现,则采用默认实现。

    #include <linux/module.h>
    #include <linux/types.h>
    #include <linux/fs.h>
    #include <linux/uaccess.h>
    #include <linux/miscdevice.h>
    #include "dummy.h"
    
    MODULE_LICENSE("GPL");
    MODULE_DESCRIPTION("dummy driver");
    
    static atomic_t dummy_ioctl_cnt = ATOMIC_INIT(0);
    static long dummy_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
    {
    	int __user *p = (int __user *)arg;
    	switch (cmd) {
    		case DUMMY_COUNT:
    			atomic_inc(&dummy_ioctl_cnt);
    			if (put_user(atomic_read(&dummy_ioctl_cnt), p))
    				return -EFAULT;
    			break;
    		default:
    			return -EOPNOTSUPP;
    	}
    	return 0;
    }
    static const struct file_operations dummy_fops = {
    	.owner = THIS_MODULE,
    	.unlocked_ioctl = dummy_ioctl,
    	.compat_ioctl = compat_ptr_ioctl,
    };
    
    static struct miscdevice dummy_dev = {
    	.minor = MISC_DYNAMIC_MINOR,
    	.name = "dummy",
    	.nodename = "dummy",
    	.fops = &dummy_fops,
    	.mode = 0666,
    };
    static int __init dummy_register(void)
    {
    	int err;
    	err = misc_register(&dummy_dev);
    	if (err == 0) {
    		printk("dummy dev registered, minor %d\n", dummy_dev.minor);
    	}
    	return err;
    }
    static void __exit dummy_unregister(void)
    {
    	misc_deregister(&dummy_dev);
    }
    
    static int __init dummy_init(void)
    {
    	return dummy_register();
    }
    static void __exit dummy_exit(void)
    {
    	dummy_unregister();
    }
    
    module_init(dummy_init);
    module_exit(dummy_exit);

    再创建一个头文件dummy.h,在里面定义ioctl命令码,如下所示。

    #ifndef _UAPI_LINUX_DUMMY_H
    #define _UAPI_LINUX_DUMMY_H
    #include <linux/ioctl.h>
    
    #define DUMMY_COUNT	_IOR('R', 0x1, int)
    
    #endif

    编译驱动程序需要一个Makefile。编译驱动需要安装内核编译支持,并指定build目录;除此之外还需要指定当前驱动源码所在目录。由于dummy驱动不是built-in驱动,因此在Makefile中采用obj-m。如下所示。

    obj-m:=dummy.o
    dummy-objs:=dummy_main.o
    
    .PHONY: all clean
    all:
    	make -C /lib/modules/`uname -r`/build M=`pwd` modules
    
    clean:
    	@rm -rf *.o *.ko *.mod *.mod.c *.order *.symvers

    最后在dummy调用make命令即可编译。

    make
    make -C /lib/modules/`uname -r`/build M=`pwd` modules
    make[1]: Entering directory '/usr/src/linux-headers-5.4.0-60-generic'
      CC [M]  dummy_main.o
      LD [M]  dummy.o
      Building modules, stage 2.
      MODPOST 1 modules
      CC [M]  dummy.mod.o
      LD [M]  dummy.ko
    make[1]: Leaving directory '/usr/src/linux-headers-5.4.0-60-generic'

    编译完成会生成dummy.ko,可调用insmod安装。安装驱动需要管理员权限。安装完成后可查看/dev/dummy检查驱动程序是否正确加载。如下所示。

    sudo insmod ./dummy.ko
    ls -l /dev/dummy
    crw-rw-rw- 1 root root 10, 57 1月  12 08:12 /dev/dummy

    需要注意的是,这个例子中并没有对生成的dummy.ko做strip操作。在正式产品开发中,一般都需要在Makefile中定义一个安装步骤,在安装时做strip操作以减小驱动程序模块文件尺寸。

     

    下面再用一个简单的应用程序来验证驱动程序的ioctl操作。在同一个目录下创建dummy_ioctl.c,并编译运行。运行了应用程序两次,可以看到ioctl操作在驱动程序中被正确累加,并由ioctl正确返回。

    #include <sys/ioctl.h>
    #include <sys/stat.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include "dummy.h"
    
    int main(int argc, char *argv[])
    {
    	int i;
    	int dummy_cnt;
    	int fd = open("/dev/dummy", O_RDONLY);
    	if (fd < 0) {
    		perror("open");
    	} else {
    		for (i = 0; i < 3; i++) {
    			if (ioctl(fd, DUMMY_COUNT, &dummy_cnt) < 0) {
    				perror("ioctl");
    			} else {
    				printf("#%d: dummy_cnt: %d\n", i, dummy_cnt);
    			}
    		}
    		close(fd);
    	}
    	return 0;
    }
     gcc -o dummy_ioctl dummy_ioctl.c
    ./dummy_ioctl
    #0: dummy_cnt: 1
    #1: dummy_cnt: 2
    #2: dummy_cnt: 3
    ./dummy_ioctl
    #0: dummy_cnt: 4
    #1: dummy_cnt: 5
    #2: dummy_cnt: 6

     

     

     

    展开全文
  • linux下ioctl函数

    2013-11-30 16:14:05
    linux下ioctl函数,这里说的ioctl函数是在驱动程序里的
  • Linux内核驱动 --ioctl函数解析

    千次阅读 2021-06-18 21:03:06
    1、前言 当我们在讨论linux内核驱动开发时,就不得不提到ioctl这个及其重要的函数。它是设备驱动程序中实现对设备控制的接口之一。当我们在用户空间中使用ioctl函数时,
  • 我正在编写一个用作伪驱动程序的Linux内核模块(LKM) - 我无法弄清楚如何在LKM之间进行IOCTL调用(wait.c)和用户级程序(user.c)。Linux内核模块/ IOCTL:不适用于设备的ioctl设备驱动程序的神奇数字是​​- LKM不与...
  • 关于LINUX下的ioctl函数

    2021-05-10 05:50:24
    驱动程序中ioctl函数的函数原型如下:int (*ioctl)(struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg);其中cmd和arg参数是ioctl与其它驱动程序函数不同的地方。cmd是预先定义好的一些...
  • ioctl 解析

    2015-06-09 16:47:50
    介绍 ioctl 的含义,以及现在哪些被占用了
  • ioctl应用详解

    千次阅读 2020-09-06 23:56:53
    前言 参考以下资料: linux 内核 - ioctl 函数详解 ...1、ioctl 是设备驱动程序中设备控制接口函数,一个字符设备驱动通常会实现设备打开、关闭、读、写等功能,在一些需要细分的情境下,如果需要扩展新.
  • 1. 前言使用ioctl系统调用是用户空间向内核交换数据的常用方法之一,从ioctl这个名称上看,本意是针对I/O设备进行的控制操作,但实际并不限制是真正的I/O设备,可以是任何一个内核设备即可。2. 基本过程在内核空间中...
  • linux驱动 ioctl 小结

    2021-03-03 11:04:54
    sys/ioctl.h ->asm/ioctl.h ->asm-generic/ioctl.h 函数原型: extern int ioctl (int __fd, unsigned long int __request, ...) __THROW; 第一个参数是文件描述符 第二个参数代表传递的命令,它会原样...
  • ioctl 是设备驱动程序中设备控制接口函数,一个字符设备驱动通常会实现设备打开、关闭、读、写等功能,在一些需要细分的情境下,如果需要扩展新的功能,通常以增设 ioctl() 命令的方式实现。 在文件 I/O 中,ioctl ...
  • i2c_ioctl详解

    2014-08-06 20:59:09
    详细描述了linux驱动中ioctl的使用方法
  • 1. 底层设备驱动已经实现ioctl相关操作接口 2. 本篇主要讲如何实现JNI层和应用层的ioctl相关内容 3. 这里是基于sda810开发板调试,其他arm开发板搭载安卓系统均可以调试 NDK环境搭建和Demo代码实现 环境搭建 ...
  • 我正在编写一个Linux内核模块(LKM)作为伪驱动程序 – 我无法弄清楚如何在LKM(wait.c)和用户级程序(user.c)之间进行IOCTL调用).设备驱动程序的幻数是0xBF – LKM不与物理块/字符设备通信,它只是一个练习.据我所知,对...
  • Linux下的ioctl接口介绍及其应用

    千次阅读 2021-11-14 20:57:42
    ioctl接口也叫做unlocked_ioctl接口。 unlocked_ioctl和read/write函数的异同点: 相同点:都可以往内核中写数据。 不同点:read函数只能完成读的功能,write函数只能完成写的功能,ioctl既可以读也可以写,但在读取...
  • Follows an explanation of the patch that introduced unlocked_ioctl and compat_ioctl into 2.6.11. The removal of the ioctl field happened a lot later, in 2.6.36. Explanation: When ioctl was executed, ...
  • v4l2的结构体之ioctl

    2021-03-19 08:43:02
    v4l2的结构体之ioctl struct v4l2_ioctl_ops 介绍 在应用程序获取视频数据的流程中,都是通过 ioctl 命令与驱动程序进行交互,结合实际需求,实现struct v4l2_ioctl_ops相关的成员即可。 定义 struct v4l2_fh; /** ...
  • ioctl系统调用

    2020-05-18 22:54:18
    先mark一下: https://www.cnblogs.com/lifexy/p/10289491.html https://www.cnblogs.com/tdyizhen1314/p/4896689.html https://blog.csdn.net/dayancn/article/details/52953777 ... ioctl内核实现的地方: //\l
  • ioctl参数详解

    2021-05-21 12:04:52
    #includeint ioctl( int fd, int request, .../* void *arg */ );返回0:成功-1:出错第三个参数总是一个指针,但指针的类型依赖于request参数。我们可以把和网络相关的请求划分为6类:套接口操作文件操作接口操作...
  • 用户空间的ioctl

    2020-11-21 22:34:52
    一个字符设备驱动通常会实现常规的打开、关闭、读、写等功能,但在一些细分的情境下,如果需要扩展新的功能,通常以增设ioctl()命令的方式实现,其作用类似于“拾遗补漏”。在文件I/O中,ioctl扮演着重要角色,本文...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 96,825
精华内容 38,730
关键字:

ioctl

友情链接: 直角坐标系.zip