ioctl函数详细说明(网络)
ioctl 函数
本函数影响由fd 参数引用的一个打开的文件。
#include<unistd.h>
int ioctl( int fd, int request, .../* void *arg */ );
返回0 :成功 -1 :出错
第三个参数总是一个指针,但指针的类型依赖于request 参数。
我们可以把和网络相关的请求划分为6 类:
套接口操作
文件操作
接口操作
ARP 高速缓存操作
路由表操作
流系统
下表列出了网络相关ioctl 请求的request 参数以及arg 地址必须指向的数据类型:
|
类别 |
Request |
说明 |
数据类型 |
|
套 接 口 |
SIOCATMARK SIOCSPGRP SIOCGPGRP |
是否位于带外标记 设置套接口的进程ID 或进程组ID 获取套接口的进程ID 或进程组ID |
int int int |
|
文 件 |
FIONBIN FIOASYNC FIONREAD FIOSETOWN FIOGETOWN |
设置/ 清除非阻塞I/O 标志 设置/ 清除信号驱动异步I/O 标志 获取接收缓存区中的字节数 设置文件的进程ID 或进程组ID 获取文件的进程ID 或进程组ID |
int 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 |
|
ARP |
SIOCSARP SIOCGARP SIOCDARP |
创建/ 修改ARP 表项 获取ARP 表项 删除ARP 表项 |
struct arpreq struct arpreq struct arpreq |
|
路 由 |
SIOCADDRT SIOCDELRT |
增加路径 删除路径 |
struct rtentry struct 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->kernel
struct 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 16
struct 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 结构。
|
ifc_len |
|
Ifc_buf |
1024
---------------------> 缓存
假设内核返回2 个ifreq 结构,ioctl 返回时通过同一个ifconf 结构缓冲区填入了那2 个ifreq 结构,ifconf 结构的ifc_len 成员也被更新,以反映存放在缓冲区中的信息量
• 改变路由表 (例如 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)
实例:
程序1:检测接口的 .net_addr,netmask,broad_addr
程序2:检查接口的物理连接是否正常
程序3:更简单一点测试物理连接
程序4:调节音量
***************************程序1****************************************
#include <stdio.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();
else
name = argv[1]; 内容来自ltesting.net
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, SIOCGMIIPHY, &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, 领测软件测试网http://www.ltesting.net
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];
else
ifname = "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 0x0000000a
struct linktest_value {
unsigned int cmd;
unsigned int data;
};
static
void
usage(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);
}
static
int
linktest(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) { ltesting.net
fprintf(stdout, "link detected on %s\n", devname);
return 0;
} else {
errno=ENONET;
}
}
perror("linktest");
return errno;
}
int
main(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 257
int 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");
}else
printf("can't open /dev/mixer error....\n"); ltesting.net
exit(0);
}
ioctl函数详细说明(网络)的更多相关文章
- ioctl函数详细说明
本函数影响由fd 参数引用的一个打开的文件. #include<unistd.h> int ioctl( int fd, int request, .../* void *arg */ ) ...
- (十)Linux 网络编程之ioctl函数
1.介绍 Linux网络程序与内核交互的方法是通过ioctl来实现的,ioctl与网络协议栈进行交互,可得到网络接口的信息,网卡设备的映射属性和配置网络接口.并且还能够查看,修改,删除ARP高速缓存的 ...
- UNIX网络编程——ioctl 函数的用法详解
1.介绍 Linux网络程序与内核交互的方法是通过ioctl来实现的,ioctl与网络协议栈进行交互,可得到网络接口的信息,网卡设备的映射属性和配置网络接口.并且还能够查看,修改,删除ARP高速缓存的 ...
- 获取网络接口信息——ioctl()函数与结构体struct ifreq、 struct ifconf
转载请注明出处:windeal专栏 Linux 下 可以使用ioctl()函数 以及 结构体 struct ifreq 结构体struct ifconf来获取网络接口的各种信息. ioctl 首先看 ...
- ioctl函数用法小记
By francis_hao Aug 27,2017 UNPV1对ioctl有算是比较详细的介绍,但是,这些request和后面的数据类型是从哪里来的,以及参数具体该如何使用呢?本文尝试在不 ...
- 通用js函数集锦<来源于网络/自己> 【一】
通用js函数集锦<来源于网络/自己>[一] 1.返回一个全地址2.cookie3.验证用户浏览器是否是微信浏览器4.验证用户浏览器是否是微博内置浏览器5.query string6.验证用 ...
- Linux系统编程(4)——文件与IO之ioctl函数
ioctl是设备驱动程序中对设备的I/O通道进行管理的函数.所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率.马达的转速等等.它的参数个数如下:int ioctl(int ...
- ioctl函数
一.函数原型 #include <unistd.h> int ioctl(int fd, int request, .../* void *arg */); 二.和网络相关的请求(requ ...
- (笔记)Linux下的ioctl()函数详解
我这里说的ioctl函数是指驱动程序里的,因为我不知道还有没有别的场合用到了它,所以就规定了我们讨论的范围.写这篇文章是因为我前一阵子被ioctl给搞混了,这几天才弄明白它,于是在这里清理一下头脑. ...
随机推荐
- WPF和js交互 WebBrowser数据交互
this.webBrowser1.ObjectForScripting = new OprateBasic(); this.webBrowser1.Source = new Uri(Environme ...
- Beta冲刺——day4
Beta冲刺--day4 作业链接 Beta冲刺随笔集 github地址 团队成员 031602636 许舒玲(队长) 031602237 吴杰婷 031602220 雷博浩 031602134 王龙 ...
- centos 7 安装搜狗输入法
1.安装alien依赖软件sudo yum install alien -y 2.安装依赖软件sudo yum install qtwebkit -ysudo yum install fcitx -y ...
- css文本垂直居中
1,一般flexca 2,行高 3,行高加边框或者透明边框
- Java_按位与&,按位或,取反,左移,右移运算符
//按位与运算& System.out.println(0&0);//0 System.out.println(0&1);//0 System.out.println(1&am ...
- 【题解】 bzoj2435: [Noi2011]道路修建 (傻逼题)
bzoj2435,懒得复制,戳我戳我 Solution: 模拟即可(有点傻逼啊 Code: //It is coded by Ning_Mew on 5.13 #include<bits/std ...
- 【Revit API】FamilyInstance、FamilySymbol、Family的寻找关系
话不多说,做个笔记 FamilyInstance instance; var typeid = instance.GetTypeId(); var symbol = RevitDoc.GetEleme ...
- BZOJ 4380 [POI2015]Myjnie | DP
链接 BZOJ 4380 题面 有n家洗车店从左往右排成一排,每家店都有一个正整数价格p[i]. 有m个人要来消费,第i个人会驶过第a[i]个开始一直到第b[i]个洗车店,且会选择这些店中最便宜的一个 ...
- What is SCons?
SCons: A software construction tool What is SCons? SCons is an Open Source software construction too ...
- 解题:SPOJ 3734 Periodni
题面 按列高建立笛卡尔树,转成树上问题...... 笛卡尔树是什么? 它一般是针对序列建立的,是下标的BST和权值的堆(即中序遍历是原序列连续区间,节点权值满足堆性质),这里不讲具体怎么建树(放在知识 ...