首页 > 代码库 > 《网络编程》ioctl 操作
《网络编程》ioctl 操作
概述
ioctl 函数和 fcntl 函数类似,都可用于对描述符的操作,获取或设置已打开描述符的属性,但是两个函数在网络编程相关中操作针对不同了类型,fcntl 函数有套接字操作、文件操作,而 ioctl 函数除了可以操作 fcntl 函数可操作的类型之外,还可以进行接口操作、路由表操作、 ARP 高速缓存操作以及流系统操作。
ioctl 函数
该函数可以实现对已打开描述符进程操作,其定义如下:
/* 函数功能:操作描述符,设置已打开的描述符属性; * 函数原型: */ #include <sys/ioctl.h> /* Perform the I/O control operation specified by REQUEST on FD. One argument may follow; its presence and type depend on REQUEST. Return value depends on REQUEST. Usually -1 indicates error. */ int ioctl (int fd, unsigned long int request, .../* void *arg */); /* * 说明: * 把和网络相关的请求request划分为以下 6 类: * (1)套接字操作 * (2)文件操作 * (3)接口操作 * (4)ARP高速缓存操作 * (5)路由表操作 * (6)流系统 */ /* *fcntl函数 *功能:操纵文件描述符,设置已打开的文件的属性*/ int fcntl(int fd, int cmd, ... /* arg */ ); /*说明: * fcntl 函数提供了与网络编程相关的特性如下: * (1)非阻塞式IO;标志:O_NONBLOCK * (2)信号驱动式IO;标志:O_ASYNC * (3)套接字属性;标志:F_GETOWN、F_SETOWN * * cmd的取值可以如下: * 复制文件描述符 * F_DUPFD (long) * 设置/获取文件描述符标志 * F_GETFD (void) * F_SETFD (long) * 设置/获取文件状态标志 * F_GETFL (void) * F_SETFL (long) * 获取/设置文件锁 * F_GETLK * F_SETLK,F_SETLKW */其中 request 参数以及 arg 地址指向的数据类型与网络相关,以下列出了不同网络类型对应的信息:
套接字操作
由上面表格可以知道,在套接字操作中,ioctl 函数的请求 request 参数有 3 可选值,并且这 3 个值对应的第三个参数的数据类型是一个指向整数的指针。
- SIOCATMARK:若套接字的 读指针 当前位于带外标记,则 ioctl 函数通过第三个参数指向的整数返回非 0 值;否则返回 0 值;
- SIOCGPRP:通过由第三个参数指向的整数返回套接字的 进程 ID 或进程组 ID,该 ID 指定针对套接字的 SIGIO 或 SIGURG 信号的接收进程;等价于 fcntl 函数指定 F_GETOWN 命令;
- SIOCSPGRP:把套接字的 进程 ID 或 进程组 ID 设置成由第三个参数指向的整数,该 ID 指定针对套接字的 SIGIO 或 SIGURG 信号的接收进程;等价于 fcntl 函数指定 F_SETOWN 命令;
文件操作
根据 请求 request 参数和第三个参数不同有以下的内容:
- FIONBIO:根据 ioctl 函数第三个参数指向一个 0 值或非 0 值,可清除或设置套接字的非阻塞 I/O 标志;
- FIOASYNC:根据 ioctl 函数第三个参数指向一个 0 值或非 0 值,可清除或设置套接字的信号驱动异步 I/O 标志,决定是否接收针对套接字的异步 I/O 信号(SIGIO);
- FIONREAD:根据 ioctl 函数第三个参数指向的整数返回当前套接字接收缓冲区的字节数;
- FIOSETOWN:对于套接字和前面的 SIOCSPGRP 等效:
- FIOGETOWN:对于套接字和前面的 SIOCGPGRP 等效:
接口操作
需要处理网络接口,首先必须从内核获取配置在系统上的所有接口信息。具体请求 request 参数的取值由上表可知。SIOCGIFCONF:从内核中获取系统中配置的所有接口。它使用了结构 ifconf,ifconf 又使用了 ifreq 结构。在调用 ioctl 之前分配一个缓冲区和一个 ifconf 结构,然后初始化后者,iotctl 的第三个参数指向 ifconf 结构。
/* 结构定义如下:*/ struct ifconf { int ifc_len; /* size of buffer, value-result */ union { caddr_t ifcu_buf; /* input from user->kernel */ struct ifreq *ifcu_req; /* return from kernel->user */ }ifc_ifcu; }; #define ifc_buf ifc_ifcu.ifcu_buf #define ifc_req ifc_ifcu.ifcu_req #define IFNAMSIZ 16 struct 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.broadaddr #define ifr_flags ifr_ifru.ifru_flags #define ifr_metric ifr_ifru.ifru_metric #define ifr_data ifr_ifru.ifru_data
ARP 高速缓存操作
可以使用 ioctl 函数操作 ARP 高速缓存,ioctl 函数的第三个参数必须指向一个 arpreq 结构,其结构定义如下:
/* ARP ioctl request. */ struct arpreq { struct sockaddr arp_pa; /* Protocol address. */ struct sockaddr arp_ha; /* Hardware address. */ int arp_flags; /* Flags. */ struct sockaddr arp_netmask; /* Netmask (only for proxy arps). */ char arp_dev[16]; }; /* ARP Flag values. */ #define ATF_COM 0x02 /* Completed entry (ha valid). */ #define ATF_PERM 0x04 /* Permanent entry. */ #define ATF_PUBL 0x08 /* Publish entry. */ #define ATF_USETRAILERS 0x10 /* Has requested trailers. */ #define ATF_NETMASK 0x20 /* Want to use a netmask (only for proxy entries). */ #define ATF_DONTPUB 0x40 /* Don't answer this addresses. */ #define ATF_MAGIC 0x80 /* Automatically added entry. */ /* Support for the user space arp daemon, arpd. */ #define ARPD_UPDATE 0x01 #define ARPD_LOOKUP 0x02 #define ARPD_FLUSH 0x03以下是请求参数的值及其功能:
- SIOCSARP:把一个新的表项添加到 ARP 高速缓存,或修改其中已经存在的一个表项;
- SIOCDARP:从 ARP 高速缓存中删除指定的一个表项;
- SIOCGARP:从 ARP 高速缓存中获取一个表项;
路由表操作
ioctl 函数有 2 个请求可以操作路由,其对应的第三个参数是指向 rtentry 结构的指针,该结构定义如下
/* This structure gets passed by the SIOCADDRT and SIOCDELRT calls. */ struct rtentry { unsigned long int rt_pad1; struct sockaddr rt_dst; /* Target address. */ struct sockaddr rt_gateway; /* Gateway addr (RTF_GATEWAY). */ struct sockaddr rt_genmask; /* Target network mask (IP). */ unsigned short int rt_flags; short int rt_pad2; unsigned long int rt_pad3; unsigned char rt_tos; unsigned char rt_class; #if __WORDSIZE == 64 short int rt_pad4[3]; #else short int rt_pad4; #endif short int rt_metric; /* +1 for binary compatibility! */ char *rt_dev; /* Forcing the device at add. */ unsigned long int rt_mtu; /* Per route MTU/Window. */ unsigned long int rt_window; /* Window clamping. */ unsigned short int rt_irtt; /* Initial RTT. */ };以下是请求参数的值及其功能:
- SIOCADDRT:往路由表中增加一个表项;
- SIOCDELRT:往路由表中删除一个表项;
总结
这章内容基本是围绕 ioctl 函数中的请求参数和第三个参数进行的,感觉不好记忆,因为都是一些参数标志,相关信息还是查看书本上的讲解,书本上有给出几个例子;
参考资料:
《Unix 网络编程》
《网络编程》ioctl 操作
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。