linux icotl函数解析
来源:互联网 发布:詹姆斯2016为止总数据 编辑:程序博客网 时间:2024/05/16 16:18
ioctl函数:
网络程序(一般是服务器程序)中ioctl常用于在程序启动时获得主机上所有接口的信息: 接口的地址、接口是否支持广播、是否支持多播等等。
#include <unistd.h> or #include <sys/ioctl.h>
int ioctl(int fd, int request, …/*void *arg */);
返回:成功返回0,出错返回-1;
下表列出了网络相关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
为这个调用拥有与网络相关的代码,所以文件描述符号fd就是socket()系统调用所返回的,而command参数可以是/usr/include/linux/sockios.h头文件中的任何一个,这些个命令根据它可以解决的问题所涉及的方面被分为多种的类型.
改变路由表(SIOCADDRT, SIOCDELRT)
读取或更新ARP/RARP缓存(SIOCDARP, SIOCSRARP)
一般的和网络有关的函数(SIOCGIFNAME, SIOCSIFADDR等等)
Goodies目录中包含了很多展示ioctl用法的示例程序,看这些程序的时候,注意根据ioctl的命令类型来使用具体的调用参数结构,比如:和路由表相关的IOCTL用RTENTRY结构,rtentry结构是被定义在/usr/include/linux/route.h文件中的,和ARP相关的ioctl调用到的arpreq结构被定义在/usr/include/linux/if_arp.h文件之中。网络接口相关的ioctl命令最具有代表性的特征的是都以S或G开头,其实就是设置或得到数据,getifinfo.c程序用这些命令去读取IP地址信息,硬件地址信息,广播地址信息和与网络接口相关的标志。对于这些ioctl,第三个参数是一个ifreq结构体,这个结构体被定义在/usr/include/linux/if.h头文件中。
根据常规约定,一个用户程序调用一个特定的ioctl命令如下:
ioctl(sockid, SIOCDEVPRIVATE, (char *) &ifr);
这里ifr是一个ifreq结构体变量,它用一个和这个设备联系的接口名称来填充ifr的ifr NAME域,比如前述的无线网卡接口名称为eth1。
ifreq结构体:
/* Interface request structure used for socket ioctl's. All interface
ioctl's must have parameter definitions which begin with ifr_name.
The remainder may be interface specific. */
struct ifreq
{
# define IFHWADDRLEN 6
# define IFNAMSIZ IF_NAMESIZE
union
{
char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "en0". */
} ifr_ifrn;
union
{
struct sockaddr ifru_addr;
struct sockaddr ifru_dstaddr;
struct sockaddr ifru_broadaddr;
struct sockaddr ifru_netmask;
struct sockaddr ifru_hwaddr;
short int ifru_flags;
int ifru_ivalue;
int ifru_mtu;
struct ifmap ifru_map;
char ifru_slave[IFNAMSIZ]; /* Just fits the size */
char ifru_newname[IFNAMSIZ];
__caddr_t ifru_data;
} ifr_ifru;
};
# define ifr_name ifr_ifrn.ifrn_name /* interface name */
# define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */
# define ifr_addr ifr_ifru.ifru_addr /* address */
# define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */
# define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
# define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */
# define ifr_flags ifr_ifru.ifru_flags /* flags */
# define ifr_metric ifr_ifru.ifru_ivalue /* metric */
# define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
# define ifr_map ifr_ifru.ifru_map /* device map */
# define ifr_slave ifr_ifru.ifru_slave /* slave device */
# define ifr_data ifr_ifru.ifru_data /* for use by interface */
# define ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */
# define ifr_bandwidth ifr_ifru.ifru_ivalue /* link bandwidth */
# define ifr_qlen ifr_ifru.ifru_ivalue /* queue length */
# define ifr_newname ifr_ifru.ifru_newname /* New name */
# define _IOT_ifreq _IOT(_IOTS(char),IFNAMSIZ,_IOTS(char),16,0,0)
# define _IOT_ifreq_short _IOT(_IOTS(char),IFNAMSIZ,_IOTS(short),1,0,0)
# define _IOT_ifreq_int _IOT(_IOTS(char),IFNAMSIZ,_IOTS(int),1,0,0)
******************************************************************************************************************************************
linux系统ioctl使用示例
These were writed and collected by kf701,
you can use and modify them but NO WARRANTY.
Contact with me : kf_701@21cn.com
程序1:检测接口的inet_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];
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, 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)
{
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]);
}
- linux icotl函数解析
- linux icotl函数解析
- linux icotl函数解析
- linux icotl函数解析
- linux icotl函数解析
- linux icotl函数解析
- Linux wait函数解析
- Linux signal函数解析
- linux wait函数解析
- Linux多线程函数解析
- Linux多线程函数解析
- Linux多线程函数解析
- Linux 多线程函数解析
- Linux 多线程函数解析
- Linux 多线程函数解析
- Linux 多线程函数解析
- Linux 多线程函数解析
- Linux 多线程函数解析
- C#的office word文档的操作(1)
- Android 中显示 Gif 格式图
- 从web转向软件的感触
- Flex 批量替换字符串,方法
- C#的office文档操作(2)
- linux icotl函数解析
- 为什么需要安装USB驱动
- C#的office文档操作(3)
- Javascript 中的false、0、null、undefined和空字符串对象
- C#的office文档操作(4)
- Android中往手机自带的存储空间写入文件
- 想买房的人必看!踢爆眼下售楼小姐的新骗局
- C#的office文档操作(5)
- 天涯的总结