linux检测网线插拔状态

Linux 同时被 2 个专栏收录
420 篇文章 0 订阅
184 篇文章 0 订阅

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、硬件环境: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下运行通过)

#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设备驱动程序》


 

展开阅读全文
  • 0
    点赞
  • 1
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
<p style="color:#666666;"> <span style="font-size:14px;">本门课程重实战,将基础知识拆解到项目里,让你在项目情境里学知识。</span> </p> <p style="color:#666666;"> <span style="font-size:14px;">这样的学习方式能让你保持兴趣、充满动力,时刻知道学的东西能用在哪、能怎么用。</span> </p> <p style="color:#666666;"> <span style="font-size:14px;">平时不明白的知识点,放在项目里去理解就恍然大悟了。</span> </p> <p style="color:#666666;"> <span></span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="color:#FF0000;font-size:14px;"><strong>一、融汇贯通</strong></span> </p> <p style="color:#666666;"> <span style="font-size:14px;">本视频采用了前后端分离的开发模式,前端使用Vue.js+Element UI实现了Web页面的呈现,后端使用Python 的Django框架实现了数据访问的接口,前端通过Axios访问后端接口获得数据。在学习完本章节后,真正理解前后端的各自承担的工作。</span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="color:#FF0000;font-size:14px;"><strong>二、贴近实战</strong></span> </p> <p style="color:#666666;"> <span style="font-size:14px;">本系列课程为练手项目实战:学生管理系统v4.0的开发,项目包含了如下几个内容:项目的总体介绍、基本功能的演示、Vuejs的初始化、Element UI的使用、在Django中实现针对数据的增删改查的接口、在Vuejs中实现前端增删改查的调用、实现文件的上传、实现表格的分页、实现导出数据到Excel、实现通过Excel导入数据、实现针对表格的批量化操作等等,所有的功能都通过演示完成、贴近了实战</span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="color:#FF0000;font-size:14px;"><strong>三、课程亮点</strong></span> </p> <p style="color:#666666;"> <span style="font-size:14px;">在本案例中,最大的亮点在于前后端做了分离,真正理解前后端的各自承担的工作。前端如何和后端交互</span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="color:#FF0000;font-size:14px;"><strong>适合人群:</strong></span> </p> <p style="color:#666666;"> <span style="font-size:14px;">1、有Python语言基础、web前端基础,想要深入学习Python Web框架的朋友;</span> </p> <p style="color:#666666;"> <span style="font-size:14px;">2、有Django基础,但是想学习企业级项目实战的朋友;</span> </p> <p style="color:#666666;"> <span style="font-size:14px;">3、有MySQL数据库基础的朋友</span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="font-size:14px;"><img alt="" src="https://img-bss.csdnimg.cn/202009070752197496.png" /><br /> </span> </p> <p style="color:#666666;"> <span style="font-size:14px;"><br /> </span> </p>
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值