通過socket獲取網絡卡狀態
阿新 • • 發佈:2018-12-14
#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"); }