linux檢測網線插拔狀態


http://blog.csdn.net/ufo714/article/details/8889759

Shell查看網線插拔狀態:

使用ifconfig命令,如果含有“RUNNING”,說明網線接入,否則就沒有。

例:

ifconfig

ifconfig eth0

ifconfig eth0|grep "RUNNING"

================================================================================================

C編程查看網線插拔狀態:

轉自:http://blog.csdn.net/alex_xhl/article/details/8584998

 

參考網絡資料,經整理驗證ok.

  1. #include <sys/socket.h>  
  2.   
  3. #include <sys/ioctl.h>  
  4. #include <linux/if.h>  
  5. #include <string.h>  
  6. #include <stdio.h>  
  7.   
  8. int net_detect(char* net_name)  
  9. {  
  10.     int skfd = 0;  
  11.     struct ifreq ifr;  
  12.     struct sockaddr_in *pAddr = NULL;  
  13.     skfd = socket(AF_INET, SOCK_DGRAM, 0);  
  14.     if(skfd < 0)  
  15.     {  
  16.         printf("%s:%d Open socket error!\n", __FILE__, __LINE__);  
  17.         return -1;  
  18.     }  
  19.     strcpy(ifr.ifr_name, net_name);  
  20.     if(ioctl(skfd, SIOCGIFFLAGS, &ifr) <0 )  
  21.     {  
  22.         printf("%s:%d IOCTL error!\n", __FILE__, __LINE__);  
  23.         printf("Maybe ethernet inferface %s is not valid!", ifr.ifr_name);  
  24.         close(skfd);  
  25.         return -1;  
  26.     }  
  27.     if(ifr.ifr_flags & IFF_RUNNING)  
  28.     {  
  29.         printf("%s is running :)\n", ifr.ifr_name);  
  30.     }  
  31.     else  
  32.     {  
  33.         printf("%s is not running :(\n", ifr.ifr_name);  
  34.     }  
  35.     if(ioctl(skfd,SIOCGIFADDR,&ifr)<0)  
  36.     {  
  37.         printf("SIOCGIFADDR IOCTL error!\n");  
  38.         close(skfd);  
  39.         return -1;  
  40.     }  
  41.     pAddr = (struct sockaddr_in *)&(ifr.ifr_addr);  
  42.     printf("ip addr :[%s]\n", inet_ntoa(pAddr->sin_addr));  
  43.     if(ioctl(skfd,SIOCGIFHWADDR,&ifr)<0)  
  44.     {  
  45.         printf("SIOCGIFHWADDR IOCTL error!\n");  
  46.         close(skfd);  
  47.         return -1;  
  48.     }  
  49.     printf("mac addr: %02x:%02x:%02x:%02x:%02x:%02x\n",  
  50.         (unsigned char)ifr.ifr_hwaddr.sa_data[0],  
  51.         (unsigned char)ifr.ifr_hwaddr.sa_data[1],  
  52.         (unsigned char)ifr.ifr_hwaddr.sa_data[2],  
  53.         (unsigned char)ifr.ifr_hwaddr.sa_data[3],  
  54.         (unsigned char)ifr.ifr_hwaddr.sa_data[4],  
  55.         (unsigned char)ifr.ifr_hwaddr.sa_data[5]);  
  56.     close(skfd);  
  57.     return 0;  
  58. }  
  59.   
  60. void main()  
  61. {  
  62.     net_detect("eth0");  
  63.   
  64. }  




參考網絡資料:

1、對於基於linux2.4內核的uclinux系統如何實現在應用層監控網線插拔狀態?

2、硬件環境:IPS100ARM7TDMI

3、實現過程

由於linux下的ifconfig命令就能夠實現在應用層監控網線插拔狀態,例如當網線連接正常時,使用ifconfig eth0命令,打印的信息中會有RUNNING,而拔掉網線后,再使用ifconfig eth0命令,RUNNING就不見了。所以,實現Linux應用層監控網線插入狀態就相當於自己寫一個ifconfig函數。

基於這個思路,首先參考ifconfig的源碼,可以參考linux自身提供的ifconfig的源碼(linux提供的有ifconfig.c函數),也可以在網上查找。首先找到linux自身提供的ifconfig.c函數,既然ifconfig通過RUNNING來判斷網絡的通斷的狀況的,首先找到RUNNING的出處,搜索一下發現這句話,

If(ptr->flags &IFF_RUNNIG)

{

Printf(__("RUNNING"));

}

以這個為切入點,層層向上找,分別是被些函數調用,最后我們進入了main函數(這是理所當然的),在這里的到RUNNING→ife_print()→if_pirint()→main().。先看ife_prinf()函數,這里沒有和內核通信,這時我們再看if_print()函數,這里剛好有和內核通信的函數,else {                       
        struct interface *ife;

        ife = lookup_interface(ifname);
        res = do_if_fetch(ife);
        if (res >= 0)
            ife_print(ife);
    }

    這時需要看到lookup_interface(ifname)和do_if_fetch(ife)的原型,由於頭文件很多,我沒辦法知道這兩個函數在那個頭文件中,所以干脆在網上找到這兩個函數的原型,我們找到了一篇ifconfing源碼分析的文章,http://viscar.blog.sohu.com/2574772.html,這里面找到了函數原型,我們看到 do_if_fetch()函數里面又調用了if_fetch()函數,太好了,這個函數正是我們所需要的,在這里面有個很重要的函數ioctl(),ioctl用於向設備發送控制和配置命令,驅動程序可以接收ioctl的數據,並返回數據,ioctl的原型為

    ioctl(int d, int cmd, ......),

