ioctl详解
- 格式:docx
- 大小:26.63 KB
- 文档页数:18
简介⼏种系统调⽤函数:write、read、open、close、ioctl 在 Linux 中,⼀切(或⼏乎⼀切)都是⽂件,因此,⽂件操作在 Linux 中是⼗分重要的,为此,Linux 系统直接提供了⼀些函数⽤于对⽂件和设备进⾏访问和控制,这些函数被称为系统调⽤(syscall),它们也是通向操作系统本⾝的接⼝。
⼀、系统调⽤ 系统调⽤就是 Linux 内核提供的⼀组⽤户进程与内核进⾏交互的接⼝。
这些接⼝让应⽤程序受限的访问硬件设备,提供了创建新进程并与已有进程进⾏通信的机制,也提供了申请操作系统其他资源的能⼒。
系统调⽤⼯作在内核态,实际上,系统调⽤是⽤户空间访问内核空间的唯⼀⼿段(除异常和陷⼊外,它们是内核唯⼀的合法⼊⼝)。
系统调⽤的主要作⽤如下:1)系统调⽤为⽤户空间提供了⼀种硬件的抽象接⼝,这样,当需要读写⽂件时,应⽤程序就可以不⽤管磁盘类型和介质,甚⾄不⽤去管⽂件所在的⽂件系统到底是哪种类型;2)系统调⽤保证了系统的稳定和安全。
作为硬件设备和应⽤程序之间的中间⼈,内核可以基于权限、⽤户类型和其他⼀些规则对需要进⾏的访问进⾏判断;3)系统调⽤是实现多任务和虚拟内存的前提。
要访问系统调⽤,通常通过 C 库中定义的函数调⽤来进⾏。
它们通常都需要定义零个、⼀个或⼏个参数(输⼊),⽽且可能产⽣⼀些副作⽤(会使系统的状态发⽣某种变化)。
系统调⽤还会通过⼀个 long 类型的返回值来表⽰成功或者错误。
通常,⽤⼀个负的值来表明错误,0表⽰成功。
系统调⽤出现错误时,C 库会把错误码写⼊ errno 全局变量,通过调⽤ perror() 库函数,可以把该变量翻译成⽤户可理解的错误字符串。
⼆、⼏种常⽤的系统调⽤函数2.1 write 系统调⽤ 系统调⽤ write 的作⽤是把缓冲区 buf 的前 nbytes 个字节写⼊与⽂件描述符 fildes 关联的⽂件中。
它返回实际写⼊的字节数。
如果⽂件描述符有错或者底层的设备驱动程序对数据块长度⽐较敏感,该返回值可能会⼩于 nbytes。
ioctl⽅法详解设备控制接⼝(ioctl 函数)回想⼀下我们在中介绍的struct file_operations 结构,这⾥我们将介绍⼀个新的⽅法:int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);这是驱动程序设备控制接⼝函数(ioctl函数)的内核原型定义,struct inode * 和struct file* 描述了操作的⽂件,unsigned int 描述了ioctl命令号,这是⼀个重要的参数,我们稍后会对它做详细介绍。
最后⼀个参数是unsigned long数据类型,描述了ioctl命令可能带有的参数,它可能是⼀个整数或指针数据。
ioctl命令号ioctl命令号是这个函数中最重要的参数,它描述的ioctl要处理的命令。
Linux中使⽤⼀个32位的数据来编码ioctl命令,它包含四个部分:dir:type:nr:size。
dir:代表数据传输的⽅向,占2位,可以是_IOC_NONE(⽆数据传输,0U),_IOC_WRITE(向设备写数据,1U)或_IOC_READ(从设备读数据,2U)或他们的逻辑或组合,当然只有_IOC_WRITE和_IOC_READ的逻辑或才有意义。
type:描述了ioctl命令的类型,8位。
每种设备或系统都可以指定⾃⼰的⼀个类型号,ioctl⽤这个类型来表⽰ioctl命令所属的设备或驱动。
⼀般⽤ASCII码字符来表⽰,如 'a'。
nr:ioctl命令序号,⼀般8位。
对于⼀个指定的设备驱动,可以对它的ioctl命令做⼀个顺序编码,⼀般从零开始,这个编码就是ioctl命令的序号。
size:ioctl命令的参数⼤⼩,⼀般14位。
ioctl命令号的这个数据成员不是强制使⽤的,你可以不使⽤它,但是我们建议你指定这个数据成员,通过它我们可以检查⽤户空间数据的⼤⼩以避免错误的数据操作,也可以实现兼容旧版本的ioctl命令。
C socket ioctl使用方法一、什么是ioctlioctl是一个用于控制设备的系统调用,它可以向设备发出特定的控制命令,从而对设备进行配置、控制和查询。
在C语言中,我们可以使用ioctl函数来调用ioctl系统调用。
二、C socket在网络编程中,C语言中的socket库提供了对网络通信的支持,可以使用socket库来创建、连接、发送和接收网络数据。
而在进行网络编程的过程中,有时候我们会需要通过ioctl来控制和配置网络套接字的一些参数。
三、使用ioctl对socket进行控制在C语言中,我们可以使用ioctl函数来对socket进行控制。
具体的使用步骤如下:1. 包含相关头文件在使用ioctl函数之前,我们需要包含相关的头文件,以便能够调用ioctl函数和使用所需的常量定义。
常用的头文件包括<sys/ioctl.h>和<sys/socket.h>。
2. 创建socket我们需要通过socket函数来创建一个套接字。
套接字可以是流套接字(SOCK_STREAM)或者数据报套接字(SOCK_DGRAM),具体的类型由实际需求决定。
3. 设置套接字参数在创建套接字之后,我们可以使用setsockopt函数来设置套接字的一些参数,如超时时间、重传次数等。
当然,也可以通过ioctl函数来设置一些更底层的套接字参数。
4. 调用ioctl函数接下来,我们就可以调用ioctl函数来对套接字进行控制。
ioctl函数的原型通常为:```cint ioctl(int fd, unsigned long request, ...);```其中,fd为套接字描述符,request为控制命令,后面的参数视具体的控制命令而定。
通过合理的request值和参数,我们可以控制套接字的多种参数,如发送缓冲区大小、接收超时时间等。
5. 错误处理在调用ioctl函数之后,我们需要根据返回值来进行错误处理。
c语言ioctl函数ioctl函数是Linux系统中的一个系统调用函数,用于控制设备驱动程序的操作。
该函数是一个通用的设备控制函数,可以通过不同的命令和参数来实现各种操作。
本文将详细介绍ioctl函数的使用方法、常见的命令和参数以及一些实际应用场景。
一、ioctl函数的定义和使用方法ioctl函数的定义如下所示:```cint ioctl(int fd, unsigned long request, ...)```fd是打开设备文件或套接字的文件描述符;request是一个32位的整数,表示对设备的操作命令;最后一个参数是一个可变参数,具体类型和数量取决于request的命令和需要的参数。
使用ioctl函数的一般步骤如下:1. 打开设备文件或套接字,并得到文件描述符fd;2. 根据实际需要构造request命令,并设置相应的参数;3. 调用ioctl函数,将fd、request和对应的参数传递给该函数;4.根据需要进行错误处理和结果处理。
二、常见的ioctl命令和参数1. 设备IO命令:通过ioctl函数可以对设备进行读写操作,常用的设备IO命令有以下几种:-FIONREAD:获取输入缓冲区中的字节数;-FIONBIO:设置套接字为非阻塞模式;-TIOCSBRK/TIOCCBRK:控制串行通信中的发送或停止发送中断信号;-TCGETS/TCSETS:获取或设置终端的配置参数。
2. 文件IO命令:ioctl函数还可以对文件进行各种操作,如文件的位置设置、锁定区域设置等。
常见的文件IO命令有以下几种:- FIOCLEX/FIONCLEX:设置和清除文件描述符的close-on-exec标志;-FIONREAD:获取文件中可读取的字节数;-FIONBIO:设置文件的非阻塞模式;-FIOASYNC:设置文件为异步IO模式。
3. 网络IO命令:通过ioctl函数还可以对网络套接字进行各种操作,如获取套接字的状态、设置套接字选项等。
用ioctl获得本地ip地址时要用到两个结构体ifconf和ifreq,它们对于大多数人来说都是比较陌生的,这里给大家一种比较简单的理解方法,当然只一种帮助理解的方法,在描述中可能会有一些地方与真实定义有所出入,仅供参考.首先先认识一下ifconf和ifreq://ifconf通常是用来保存所有接口信息的//if.hstruct ifconf{int ifc_len; /* size of buffer */union{char *ifcu_buf; /* input from user->kernel*/struct ifreq *ifcu_req; /* return from kernel->user*/} ifc_ifcu;};#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */#define ifc_req ifc_ifcu.ifcu_req /* array of structures *///ifreq用来保存某个接口的信息//if.hstruct ifreq{char ifr_name[IFNAMSIZ];union {struct sockaddr ifru_addr;struct sockaddr ifru_dstaddr;struct sockaddr ifru_broadaddr;short ifru_flags;int ifru_metric;caddr_t ifru_data;} ifr_ifru;};#define ifr_addr ifr_ifru.ifru_addr#define ifr_dstaddr ifr_ifru.ifru_dstaddr#define ifr_broadaddr ifr_ifru.ifru_broadaddr上边这两个结构看起来比较复杂,我们现在把它们简单化一些:比如说现在我们向实现获得本地IP的功能。
unlocked_ioctl的用法在Linux内核中,ioctl系统调用是用于设备驱动程序与用户空间之间进行通信的一种机制。
其中,unlocked_ioctl函数用于处理非重要的ioctl命令,而在多线程执行时无需加锁。
unlocked_ioctl函数的定义如下:long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long)其中,第一个参数为打开的设备文件指针,第二个参数为ioctl 命令,第三个参数为ioctl参数。
在驱动程序中实现unlocked_ioctl函数时,需要根据ioctl命令的不同进行相应的处理。
一般来说,可以使用switch语句来判断ioctl命令,并在每个case中进行相应的处理。
例如,当ioctl命令为IOCTL_CMD1时,可以执行如下操作:static long my_ioctl(struct file *file, unsigned int cmd, unsigned long arg){switch (cmd) {case IOCTL_CMD1:/* 处理IOCTL_CMD1命令 */break;/* 其他命令的处理 */default:return -EINVAL;}return 0;}需要注意的是,在实现unlocked_ioctl函数时,应该遵循良好的编程实践,防止出现访问非法内存、空指针等问题,确保驱动程序的稳定性和安全性。
总之,unlocked_ioctl函数是Linux内核中用于处理ioctl命令的重要函数之一,驱动程序开发者应该熟悉其用法,合理地使用该函数,提高驱动程序的效率和稳定性。
文章标题:深度解析ioctl write read及其在操作系统中的应用在操作系统中,ioctl write read是一个重要的系统调用,用于设备驱动程序和用户空间程序之间进行通信和数据传输。
它涉及到设备的读写操作,以及参数的传递和数据的交换,对于理解操作系统的基本原理和内部机制具有重要意义。
一、ioctl write read的基本概念和原理1. ioctl write read的定义和功能ioctl write read是一种用于设备驱动程序的系统调用,它允许用户空间程序向设备发出控制命令(ioctl write)或者进行数据读写(ioctl read),从而实现设备的配置、状态查询和数据交换等操作。
2. ioctl write read的调用方式和参数ioctl write read的调用通常需要指定设备文件描述符、ioctl命令码和参数指针等信息,以便设备驱动程序正确解析并执行用户空间程序的请求。
3. ioctl write read的内部实现和机制ioctl write read的内部实现涉及到系统调用的传递和参数的解析,以及设备驱动程序的响应和数据传输,需要通过对操作系统内部结构和调度机制的理解才能深入掌握其工作原理。
二、ioctl write read的应用场景和实际意义1. 设备驱动程序中的ioctl write read使用在设备驱动程序中,ioctl write read常用于设备的配置和控制,以及数据的读写和传输,例如网络设备的设置、字符设备的输入输出等。
2. 用户空间程序中的ioctl write read调用在用户空间程序中,ioctl write read可以用于与设备驱动程序进行通信和交互,实现设备的操作和功能扩展,例如串口通信、USB设备控制等。
三、个人观点和理解从我个人的理解来看,ioctl write read是操作系统中一个重要的系统调用,它为设备驱动程序和用户空间程序之间的通信提供了灵活和强大的接口,有利于实现设备的功能扩展和应用开发。
ioctl函数详细说明(网络)分类:应用编程2012-06-15 12:02 947人阅读评论(0) 收藏举报网络structcommandsocketinterface软件测试ioctl 函数本函数影响由fd 参数引用的一个打开的文件。
#include<unistd.h>int ioctl( int fd, int request, .../* void *arg */ );返回0 :成功-1 :出错第三个参数总是一个指针,但指针的类型依赖于request 参数。
我们可以把和网络相关的请求划分为6 类:套接口操作文件操作接口操作ARP 高速缓存操作路由表操作流系统下表列出了网络相关ioctl 请求的request 参数以及arg 地址必须指向的数据类型:类别Request 说明数据类型套接口SIOCATMARKSIOCSPGRPSIOCGPGRP是否位于带外标记设置套接口的进程ID 或进程组ID获取套接口的进程ID 或进程组IDintintint文件FIONBINFIOASYNCFIONREADFIOSETOWNFIOGETOWN设置/ 清除非阻塞I/O 标志设置/ 清除信号驱动异步I/O 标志获取接收缓存区中的字节数设置文件的进程ID 或进程组ID获取文件的进程ID 或进程组IDintintintintint接口SIOCGIFCONFSIOCSIFADDRSIOCGIFADDRSIOCSIFFLAGSSIOCGIFFLAGSSIOCSIFDSTADDRSIOCGIFDSTADDR获取所有接口的清单设置接口地址获取接口地址设置接口标志获取接口标志设置点到点地址获取点到点地址struct ifconfstruct ifreqstruct ifreqstruct ifreqstruct ifreqstruct ifreqstruct ifreqSIOCGIFBRDADDR SIOCSIFBRDADDR SIOCGIFNETMASK SIOCSIFNETMASK SIOCGIFMETRIC SIOCSIFMETRIC SIOCGIFMTU SIOCxxx 获取广播地址设置广播地址获取子网掩码设置子网掩码获取接口的测度设置接口的测度获取接口MTU(还有很多取决于系统的实现)struct ifreqstruct ifreqstruct ifreqstruct ifreqstruct ifreqstruct ifreqstruct ifreqARP SIOCSARPSIOCGARPSIOCDARP创建/ 修改ARP 表项获取ARP 表项删除ARP 表项struct arpreqstruct arpreqstruct arpreq路由SIOCADDRTSIOCDELRT增加路径删除路径struct rtentrystruct rtentry流I_xxx套接口操作:明确用于套接口操作的ioctl 请求有三个, 它们都要求ioctl 的第三个参数是指向某个整数的一个指针。
linux 驱动的ioctl 详细说明摘要:1.概述ioctl 的作用和用法2.ioctl 的错误码及含义3.ioctl 的参数4.ioctl 的返回值及意义5.ioctl 在Linux 声卡驱动中的应用正文:一、概述ioctl 的作用和用法ioctl(input/output control)是Linux 系统中一种用于设备控制的系统调用,通过ioctl,用户进程可以对设备进行配置、查询和控制等操作。
ioctl 的用法通常为:```int ioctl(int fd, int request,...);```其中,fd 表示设备的文件描述符,request 表示设备驱动程序所支持的控制请求,后面的省略号表示可能的附加参数。
二、ioctl 的错误码及含义ioctl 系统调用可能返回以下错误码:- -1:表示发生了错误,此时errno 系统变量将包含具体的错误码。
- 0:表示操作成功完成。
- 其他大于0 的值:表示设备的某些特殊状态,具体含义需根据设备类型和驱动程序来确定。
三、ioctl 的参数ioctl 的参数主要包括以下几类:1.设备文件描述符fd:表示要控制的设备的文件描述符。
2.控制请求request:表示要执行的设备控制操作,如配置、查询、控制等。
3.附加参数:根据设备类型和控制请求的不同,可能需要提供不同的附加参数。
这些参数通常是设备驱动程序所支持的数据结构或整数变量。
四、ioctl 的返回值及意义ioctl 的返回值表示设备驱动程序处理控制请求的结果。
如果返回值为-1,则表示发生了错误;如果返回值为0,则表示操作成功完成;如果返回值为其他大于0 的值,则表示设备的某些特殊状态。
具体的错误码和含义可以通过errno 系统变量获取。
五、ioctl 在Linux 声卡驱动中的应用在Linux 声卡驱动中,ioctl 被广泛应用于配置声卡设备、查询声卡状态、控制声音播放等。
例如,通过ioctl 可以实现以下功能:- 获取声卡设备的信息,如设备型号、支持的采样率等。
ioctl系统调用流程一、系统调用框架∙与系统调用相关的数据结构和函数系统调用函数名以“sys_”开头,后面是该系统调用的名字,由此构成了sys_name()这样的函数名。
在include/asm/unistd.h中不同的体系结构为每一个系统调用定义了惟一的编号,假设用name来表示系统调用的名称,那么系统调用号与系统调用响应函数的关系是:以系统调用号__NR_name作为下标,可找出系统调用表sys_call_table中对应表项的内容,它也就是该系统调用的响应函数sys_name的入口地址。
∙系统调用具体执行流程当执行一个系统调用时,处理器跳转到地址0xc00。
参考代码:arch/ppc/kernel/head.S. = 0xc00SystemCall:EXCEPTION_PROLOGstw r3,ORIG_GPR3(r21)li r20,MSR_KERNELrlwimi r20,r23,0,16,16bl transfer_to_handler.long DoSyscall.long ret_from_except有关DoSyscall,它在文件arch/ppc/kernel/entry.S 中定义。
这个函数最终使用系统调用编号把系统调用表的地址和索引加载,操作系统使用系统调用表把系统调用编号翻译为特定的系统调用。
系统调用表名为sys_call_table,在arch/ppc/kernel/misc.S 中定义。
系统调用表包含有实现每个系统调用的函数的地址。
_GLOBAL(sys_call_table).long sys_ni_syscalllong sys_getegid.long sys_acct.long sys_umount.long sys_ni_syscall.long sys_ioctl.long sys_fcntl当DoSyscall 找到正确的系统调用地址后,它把调用指定的系统调用函数。
ioctl函数详细说明(网络)分类:应用编程2012-06-15 12:02 947人阅读评论(0) 收藏举报网络structcommandsocketinterface软件测试ioctl 函数本函数影响由fd 参数引用的一个打开的文件。
#include<unistd.h>int ioctl( int fd, int request, .../* void *arg */ );返回0 :成功-1 :出错第三个参数总是一个指针,但指针的类型依赖于request 参数。
我们可以把和网络相关的请求划分为6 类:套接口操作文件操作接口操作ARP 高速缓存操作路由表操作流系统下表列出了网络相关ioctl 请求的request 参数以及arg 地址必须指向的数据类型:类别Request 说明数据类型套接口SIOCATMARKSIOCSPGRPSIOCGPGRP是否位于带外标记设置套接口的进程ID 或进程组ID获取套接口的进程ID 或进程组IDintintint文件FIONBINFIOASYNCFIONREADFIOSETOWNFIOGETOWN设置/ 清除非阻塞I/O 标志设置/ 清除信号驱动异步I/O 标志获取接收缓存区中的字节数设置文件的进程ID 或进程组ID获取文件的进程ID 或进程组IDintintintintint接口SIOCGIFCONFSIOCSIFADDRSIOCGIFADDRSIOCSIFFLAGSSIOCGIFFLAGSSIOCSIFDSTADDRSIOCGIFDSTADDR获取所有接口的清单设置接口地址获取接口地址设置接口标志获取接口标志设置点到点地址获取点到点地址struct ifconfstruct ifreqstruct ifreqstruct ifreqstruct ifreqstruct ifreqstruct ifreqSIOCGIFBRDADDR SIOCSIFBRDADDR SIOCGIFNETMASK SIOCSIFNETMASK SIOCGIFMETRIC SIOCSIFMETRIC SIOCGIFMTU SIOCxxx 获取广播地址设置广播地址获取子网掩码设置子网掩码获取接口的测度设置接口的测度获取接口MTU(还有很多取决于系统的实现)struct ifreqstruct ifreqstruct ifreqstruct ifreqstruct ifreqstruct ifreqstruct ifreqARP SIOCSARPSIOCGARPSIOCDARP创建/ 修改ARP 表项获取ARP 表项删除ARP 表项struct arpreqstruct arpreqstruct arpreq路由SIOCADDRTSIOCDELRT增加路径删除路径struct rtentrystruct rtentry流I_xxx套接口操作:明确用于套接口操作的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 等效。
接口配置:得到系统中所有接口由SIOCGIFCONF 请求完成,该请求使用ifconf 结构,ifconf 又使用ifreq结构,如下所示:Struct ifconf{int ifc_len; // 缓冲区的大小union{caddr_t ifcu_buf; // input from user->kernelstruct ifreq *ifcu_req; // return of structures returned}ifc_ifcu;};#define ifc_buf ifc_ifcu.ifcu_buf //buffer address#define ifc_req ifc_ifcu.ifcu_req //array of structures returned#define IFNAMSIZ 16struct ifreq{char ifr_name[IFNAMSIZ]; // interface name, e.g., “le0”union{struct sockaddr ifru_addr;struct sockaddr ifru_dstaddr;struct sockaddr ifru_broadaddr;short ifru_flags; int ifru_metric; caddr_t ifru_data; }ifr_ifru; };#define ifr_addr ifr_ifru.ifru_addr // address#define ifr_dstaddr ifr_ifru.ifru_dstaddr // otner end of p-to-p link #define ifr_broadaddr ifr_ifru.ifru_broadaddr // broadcast address #define ifr_flags ifr_ifru.ifru_flags // flags #define ifr_metric ifr_ifru.ifru_metric // metric#define ifr_data ifr_ifru.ifru_data // for use by interface再调用ioctl 前我们必须先分撇一个缓冲区和一个ifconf 结构,然后才初始化后者。
如下图 展示了一个ifconf 结构的初始化结构,其中缓冲区的大小为1024 ,ioctl 的第三个参数指向 这样一个ifconf 结构。
1024---------------------> 缓存假设内核返回2 个ifreq 结构,ioctl 返回时通过同一个ifconf 结构缓冲区填入了那2 个ifreq 结构,ifconf 结构的ifc_len 成员也被更新,以反映存放在缓冲区中的信息量 一般来讲ioctl 在用户程序中的调用是: ioctl (int fd,int command, (char*)argstruct)ioctl 调用与网络编程有关(本文只讨论这一点),文件描述符fd 实际上是由socket()系统调用返回的。
参数command 的取值由/usr/include/linux/sockios.h 所规定。
这些command 的由于功能的不同,可分为以下几个小类: • 改变路由表 (例如 SIOCADDRT, SIOCDELRT),• 读/更新 ARP/RARP 缓存(如:SIOCDARP, SIOCSRARP),• 一般的与网络接口有关的(例如 SIOCGIFNAME, SIOCSIFADDR 等等)在 Gooodies 目录下有很多样例程序展示了如何使用ioctl 。
当你看这些程序时,注意参数argstruct 是与参数command 相关的。
例如,与 路由表相关的ioctl 使用rtentry 这种结构,rtentry 定义在/usr/include/linux/route.h (参见例子 adddefault.c )。
与ARP 有关的ioctl 调用使用arpreq 结构,arpreq 定义在/usr/include/linux /if_arp.h (参见例子arpread.c )ifc_len Ifc_buf与网络接口有关的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之外的新的定义。
实例:程序1:检测接口的.net_addr,netmask,broad_addr程序2:检查接口的物理连接是否正常程序3:更简单一点测试物理连接程序4:调节音量***************************程序1****************************************#include <s td io.h>#include <string.h>#include <stdlib.h>#include <errno.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/ioctl.h>#include <net/if.h>static void usage(){printf("usage : ipconfig interface \n");exit(0);}int main(int argc,char **argv){struct sockaddr_in *addr;struct ifreq ifr;char *name,*address;int sockfd;if(argc != 2)usage();elsename = argv[1];sockfd = socket(AF_INET,SOCK_DGRAM,0); strncpy(ifr.ifr_name,name,IFNAMSIZ-1);if(ioctl(sockfd,SIOCGIFADDR,&ifr) == -1)perror("ioctl error"),exit(1);addr = (struct sockaddr_in *)&(ifr.ifr_addr); address = inet_ntoa(addr->sin_addr);printf("inet addr: %s ",address);if(ioctl(sockfd,SIOCGIFBRDADDR,&ifr) == -1) perror("ioctl error"),exit(1);addr = (struct sockaddr_in *)&ifr.ifr_broadaddr; address = inet_ntoa(addr->sin_addr);printf("broad addr: %s ",address);if(ioctl(sockfd,SIOCGIFNETMASK,&ifr) == -1) perror("ioctl error"),exit(1);addr = (struct sockaddr_in *)&ifr.ifr_addr; address = inet_ntoa(addr->sin_addr);printf("inet mask: %s ",address);printf("\n");exit(0);}******************************** 程序2***************************************************** #include <stdio.h>#include <string.h>#include <errno.h>#include <fcntl.h>#include <getopt.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <net/if.h>#include <stdlib.h>#include <unistd.h>typedef unsigned short u16;typedef unsigned int u32;typedef unsigned char u8;#include <linux/ethtool.h>#include <linux/sockios.h>int detect_mii(int skfd, char *ifname){struct ifreq ifr;u16 *data, mii_val;unsigned phy_id;/* Get the vitals from the interface. */strncpy(ifr.ifr_name, ifname, IFNAMSIZ);if (ioctl(skfd, SIOCG MI IPHY, &ifr) < 0){fprintf(stderr, "SIOCGMIIPHY on %s failed: %s\n", ifname,strerror(errno));(void) close(skfd);return 2;}data = (u16 *)(&ifr.ifr_data);phy_id = data[0];data[1] = 1;if (ioctl(skfd, SIOCGMIIREG, &ifr) < 0){fprintf(stderr, "SIOCGMIIREG on %s failed: %s\n", ifr.ifr_name,strerror(errno));return 2;}mii_val = data[3];return(((mii_val & 0x0016) == 0x0004) ? 0 : 1);}int detect_ethtool(int skfd, char *ifname){struct ifreq ifr;struct ethtool_value edata;memset(&ifr, 0, sizeof(ifr));edata.cmd = ETHTOOL_GLINK;strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)-1);ifr.ifr_data = (char *) &edata;if (ioctl(skfd, SIOCETHTOOL, &ifr) == -1){printf("ETHTOOL_GLINK failed: %s\n", strerror(errno));return 2;}return (edata.data ? 0 : 1);}int main(int argc, char **argv){int skfd = -1;char *ifname;int retval;if( argv[1] )ifname = argv[1];elseifname = "eth0";/* Open a socket. */if (( skfd = socket( AF_INET, SOCK_DGRAM, 0 ) ) < 0 ) {printf("socket error\n");exit(-1);}retval = detect_ethtool(skfd, ifname);if (retval == 2)retval = detect_mii(skfd, ifname);close(skfd);if (retval == 2)printf("Could not determine status\n");if (retval == 1)printf("Link down\n");if (retval == 0)printf("Link up\n");return retval;}*******************************程序3***************************************************** #include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <net/if.h>#include <linux/sockios.h>#include <sys/ioctl.h>#define LINKTEST_GLINK 0x0000000astruct linktest_value {unsigned int cmd;unsigned int data;};staticvoidusage(const char * pname){fprintf(stderr, "usage: %s <device>\n", pname);fprintf(stderr, "returns: \n");fprintf(stderr, "\t 0: link detected\n");fprintf(stderr, "\t%d: %s\n", ENODEV, strerror(ENODEV));fprintf(stderr, "\t%d: %s\n", ENONET, strerror(ENONET));fprintf(stderr, "\t%d: %s\n", EOPNOTSUPP, strerror(EOPNOTSUPP));exit(EXIT_FAILURE);}staticintlinktest(const char * devname){struct ifreq ifr;struct linktest_value edata;int fd;/* setup our control structures. */memset(&ifr, 0, sizeof(ifr));strcpy(ifr.ifr_name, devname);/* open control socket. */fd=socket(AF_INET, SOCK_DGRAM, 0);if(fd < 0 ) {return -ECOMM;}errno=0;edata.cmd = LINKTEST_GLINK;ifr.ifr_data = (caddr_t)&edata;if(!ioctl(fd, SIOCETHTOOL, &ifr)) {if(edata.data) {fprintf(stdout, "link detected on %s\n", devname);return 0;} else {errno=ENONET;}}perror("linktest");return errno;}intmain(int argc, char *argv[]){if(argc != 2) {usage(argv[0]);}return linktest(argv[1]);}*************************************程序4********************************************************* #include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/ioctl.h>#include <sys/soundcard.h>#include <stdio.h>#include <unistd.h>#include <math.h>#include <string.h>#include <stdlib.h>#define BASE_VALUE 257int main(int argc,char *argv[]){int mixer_fd=0;char *names[SOUND_MIXER_NRDEVICES]=SOUND_DEVICE_LABELS;int value,i;printf("\nusage:%s dev_no.[0..24] value[0..100]\n\n",argv[0]);printf("eg. %s 0 100\n",argv[0]);printf(" will change the volume to MAX volume.\n\n");printf("The dev_no. are as below:\n");for (i=0;i<SOUND_MIXER_NRDEVICES;i++){if (i%3==0) printf("\n");printf("%s:%d\t\t",names[i],i);}printf("\n\n");if (argc<3)exit(1);if ((mixer_fd = open("/dev/mixer",O_RDWR))){printf("Mixer opened successfully,working...\n");value=BASE_VALUE*atoi(argv[2]);if (ioctl(mixer_fd,MIXER_WRITE(atoi(argv[1])),&value)==0)printf("successfully.....");else printf("unsuccessfully.....");printf("done.\n");}elseprintf("can't open /dev/mixer error....\n");exit(0);}。