linux ioctl函数详解,ioctl函数详解「建议收藏」

linux ioctl函数详解,ioctl函数详解「建议收藏」1.介绍Linux网络程序与内核交互的方法是通过ioctl来实现的,ioctl与网络协议栈进行交互,可得到网络接口的信息,网卡设备的映射属性和配置网络接口.并且还能够查看,修改,删除ARP高速缓存的信息,所以,我们有必要了解一下ioctl函数的具体实现.2.相关结构体与相关函数#includeintioctl(intd,intrequest,….);参数:d-文件描述符,这里是对网络套…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

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高速缓存的操作分别给出了实例

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/180663.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 各种关闭eslint方法总结[通俗易懂]

    各种关闭eslint方法总结[通俗易懂]1、package.json关闭eslint直接注释掉package.json文件中eslint的配置”eslintConfig”:{“root”:true,////此项是用来告诉eslint找当前配置文件不能往父级查找”env”:{“node”:true//此项指定环境的全局变量,下面的配置指定为node环境},”extends”:[//此项是用来配置vue.js风格,就是说写代码的时候要规范的写,如果你使用vs-code我

    2022年6月14日
    127
  • c语言findwindow函数_findwindow函数

    c语言findwindow函数_findwindow函数转自:http://blog.csdn.net/coolszy/article/details/5523486[DllImport(“User32.dll”,EntryPoint=”FindWindow”)]句柄,是整个Windows编程的基础。一个句柄是指使用的一个唯一的整数值,即一个4字节(64位程序中为8字节)长的数值,来标识应用程序中的不同对象和同类中的不同的指针,程序不能利用句柄来…

    2022年8月13日
    16
  • java中获取绝对值的方法_Java完美判断绝对值的两种方法 | 彬菌「建议收藏」

    版权声明:转载原创文章请以超链接形式请注明原文章出处,尊重作者,尊重原创!恰饭广告if-else语句判断:importjava.util.Scanner;publicclassAbsoluteValue{publicstaticvoidmain(String[]args){Scannerinput=newScanner(System.in);//声明扫描仪变量System.ou…

    2022年4月15日
    144
  • 4G LTE Advanced_LTE百科

    4G LTE Advanced_LTE百科IS-95   IS-95是由高通公司发起的第一个基于CDMA数字蜂窝标准。IS全称为InterimStandard,即暂时标准,基于IS-95的第一个品牌是cdmaOne。IS-95也叫TIA-EIA-95。它是一个使用CDMA的2G移动通信标准,一个数据无线电多接入方案,其用来发送声音,数据和在无线电话和蜂窝站点间发信号数据(如被拨电话号码)。IS-95及其相关标准是最早商用的

    2022年10月4日
    4
  • uniapp打包ios真机测试_苹果手机没有app可供测试

    uniapp打包ios真机测试_苹果手机没有app可供测试这里说的是数据线链接首先要给电脑上安装一个手机驱动我用的是360助手(链接如下:)http://sj.360.cn/index.html先测试手机和电脑是否能连接成功然后再HBuilderX中点击运行到手机模拟器就可以了,注意:连接手机的时候会提示手机也需要下载360手机助手(按照提示下载即可),手机上会自动安装一个HBuilder,点击进去就是自己的app手机连接的时候要选中usb调试模式…

    2025年9月23日
    10
  • 网易视频 java_合并网易视频中英文字幕文件,解决Java输入输出的中文乱码问题…「建议收藏」

    网易视频 java_合并网易视频中英文字幕文件,解决Java输入输出的中文乱码问题…「建议收藏」packagehebingsrt;importjava.io.BufferedReader;importjava.io.BufferedWriter;importjava.io.File;importjava.io.FileInputStream;importjava.io.FileOutputStream;importjava.io.FileReader;importjava.i…

    2022年7月11日
    24

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号