Shell查看网线插拔状态:
使用ifconfig命令,如果含有“RUNNING”,说明网线接入,否则就没有。
ifconfig
ifconfig eth0
ifconfig eth0|grep "RUNNING"
================================================================================================
C编程查看网线插拔状态:
参考网络资料,经整理验证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. "%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. "%s:%d IOCTL error!\n", __FILE__, __LINE__);
23. "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. "%s is running :)\n", ifr.ifr_name);
30. }
31. else
32. {
33. "%s is not running :(\n", ifr.ifr_name);
34. }
35. if(ioctl(skfd,SIOCGIFADDR,&ifr)<0)
36. {
37. "SIOCGIFADDR IOCTL error!\n");
38. close(skfd);
39. return -1;
40. }
41. struct sockaddr_in *)&(ifr.ifr_addr);
42. "ip addr :[%s]\n", inet_ntoa(pAddr->sin_addr));
43. if(ioctl(skfd,SIOCGIFHWADDR,&ifr)<0)
44. {
45. "SIOCGIFHWADDR IOCTL error!\n");
46. close(skfd);
47. return -1;
48. }
49. "mac addr: %02x:%02x:%02x:%02x:%02x:%02x\n",
50. char)ifr.ifr_hwaddr.sa_data[0],
51. char)ifr.ifr_hwaddr.sa_data[1],
52. char)ifr.ifr_hwaddr.sa_data[2],
53. char)ifr.ifr_hwaddr.sa_data[3],
54. char)ifr.ifr_hwaddr.sa_data[4],
55. char)ifr.ifr_hwaddr.sa_data[5]);
56. close(skfd);
57. return 0;
58. }
59.
60. void main()
61. {
62. "eth0");
63.
64. }
参考网络资料:
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);
}
源码分析的文章,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下运行通过)
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. "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. "SIOCGIFHWADDR IOCTL error!\n");
4. close(skfd);
5. return -1;
6. }
7.
8. printf("mac addr: %02x:%02x:%02x:%02x:%02x:%02x\n"
9. char)ifr.ifr_hwaddr.sa_data[0],
10. char)ifr.ifr_hwaddr.sa_data[1],
11. char)ifr.ifr_hwaddr.sa_data[2],
12. char)ifr.ifr_hwaddr.sa_data[3],
13. char)ifr.ifr_hwaddr.sa_data[4],
14. 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设备驱动程序》