免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 7896 | 回复: 4
打印 上一主题 下一主题

浅谈"watchdog timeout"出现的原因 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2004-03-15 22:20 |只看该作者 |倒序浏览
  1. 浅谈"watchdog timeout"出现的原因
  2. 最近有比较多的人谈到网卡的”watchdog timeout“问题,究竟是什么原因造成的,大多数人都
  3. 把网卡的性能不佳做为问题的根源所在。我认为网卡的性能只是一方面的因素,他还涉及到缓冲的
  4. 大小、单位时间内的包的数量、及网卡驱动程序等一系列因素。以下将从源代码的角度来对他进行
  5. 分析。
  6.     首先,我们看看到底是哪个函数发出了“watchdog timeout”字符串,只要你查一下源代码
  7. 不难看出,在各网卡的驱动程序里的XX_watchdog(XX是各网卡的名称,如:8139是rl,AMD7990
  8. 是pcn,Inter是fxp等等)函数发出的。函数比较简单:
  9. static void rl_watchdog(ifp)
  10.         struct ifnet                *ifp;/*申明ifp是一个ifnet结构,结构存放了该网卡的输入输
  11.                                 出的函数指针和一些重要参数,当然也包括rl_watchdog函数的
  12.                                 指针*/
  13. {
  14.         struct rl_softc                *sc;
  15.         sc = ifp->;if_softc; /*ifnet是softc结构的一个子集,softc包含了更多的该网卡的参数*/
  16.         printf("rl%d: watchdog timeout\n", sc->;rl_unit);/*打印出是哪块网卡出现问题。
  17.                                 sc->;rl_unit代办该种网卡的第几快。我们知道在一个机器里同样
  18.                                 的网卡可能有几块,当然此参数是由网卡驱动程序的初始化程序填充*/
  19.         ifp->;if_oerrors++; /*累计输出出现的错误包数量(o代表输出)*/
  20.         rl_txeof(sc);/*这里是每个驱动程序不同的,此处为8139的,不过我觉得用rl_stop(sc)更好*/
  21.         rl_rxeof(sc);/*这里也是每个驱动程序不同。我觉得来一个rl_reset(sc)也不错。*/
  22.         rl_init(sc);/*这里大家都一样,重新初始芯片。*/
  23.         return;
  24. }
  25. 好了,到这我们知道是XX_watchdog函数发出了watchdog timeout信息。那么是谁来调用该函数呢?
  26. 我们接着来看另一个函数:if_slowtimo函数,该函数在if.c中。if.c是interface(接口)的简称,
  27. 即系统在启动过程中初始化时必须调用其中的一些函数。ifinit函数是其中被调用的一个,这个函数很
  28. 简单:
  29. void
  30. ifinit()
  31. {
  32.         static struct timeout if_slowtim;
  33.         timeout_set(&if_slowtim, if_slowtimo, &if_slowtim);/*简单的说就是设置一定时器*/
  34.         if_slowtimo(&if_slowtim);/*哈哈,等不急了,先调用了再说*/
  35. }
  36. 这样一来,if_slowtimo就成了一个一定时间内就要执行的一个函数了,此时候,大家应该能猜到if_slowtimo
  37. 的大概功能,无非是定时查看各网卡的发送数据的情况,如果没发送完成,就给该卡加一个计数器,到
  38. 计数器达到一定的值时还没发送出去就调用该卡的XX_watchdog函数。下面我们来看看if_slowtimo函数。
  39. void
  40. if_slowtimo(arg)
  41.         void *arg;
  42. {
  43.         struct timeout *to = (struct timeout *)arg;
  44.         struct ifnet *ifp;
  45.         int s = splimp();/*在做以下操作的时候必须关中断*/
  46.         TAILQ_FOREACH(ifp, &ifnet, if_list) {/*搜索每一个接口设备,TAILQ_FOREACH实际上是for(...)*/
  47.                 if (ifp->;if_timer == 0 || --ifp->;if_timer)
  48.                         continue;/*如果是if_timer为0或if_timer减1以后还为真,实际上是对每块网卡
  49.                                 的计数器if_timer减1后判断他是否还大于0,小于0就调用watchdog函数。*/
  50.                 if (ifp->;if_watchdog) /*不过调用之前看看该卡有没有watchdog函数*/
  51.                         (*ifp->;if_watchdog)(ifp);
  52.         }
  53.         splx(s);
  54.         timeout_add(to, hz / IFNET_SLOWHZ);/*每次计时器完成后都会清除,你不得不又加上去。hz是计算
  55.                                                 机的主频,就是说调度的间隔时间是和主频成正比的关系。*/
  56. }
  57. 到这里一切都很明白了,我们只要在驱动程序的输出包时给定一个值(if_timer,大多数是5),而输出函数是一个
  58. 直到输出成功才跳出的循环,不成功他就一直重试来输出此包,而我们上面的程序就会时间一到就给你的值减1,如果
  59. 减到小于0了,就watchdog timeout。我们还是来看一看程序吧:

  60. static void rl_start(ifp)
  61.         struct ifnet                *ifp;
  62. {
  63.         struct rl_softc                *sc;
  64.         struct mbuf                *m_head = NULL;
  65.         sc = ifp->;if_softc;
  66.         while(RL_CUR_TXMBUF(sc) == NULL) {/* 1:当输出缓冲区为空时才进行新的输出*/
  67.                 IF_DEQUEUE(&ifp->;if_snd, m_head);/*把将要输出的数据加入到输出队列中。*/
  68.                 if (m_head == NULL)/* 2:申请内存失败*/
  69.                         break;
  70.                 if (rl_encap(sc, m_head)) {/*8139卡的弱智表现在此,多加一个头部,还要长字节对齐,影响
  71.                                                 到数据必须重新搬迁。花时间啊!*/
  72.                         IF_PREPEND(&ifp->;if_snd, m_head);
  73.                         ifp->;if_flags |= IFF_OACTIVE;
  74.                         break;
  75.                 }
  76.                 if (ifp->;if_bpf)/* 3:如果包过滤存在就进行过滤*/
  77.                         bpf_mtap(ifp, RL_CUR_TXMBUF(sc));
  78.                 CSR_WRITE_4(sc, RL_CUR_TXADDR(sc),/* 4:以下为硬件输出的IO指令*/
  79.                     vtophys(mtod(RL_CUR_TXMBUF(sc), caddr_t)));
  80.                 CSR_WRITE_4(sc, RL_CUR_TXSTAT(sc),
  81.                     RL_TXTHRESH(sc->;rl_txthresh) |
  82.                     RL_CUR_TXMBUF(sc)->;m_pkthdr.len);

  83.                 RL_INC(sc->;rl_cdata.cur_tx);
  84.         }
  85.         if (RL_CUR_TXMBUF(sc) != NULL)/*如果传送缓冲不为空,说明数据放到缓冲中已经准备传了*/
  86.                 ifp->;if_flags |= IFF_OACTIVE;/*加上正在传标志*/
  87.         ifp->;if_timer = 5;/*设定计数器为5*/
  88.         return;
  89. }
  90. 大家注意看我注释中的1,2,3,4标号,即是4个有可能使传送出现问题的地方。但大家也会问:即使我传送
  91. 成功了也会if_timer变成5啊,那么成功了后是怎么消除这个5的呢,答案在当传送完一个包后,网卡将产生一个
  92. 中断,我们来看中断程序:
  93. static void rl_intr(arg)
  94. {
  95. ...  这中间我就不写了
  96.         if ((status & RL_ISR_TX_OK) || (status & RL_ISR_TX_ERR))  /*如果中断后状态寄存器的标识
  97.                                                         是成功或出错,就调用下面的程序。*/
  98.                 rl_txeof(sc);
  99. ...
  100. }
  101. 再看rl_txeof:
  102. static void rl_txeof(sc)
  103. {
  104. ...
  105.         ifp->;if_timer = 0;/*哈哈,在这清0了,也就是说,只要你不是反复在那传,不过错误和传输正确
  106.                                 都不会出现"watchdog timeout"*/
  107. ...
  108. }
  109. 综上所述:引起watchdog timeout的主要原因为:1、缓冲区不够大,前面的没发完后面的又跟的来了。2、内核
  110. 的内存分配出现问题,此情况比较少发生。3、卡的质量(在IO时的吞吐量)。4、bpf过滤过于复杂引起。
  111. 如何解决这个问题:
  112. 首先我们必须查出导致出现该问题的原因,即是4个问题中的哪个引起的,我们来修改驱动程序和相关的程序:
  113. 在if.h中定义一全局变量:
  114. u_int8_t myerror;   /*意思是出错的原因代码,按我列的来吧,1是缓冲区不够...*/
  115. 在函数static void rl_start(ifp)中加入:
  116. static void rl_start(ifp)
  117.         struct ifnet                *ifp;
  118. {
  119.         struct rl_softc                *sc;
  120.         struct mbuf                *m_head = NULL;
  121.         sc = ifp->;if_softc;
  122.         u_int8_t tmperror;
  123.         if (RL_CUR_TXMBUF(sc) != NULL) {/*新加,如果是缓冲区不够问题*/
  124.                 myerror=1;
  125.         }
  126.         while(RL_CUR_TXMBUF(sc) == NULL) {
  127.                 IF_DEQUEUE(&ifp->;if_snd, m_head);
  128.                 if (m_head == NULL)
  129.                 {
  130.                         myerror=2; /*内存分配出错*/
  131.                         break;
  132.                 }

  133.                 if (rl_encap(sc, m_head)) {
  134.                         IF_PREPEND(&ifp->;if_snd, m_head);
  135.                         ifp->;if_flags |= IFF_OACTIVE;
  136.                         break;
  137.                 }
  138.                 if (ifp->;if_bpf)
  139.                         bpf_mtap(ifp, RL_CUR_TXMBUF(sc));
  140.                 tmperror=myerror;/*在进行写IO口前先保存前面出错的原因*/
  141.                 CSR_WRITE_4(sc, RL_CUR_TXADDR(sc),
  142.                     vtophys(mtod(RL_CUR_TXMBUF(sc), caddr_t)));
  143.                 CSR_WRITE_4(sc, RL_CUR_TXSTAT(sc),
  144.                     RL_TXTHRESH(sc->;rl_txthresh) |
  145.                     RL_CUR_TXMBUF(sc)->;m_pkthdr.len);
  146.                 myerror=tmperror;/*上面两句没问题的话再还原前面的出错原因*/
  147.                 RL_INC(sc->;rl_cdata.cur_tx);
  148.         }
  149.         if (RL_CUR_TXMBUF(sc) != NULL)
  150.                 ifp->;if_flags |= IFF_OACTIVE;
  151.         ifp->;if_timer = 5;

  152.         return;
  153. }
  154. 最后再改一下rl_watchdog中的显示部分
  155.         printf("rl%d: watchdog timeout:error number is %x\n", sc->;rl_unit,myerror);
  156. 当然这只是我个人的见解,可能有许多不足或没考虑到的地方,也希望大家能提出更好、更容易
  157. 的方法。

  158.                                                 xie_minix 于 2004-3-15
复制代码

论坛徽章:
0
2 [报告]
发表于 2005-12-13 20:25 |只看该作者
我今天也遇到了这个问题,同样的3台机器,只有一台发送watchdog timeout,是不是说它的网卡质量不好呢?

论坛徽章:
0
3 [报告]
发表于 2006-09-14 10:15 |只看该作者
......lz 好像是没有理解 watchdog 是做什么用的。


在嵌入式领域,watchdog 俗称“看门狗”,本质上是一个自减的定时器,一般跟硬件设备的复位电路相连。初始化 watchdog 的时候需要给它一个初始值,这个 watchdog 就会定时自减。硬件设备的程序需要每隔一段时间“喂狗”,就是重设 watchdog 定时器的值。如果程序因为某种原因跑飞、陷入死循环等等,就会停止“喂狗”的行为(well,也不一定),watchdog 自减到 0 的时候就往复位电路发信号,重启设备。

所以 watchdog 的作用就是防止设备长时间陷入某种不希望的状态,在网卡驱动上也是一样的,作用是为了防止网卡驱动因为硬件或者程序的问题死掉,长时间陷入在某个状态而失去响应。如果驱动程序编写没有问题的话,这种情况只会是因为硬件的原因造成的。

论坛徽章:
0
4 [报告]
发表于 2008-12-08 13:09 |只看该作者
我想问下楼主,要想看懂那些代码我该怎么做?

论坛徽章:
0
5 [报告]
发表于 2008-12-31 16:14 |只看该作者
我遇到过这样的问题,有硬件出问题的,也有驱动要Patch的
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP