在本书中有两个地方都对这个函数进行了介绍,其实还有很多地方需要这个函数。ioclt函数传统上一直作为纳西而不适合归入其他精细定义类别的特性的系统接口。网络程序(特别是服务器程序)经常在程序启动执行后使用ioctl获取所在主机全部网络接口的信心,包括:接口地址、是否支持广播、是否支持多播。

#include <unistd.h>
int ioctl(int fd,int request,...../* void *arg /);
//返回:若成功则为0.失败则我-1
  1. 套接字操作
  2. 文件操作
  3. 接口操作
  4. ARP高速缓存操作
  5. 路由表操作
  6. 流系统

  不但某些ioclt操作和某些fcntl操作功能重叠(譬如把套接字设置为非阻塞),而且某些操作可以使用ioctl以不止一种方式制定(譬如设置套接字的进程组属主)。下表列出了网络相关ioctl请求的request参数以及arg地址必须指向的数据类型。

套接字操作

  明确要求套接字ioctl请求有三个,它们都要求ioctl的第三个参数是指向某个整数的一个指针。

  1. SIOCATMARK:如果本套接字的读指针当前位于带外标记,那就通过由第三个参数指向的帧数放回一个非0值,否则返回一个0值。
  2. SIOCGPGRP:通过由第三个参数指向的整数返回本套接字的进程ID或进程组ID,该ID指定针对本套接字的SIGIO或SIGURG信号的接受进程。
  3. SIOCSPGR :本套接字的进程ID或进程组ID设置成由第三个参数指向的整数,该ID指定对本套接字的SIGIO或SIGURG信号的接受进程。

文件操作

  以FIO打头的可能还适用于除套接字外某些特定类型的文件。都要求ioctl的第三个参数指向一个帧数。

  1. FIONBIO:根据ioctl的第三个参数指向一个0值或非0值,可消除或设置本套接字的非阻塞式I/O标志。本请求和O_NONBLOCK文件状态标志等效,而可以通过fcntlde F_SETFL命令清除或设置该标志。
  2. FIOASYNC:根据ioctl的第三个参数指向一个0值或非0值,可消除或设置本套接字的信号驱动异步I/O标志,它决定是否收取针对本套接字的异步I/O信号。本请求和O_ASYNC文件状态标志等效,而可以通过fcntl的F_SETFL命令清除或设置该标志
  3. FIONREAD:通过由ioctl的第三个参数指向的整数返回当前在本套接字接受缓冲区中的字节数。
  4. FIOSETOWN:对于本套接字和SIOCSPGRP等效
  5. FIOGETOWN:对于套接字和SIOCGPGRP等效。

接口配置

  从内核获取配置在系统中的所有接口,由SIOCGIFCONF完成。它使用ifconf结构,ifconf又使用ifreq结构。在使用ioctl前先分配一个缓冲区和一个ifconf结构,然后初始化后者。假设缓冲区大小为1024字节,ioctl的第三个参数指向这个结构。

  SIOCGIFCONF请求存在一个严重的问题是:在缓冲区大小不足以存放结果时,一些实现不返回错误,而是截断结果并返回成功(即ioctl的返回值为0)。要知道缓冲区足够大的唯一办法是:发请求,记下返回长度,用更大的缓冲区发请求,比较返回的长度和刚才记下的长度,只有这两个长度相同才说缓冲区足够大。

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地址 #define IFNAMSIZ 16
struct ifreq {
#define IFHWADDRLEN 6 //6个字节的硬件地址,即MAC
union {
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;//设备协议设置

  使用SIOCGIFCONF前ifconf结构的初始化结果

  SIOCGIFCONF返回值

接口操作

  SIOCGIFCONF请求为每个已配置的接口返回其名字以及一个套接字地址结构。这些请求(get)版本(SIOCGxxx)由netstat程序发出。设置(set)版本(SIOCSxxx)由ifconfig发出。这些请求接受或返回一个ifreq结构中的信息。而这个结构的地址则作为ioctl调用的第三个参数指定。接口总是以其名字标识,在ifreq结构中的ifr_name指定,如;le0、lo0。

相关数据结构

ARP高速缓存

/*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[];//查询网络接口的名称
};
#define ATF_INUSE 0x01 //entry in use
#define ATF_COM 0x02//completed entry (hardware addr valid)
#define ATF_PERM 0x04//permanent entry
#define ATF_PUBL 0x08/published entry(respond for other host)

路有表操作

  ioctl没有办法列出路有表中所有表项。这个操作通常有netstat程序在指定-r标志时完成。

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

获取网络接口信息

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <linux/if.h>
#include <arpa/inet.h>
#include <linux/sockios.h>
/**
ioctl函数是与内核交互的一种方法,使用ioctl函数与内核协议栈进行交互
ioctl函数可操作I/O请求,文件请求与网络接口请求
网络接口请求的几个结构体:
struct ifreq{
#define IFHWADDRLEN 6 //6个字节的硬件地址,即MAC
union{
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;//DMA
unsigned 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,);
if(s<){
perror("socket error");
return;
} //传入网络接口序号,获得网络接口的名称
struct ifreq ifr; ifr.ifr_ifindex=;//获得第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",);
err=ioctl(s,SIOCGIFFLAGS,&ifr);
if(!err)
printf("SIOCGIFFLAGS:%d\n",ifr.ifr_flags); //获得MTU和MAC
err=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[],hw[],hw[],hw[],hw[],hw[]);
} //获得网卡映射参数 命令字SIOCGIFMAP
err=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); //获取网络接口IP struct sockaddr_in *sin=(struct sockaddr_in*)&ifr.ifr_addr;//保存的是二进制IP
char ip[];//字符数组,存放字符串
memset(ip,,);
err=ioctl(s,SIOCGIFADDR,&ifr);
if(!err){
inet_ntop(AF_INET,&sin->sin_addr.s_addr,ip,);//转换的字符串保存到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,);
printf("SIOCGIFDSTADDR:%s\n",ip);
} //查询子网掩码
err=ioctl(s,SIOCGIFNETMASK,&ifr);
if(!err){
inet_ntop(AF_INET,&sin->sin_addr.s_addr,ip,);
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,,sizeof(ifr));
memcpy(ifr.ifr_name,"eth0",);
ioctl(s,SIOCGIFADDR,&ifr);
inet_ntop(AF_INET,&sin->sin_addr.s_addr,ip,);
printf("%s\n",ip);
} //得到接口的广播地址
memset(&ifr,,sizeof(ifr));
memcpy(ifr.ifr_name,"eth0",);
ioctl(s,SIOCGIFBRDADDR,&ifr);
struct sockaddr_in *broadcast=(struct sockaddr_in*)&ifr.ifr_broadaddr;
//转换成字符串
inet_ntop(AF_INET,&broadcast->sin_addr.s_addr,ip,);//inet_ntop将二进制IP转换成点分十进制的字符串
printf("BROADCAST IP:%s\n",ip);
close(s);
}

查看arp高速缓存信息

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if_arp.h>
#include <string.h>
#include <stdlib.h>
#include <linux/sockios.h>
/**
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,);
if(s<)
perror("socket error"); addr->sin_family=AF_INET;
addr->sin_addr.s_addr=inet_addr(argv[]);//转换成二进制IP
if(addr->sin_addr.s_addr==INADDR_NONE)
printf("IP地址格式错误\n"); strcpy(arpreq.arp_dev,"eth0");
err=ioctl(s,SIOCGARP,&arpreq);
if(err==-){
perror("arp");
return -;
} unsigned char* hw=(unsigned char*)&arpreq.arp_ha.sa_data;//硬件地址
printf("%s\n",argv[]);
printf("%02x:%02x:%02x:%02x:%02x:%02x\n",hw[],hw[],hw[],hw[],hw[],hw[]);
close(s);
return ;
}

  查看网关的MAC。在查看ARP高速缓存时要传入IP地址与接口信息。而获得接口信息要传入接口名ifr_name,如eth0。

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

ioctl操作的更多相关文章

  1. Oracle 11gR2 11.2.0.1 ( 11.2.0.1的BUG?):ohasd不能正常启动:ioctl操作:npohasd的问题:【chmod a+wr /var/tmp/.oracle/npohasd】

    问题1:执行安装,编译成功后,执行asmca时,失败,无法成功创建后台相关服务 问题2:os系统重启后,ohasd无法正常启动,css服务失败 原因:11.2.0.1的BUG:/var/tmp/.or ...

  2. UNIX网络编程--ioctl操作(十七)

    一.概述 在本书中有两个地方都对这个函数进行了介绍,其实还有很多地方需要这个函数.ioclt函数传统上一直作为纳西而不适合归入其他精细定义类别的特性的系统接口.网络程序(特别是服务器程序)经常在程序启 ...

  3. linux 高级字符设备驱动 ioctl操作介绍 例程分析实现【转】

    转自:http://my.oschina.net/u/274829/blog/285014 1,ioctl介绍 ioctl控制设备读写数据以及关闭等. 用户空间函数原型:int ioctl(int f ...

  4. UNP学习笔记(第十七章 ioctl操作)

    ioctl相当于一个杂物箱,它一直作为那些不适合归入其他精细定义类别的特性的系统接口. 本章笔记先放着,到时候有需要再看 ioctl函数 #include <unistd.h> int i ...

  5. 《网络编程》ioctl 操作

    概要 ioctl 功能与 fcntl 功能类似,它可以被用于描述操作的叙述字符,获取或设置属性的描述是开放式的叙事休息,但在网络编程的两个功能有关的不同类型的操作.fcntl 作.文件操作,而 ioc ...

  6. UNP学习 ioctl操作

    一.ioctl函数 #include <unistd.h> int ioctl(int fd, int request, ... /* void * arg */); 返回:成功0,出错- ...

  7. (十五)ioctl、ifreq、ifconf

    ioctl操作   传统上ioctl函数是用于那些普遍使用,但不适合归入其他类别的任何特性的系统接 口.Posix去掉了ioctl,它通过 创建特殊的其功能已被Posix标准化的包裹函数来代替ioct ...

  8. ioctl用法详解 (网络)

    本函数影响由fd参数引用的一个打开的文件. #include#include int ioctl( int fd, int request, .../* void *arg */ );返回0:成功   ...

  9. ioctl函数详细说明

    本函数影响由fd 参数引用的一个打开的文件. #include<unistd.h> int ioctl( int fd, int request, .../* void *arg */ ) ...

随机推荐

  1. CodeForces - 1243D (思维+并查集)

    题意 https://vjudge.net/problem/CodeForces-1243D 有一张完全图,n个节点 有m条边的边权为1,其余的都为0 这m条边会给你 问你这张图的最小生成树的权值 思 ...

  2. github.com/pkg/errors库学习

    为了理解go error,进一步学习github.com/pkg/errors作的训练. http://www.shtml.net/article/content/tok/48369/id/37733 ...

  3. Xposed优缺点和入门

    Xposed框架的原理是替换安卓系统/System/bin目录下的文件,从而实现对系统某些功能的替换,进而给予基于 Xposed 框架开发的App更多权限. 优点:1.功能强大2.执行效率快缺点:1. ...

  4. java自定义函数调用

    一:主类中自定义函数 在主类中,如果想要在main函数中调用自定义的其他方法,则这个函数需要使用static关键字定义,否则会报错Cannot make a static reference to t ...

  5. 超实用的Java web面试题

    Java web面试题 1.Tomcat的优化经验 答:去掉对web.xml的监视,把jsp提前编辑成Servlet. 有富余物理内存的情况,加大tomcat使用的jvm的内存 2.HTTP请求的GE ...

  6. SpringBatch介绍

    SpringBatch 是一个大数据量的并行处理框架.通常用于数据的离线迁移,和数据处理,⽀持事务.并发.流程.监控.纵向和横向扩展,提供统⼀的接⼝管理和任务管理;SpringBatch是Spring ...

  7. 部署Springboot项目到Linux云服务器

    前言 环境:IDEA.Springboot.Maven(自己电脑安装的Maven) 一.打包jar包 检查自己的pom.xml文件下面有无Maven的依赖插件,即有无如下: <build> ...

  8. 基于Django的Rest Framework框架的url控制器

    本文目录 一 自定义路由(原始方式) 二 半自动路由(视图类继承ModelViewSet) 三 全自动路由(自动生成路由) 回到目录 一 自定义路由(原始方式) from django.conf.ur ...

  9. SpringMVC方法的返回值类型和自动装配

    1. void类型作为返回值类型 /** * 如果方法写成了void就跟原来servlet含义是差不多 的 * json */ @RequestMapping("/firstRequest& ...

  10. Vue ---- 组件文件分析 组件生命周期钩子 路由 跳转 传参

    目录 Vue组件文件微微细剖 Vue组件生命周期钩子 Vue路由 1.touter下的index.js 2.路由重定向 3.路由传参数 补充:全局样式导入 路由跳转 1. router-view标签 ...