使用socket+ioctl。
舉例如下:
#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>
#include <linux/ethtool.h>
#include <linux/sockios.h>
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned char u8;
/* 獲取MII phy的地址 然後讀取phy寄存器的值*/
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; /* ifreq裏包含了接口的所有信息,比如接口名,地址等等 */
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 CheckNet()
{
int skfd = -1;
/* 如果這裏所填的名字沒有對應的phy(比如phy2),則會報錯No such device */
char *ifname = "eth0";
int retval;
/* Open a socket. */
if (( skfd = socket( AF_INET, SOCK_DGRAM, 0 ) ) < 0 )
{
printf("socket error\n");
exit(-1);
}
/* 這裏使用兩種方式來獲取網卡的狀態 */
retval = detect_ethtool(skfd, ifname); /* 使用SIOCETHTOOL方式獲取 */
if (retval == 2)
{
retval = detect_mii(skfd, ifname); /*使用SIOCGMIIPHY方式獲取,即先獲取指定phy的地址,然後讀指定的寄存器*/
}
close(skfd);
return retval;
}
//int main(int argc, char **argv)
int phyOperate(void* arg)
{
int ret = -1,retold = -1;
while(1)
{
ret = CheckNet();
/*如果狀態發生變化纔打印*/
if(ret != retold)
{
retold = ret;
if (ret == 2)
printf("Could not determine status\n");
if (ret == 1)
printf("Link down %s pid = %d\n",(char*)arg,getpid());
if (ret == 0)
printf("Link up %s pid = %d\n",(char*)arg,getpid());
}
}
}
/*多個線程檢測網卡狀態*/
int main()
{
int i = 0;
pthread_t thread1,thread2,thread3,thread4;
pthread_create(&thread1,NULL,phyOperate,"thread1");
pthread_create(&thread2,NULL,phyOperate,"thread2");
pthread_create(&thread3,NULL,phyOperate,"thread3");
//pthread_create(&thread4,NULL,phyOperate,"thread4");
/*不加下面的話線程會結束*/
pthread_join(thread1,"thread1");
pthread_join(thread2,"thread2");
pthread_join(thread3,"thread3");
//pthread_join(thread4,"thread4");
}