当前位置:嗨网首页>书籍在线阅读

12-网络连接状态

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

16.7 网络连接状态

网络适配器硬件电路可以检测出链路上是否有载波,载波反映了网络的连接是否正常。网络设备驱动可以通过netif_carrier_on()和netif_carrier_off()函数改变设备的连接状态,如果驱动检测到连接状态发生变化,也应该以netif_carrier_on()和netif_carrier_off()函数显式地通知内核。

除了netif_carrier_on()和netif_carrier_off()函数以外,另一个函数netif_carrier_ok()可用于向调用者返回链路上的载波信号是否存在。

这几个函数都接收一个net_device设备结构体指针为参数,原型分别为:

void netif_carrier_on(struct net_device *dev);

void netif_carrier_off(struct net_device *dev);

int netif_carrier_ok(struct net_device *dev);

网络设备驱动程序中可采取一定的手段来检测和报告链路状态,例如设置一个定时器来对链路状态进行周期性地检查。当定时器到期之后,在定时器处理函数中读取物理设备的相关寄存器获得载波状态,从而更新设备的连接状态,如代码清单16.12所示。

代码清单16.12 网络设备驱动用定时器周期检查链路状态

1 static void xxx_timer(unsigned long data)

2 {

3 struct net_device dev = (struct net_device)data;

4 u16 link;

5 …

6 if (!(dev->flags &IFF_UP))

7 goto set_timer;

8

9 / 获得物理上的连接状态 /

10 if (link = xxx_chk_link(dev)) {

11 if (!(dev->flags &IFF_RUNNING)) {

12 netif_carrier_on(dev);

13 dev->flags |= IFF_RUNNING;

14 printk(KERN_DEBUG "%s: link up\n", dev->name);

15 }

16 } else {

17 if (dev->flags &IFF_RUNNING) {

18 netif_carrier_off(dev);

19 dev->flags &= ~IFF_RUNNING;

20 printk(KERN_DEBUG "%s: link down\n", dev->name);

21 }

22 }

23

24 set_timer:

25 priv->timer.expires = jiffies + 1 * Hz;

26 priv->timer.data = (unsigned long)dev;

27 priv->timer.function = &xxx_timer; / timer handler /

28 add_timer(&priv->timer);

29 }

上述代码第10行调用的xxx_chk_link()函数用于读取网络适配器硬件的相关寄存器以获得链路连接状态,具体实现由硬件决定。当链路连接上时,第12行的netif_carrier_on()函数显式地通知内核链路正常;反之,第18行的netif_carrier_off()同样显式地通知内核链路失去连接。

此外,从上述源代码还可以看出,定时器处理函数会不停地利用第24~28行代码启动新的定时器以实现周期检测的目的。那么最初启动定时器的地方在哪里呢?很显然,它最适合在设备的打开函数中完成,如代码清单16.13所示。

代码清单16.13 在网络设备驱动的打开函数中初始化定时器

1 static int xxx_open(struct net_device *dev)

2 {

3 struct xxx_priv priv = (struct xxx_priv)dev->priv;

4

5 ...

6 priv->timer.expires = jiffies + 3 * Hz;

7 priv->timer.data = (unsigned long)dev;

8 priv->timer.function = &xxx_timer; / timer handler /

9 add_timer(&priv->timer);

10 ...

11 }