一个常见的应用场景就是,某个设备插上网线的时候,设备会去自动申请IP(如果设备没有IP)
那就需要应用层能够捕获硬件Link up-down事件,link up-down最先获取到事件的是 驱动层。
在/driver/net/phy.c里面会有 phy_print_status函数,netif_msg_link/netif_msg_ifup/netif_msg_ifdown也可以获取网口up-down 状态。
应用层要做到获取up-down信息,可以有2种做法:
1. 是查询,应用层不停的查询网卡状态,发现up的时候,就去申请IP
2. 中断通知,驱动发现网口up-down的时候,中断通知应用层
第一种做法主要是通过检查 ifconfig结果里面的RUNNING关键字来做到的
eth0 Link encap:Ethernet HWaddr 00:22:A2:00:10:11
inet addr:192.168.2.1 Bcast:192.168.2.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1415 errors:0 dropped:0 overruns:0 frame:0
TX packets:120 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:100515 (98.1 KiB) TX bytes:9401 (9.1 KiB)
Interrupt:106
当网口是up的时候,会有RUNNING,down的时候,则没有, 源码如下:
#include
#include
#include
#include
#include
char *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 NULL;
}
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 NULL;
}
if(ifr.ifr_flags & IFF_RUNNING) {
return "UP";
} else {
return "DOWN";
}
}
int main()
{
printf("%s\n",net_detect("eth0"));
return 0;
}
第二种做法,通过内核给应用层发signal信号(类似中断,sigint等),应用层收到后再做响应处理
首先用request_irq申请一个中断,然后用fasync_helper/kill_fasync把中断和驱动关联起来,应用层
在通过fcntl(iFd, F_SETOWN, getpid()) 将本进程和驱动关联,再通过fcntl(iFd, F_SETFL, iOFlags | FASYNC);
设置FASYNC flag,这样当驱动收到中断时候,就能及时通知应用层。
第一种做法,优点是实现都在应用层,但是实时性会差些,同时使用时候不能ifdown掉某个Interface
第二种做法,优点是实时性高,通用性好,缺点是增加了内核开销
阅读(14621) | 评论(0) | 转发(0) |