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.
- #include <sys/socket.h>
- #include <sys/ioctl.h>
- #include <linux/if.h>
- #include <string.h>
- #include <stdio.h>
- int net_detect(char* net_name)
- {
- int skfd = 0;
- struct ifreq ifr;
- struct sockaddr_in *pAddr = NULL;
- skfd = socket(AF_INET, SOCK_DGRAM, 0);
- if(skfd < 0)
- {
- printf("%s:%d Open socket error!\n", __FILE__, __LINE__);
- return -1;
- }
- strcpy(ifr.ifr_name, net_name);
- if(ioctl(skfd, SIOCGIFFLAGS, &ifr) <0 )
- {
- printf("%s:%d IOCTL error!\n", __FILE__, __LINE__);
- printf("Maybe ethernet inferface %s is not valid!", ifr.ifr_name);
- close(skfd);
- return -1;
- }
- if(ifr.ifr_flags & IFF_RUNNING)
- {
- printf("%s is running :)\n", ifr.ifr_name);
- }
- else
- {
- printf("%s is not running :(\n", ifr.ifr_name);
- }
- if(ioctl(skfd,SIOCGIFADDR,&ifr)<0)
- {
- printf("SIOCGIFADDR IOCTL error!\n");
- close(skfd);
- return -1;
- }
- pAddr = (struct sockaddr_in *)&(ifr.ifr_addr);
- printf("ip addr :[%s]\n", inet_ntoa(pAddr->sin_addr));
- if(ioctl(skfd,SIOCGIFHWADDR,&ifr)<0)
- {
- printf("SIOCGIFHWADDR IOCTL error!\n");
- close(skfd);
- return -1;
- }
- printf("mac addr: %02x:%02x:%02x:%02x:%02x:%02x\n",
- (unsigned char)ifr.ifr_hwaddr.sa_data[0],
- (unsigned char)ifr.ifr_hwaddr.sa_data[1],
- (unsigned char)ifr.ifr_hwaddr.sa_data[2],
- (unsigned char)ifr.ifr_hwaddr.sa_data[3],
- (unsigned char)ifr.ifr_hwaddr.sa_data[4],
- (unsigned char)ifr.ifr_hwaddr.sa_data[5]);
- close(skfd);
- return 0;
- }
- void main()
- {
- net_detect("eth0");
- }
參考網絡資料:
1、對於基於linux2.4內核的uclinux系統如何實現在應用層監控網線插拔狀態?
2、硬件環境:IPS100(ARM7TDMI)
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是某個設備的文件描述符,cmd是ioctl的命令,可變參數取決於cmd,是指向變量或結構體的指針。
這里面用到的設備文件描述符skfd = socket(AF_INET,SOCK_DGRAM,0);這是一個套接字,作用是打開一個網絡通訊端口,成功的話返回skfd,相當於一個文件描述符。
有了這些之后我們就可以寫一個自己的簡潔版的ifconfig函數了,現在ubuntu10.04上編寫代碼,代碼里面的ioctl函數這樣寫ioctl(skfd, SIOCGIFFLAGS, &ifr) ,其中SIOCGIGGLAGS表示得到sock i/o的flags,這時因為,RUNNIGN的條件是ptr->flags &IFF_RUNNING 是否為真,代碼里面直接體現eth0,函數為strcpy(ifr.ifr_name, “eth0”);完整的代碼如下:
(以下代碼在ubuntu 10.04下運行通過)
- #include "icconst.h"
- #include <sys/socket.h>
- #include <sys/ioctl.h>
- #include <linux/if.h>
- #include <string.h>
- #include <stdio.h>
- #include "net_detect.h"
- int net_detect(char* net_name)
- {
- int skfd = 0;
- struct ifreq ifr;
- skfd = socket(AF_INET, SOCK_DGRAM, 0);
- if(skfd < 0)
- {
- printf("%s:%d Open socket error!\n", __FILE__, __LINE__);
- return -1;
- }
- strcpy(ifr.ifr_name, net_name);
- if(ioctl(skfd, SIOCGIFFLAGS, &ifr) <0 )
- {
- printf("%s:%d IOCTL error!\n", __FILE__, __LINE__);
- printf("Maybe ethernet inferface %s is not valid!", ifr.ifr_name);
- close(skfd);
- return -1;
- }
- if(ifr.ifr_flags & IFF_RUNNING)
- {
- printf("%s is running :)\n", ifr.ifr_name);
- }
- else
- {
- printf("%s is not running :(\n", ifr.ifr_name);
- }
- /*****************以下為識別ip地址,mac地址***************************************/
- if(ioctl(skfd,SIOCGIFADDR,&ifr)<0)
- {
- printf("SIOCGIFADDR IOCTL error!\n");
- close(skfd);
- return -1;
- }
- printf("ip addr :[%s]\n",inet_ntoa(((struct sockaddr_in*)&(ifr.ifr_addr))->sin_addr));
- if(ioctl(skfd,SIOCGIFHWADDR,&ifr)<0)
- {
- printf("SIOCGIFHWADDR IOCTL error!\n");
- close(skfd);
- return -1;
- }
- printf("mac addr: %02x:%02x:%02x:%02x:%02x:%02x\n"
- (unsigned char)ifr.ifr_hwaddr.sa_data[0],
- (unsigned char)ifr.ifr_hwaddr.sa_data[1],
- (unsigned char)ifr.ifr_hwaddr.sa_data[2],
- (unsigned char)ifr.ifr_hwaddr.sa_data[3],
- (unsigned char)ifr.ifr_hwaddr.sa_data[4],
- (unsigned char)ifr.ifr_hwaddr.sa_data[5] );
- /*************************************************************************************************************************************/
- close(skfd);
- return 0;
- }
代碼里面的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設備驅動程序》