linux檢測網線插拔小程式

來源:互聯網
上載者:User

參考網路資料,經整理驗證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裝置驅動程式》

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.