linux系统ioctl函数使用实例注释版


原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://idear.blog.51cto.com/4097017/853582
源代码来源:http://www.linuxidc.com/Linux/2007-12/9623p2.htm
由于源代码注释几乎没有,可能新手较难看懂。因此鄙人加上了注释,有些小错误的地方也改了一下,其它不多说了。
程序1:检测接口的 inet_addr,netmask,broad_addr
程序2:检查接口的物理连接是否正常
程序3:更简单一点测试物理连接
程序4:调节音量

程序1:检测接口的 inet_addr,netmask,broad_addr

可能用到的资料:
1.ioctl和struct ifreq
http://wenku.baidu.com/view/59f4508d680203d8ce2f2412.html
上面链接中的源代码,头文件需要自己修改一下

//程序1:检测接口的 inet_addr,netmask,broad_addr 
#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; //用于ioctl 
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) //用 SIOCGIFADDR 来获得接口地址 
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) //用 SIOCGIFBRDADDR 来获得广播地址 
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) //用 SIOCGIFNETMASK 来获得掩码地址 
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:检查接口的物理连接是否正常
//程序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); 

//MII=(媒介无关接口) 
//PHY=物理链路 
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; 

//REG regedit 
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; 

//ETH : EtherNet n. 以太网O 
/\tOOL 工具 
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"; //默认值 

//打开一个套接子 
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:更简单一点测试物理连接
//程序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);//为什么没有用strncpy了 

//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]); 
} 




程序4:调节音量
可能用到的资料:
Linux的混音设备/dev/mixer
http://blog.163.com/ji_wei8888/blog/static/48680446201110925825588/
//程序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; 

//检查参数 
if (argc<3) 
{ 
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"); 
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"); 
exit(0); 
} 




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值