d是某個設備的文件描述符,cmdioctl的命令,可變參數取決於cmd,是指向變量或結構體的指針。

這里面用到的設備文件描述符skfd = socketAF_INET,SOCK_DGRAM,0);這是一個套接字,作用是打開一個網絡通訊端口,成功的話返回skfd,相當於一個文件描述符。

   有了這些之后我們就可以寫一個自己的簡潔版的ifconfig函數了,現在ubuntu10.04上編寫代碼,代碼里面的ioctl函數這樣寫ioctl(skfd, SIOCGIFFLAGS, &ifr) ,其中SIOCGIGGLAGS表示得到sock i/oflags,這時因為,RUNNIGN的條件是ptr->flags &IFF_RUNNING 是否為真,代碼里面直接體現eth0,函數為strcpy(ifr.ifr_name, “eth0”);完整的代碼如下:
(以下代碼在ubuntu 10.04下運行通過)

  1. #include "icconst.h"  
  2. #include <sys/socket.h>  
  3. #include <sys/ioctl.h>  
  4. #include <linux/if.h>  
  5. #include <string.h>  
  6. #include <stdio.h>  
  7. #include "net_detect.h"  
  8.   
  9. int net_detect(char* net_name)  
  10. {  
  11. int skfd = 0;  
  12. struct ifreq ifr;   
  13. skfd = socket(AF_INET, SOCK_DGRAM, 0);  
  14.   
  15. if(skfd < 0)  
  16. {  
  17. printf("%s:%d Open socket error!\n", __FILE__, __LINE__);  
  18. return -1;  
  19. }  
  20.   
  21. strcpy(ifr.ifr_name, net_name);  
  22.   
  23. if(ioctl(skfd, SIOCGIFFLAGS, &ifr) <0 )  
  24. {  
  25. printf("%s:%d IOCTL error!\n", __FILE__, __LINE__);  
  26. printf("Maybe ethernet inferface %s is not valid!", ifr.ifr_name);  
  27. close(skfd);  
  28. return -1;  
  29. }  
  30.   
  31. if(ifr.ifr_flags & IFF_RUNNING)  
  32. {  
  1. printf("%s is running :)\n", ifr.ifr_name);  
  2. }  
  3. else  
  4. {  
  5. printf("%s is not running :(\n", ifr.ifr_name);  
  6. }  
  7.   
  8. /*****************以下為識別ip地址,mac地址***************************************/  
  9. if(ioctl(skfd,SIOCGIFADDR,&ifr)<0)  
  10. {  
  11.   printf("SIOCGIFADDR IOCTL error!\n");  
  12.   close(skfd);  
  13.   return -1;  
  14. }  
  1. printf("ip addr :[%s]\n",inet_ntoa(((struct sockaddr_in*)&(ifr.ifr_addr))->sin_addr));  
  1. if(ioctl(skfd,SIOCGIFHWADDR,&ifr)<0)  
  2. {  
  3.    printf("SIOCGIFHWADDR IOCTL error!\n");  
  4.   close(skfd);  
  5.   return -1;  
  6. }  
  7.   
  8. printf("mac addr: %02x:%02x:%02x:%02x:%02x:%02x\n"  
  9.     (unsigned char)ifr.ifr_hwaddr.sa_data[0],  
  10.     (unsigned char)ifr.ifr_hwaddr.sa_data[1],  
  11.     (unsigned char)ifr.ifr_hwaddr.sa_data[2],  
  12.     (unsigned char)ifr.ifr_hwaddr.sa_data[3],  
  13.     (unsigned char)ifr.ifr_hwaddr.sa_data[4],  
  14.     (unsigned char)ifr.ifr_hwaddr.sa_data[5]  );  
  15.   
  16. /*************************************************************************************************************************************/  
  17.   
  18. close(skfd);  
  19.   
  20. return 0;  
  21. }  


 

代碼里面的struct ifreq 是一個設備請求的結構體,在<linux/if.h>中定義,SIOCGIFFLAGS使用了ifreq結構,

  在ubuntu10.04環境下編譯之后,運行#./a.out eth0  即可實現網線插拔的監控。

這時把代碼加到uclinux下運行,發現並不能實現ubuntu的效果,這是為什么呢?

初步分析原因,可能是在驅動程序中沒有將插拔狀態的信息通知內核,所以我們使用ioctl實際上不能獲得內核網絡設備的狀態的信息。我們在《linux設備驅動程序這本書上》看到有兩個函數剛好做這件事情:

Void netif_carrier_off(struct net_device*dev);

Void netif_carrier_on(struct net_device*dev);

當驅動檢測到設備沒有連接好,可以調用netif_carrier_off通知內核這一事情;當設備再次連接好時,調用netif_carrier_on通知內核現在連接好了。

現在我們將這兩個函數分別加到驅動程序中,放到監控網線插拔狀態的位置,再在unlinux中插拔網線時,會在串口終端打印出相應的狀態信息,這時的狀態信息完全是在應用層實現的。

 

4.參考文檔:uclinux內核網絡驅動源碼和ifconfig的源碼

           《linux設備驅動程序》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM