zoukankan      html  css  js  c++  java
  • 具体解释kernel中watchdog 驱动程序

    watchdog不管在小系统还是大的project系统中都是必须存在的。在解决线程挂死、系统死循环等都用非常重要的应用,算是系统出问题恢复初始状态的救命稻草。

    在kernel中wdt的应用不是非经常见,原因就是相比于裸系统来讲。它的线程会出现一些异步的情况,执行状态easy出现系统不可控的时刻。

    对于kernel中应用wdt而言,一般採用了一种通用方法。就是用一个timer进行喂狗操作。

    下面选取一个典型的代码进行说明,就用 Atmel AT32AP700X device,在kernel-》drivers-》watchdog->at32ap700x_wdt.c

    它的操作方法调用方法是不支持文件操作的,一般执行ioctl的方式进行调用

    static long at32_wdt_ioctl(struct file *file,
    unsigned int cmd, unsigned long arg)
    {
    int ret = -ENOTTY;
    int time;
    void __user *argp = (void __user *)arg;
    int __user *p = argp;


    switch (cmd) {
    case WDIOC_GETSUPPORT:
    ret = copy_to_user(argp, &at32_wdt_info,
    sizeof(at32_wdt_info)) ? -EFAULT : 0;
    break;
    case WDIOC_GETSTATUS:
    ret = put_user(0, p);
    break;
    case WDIOC_GETBOOTSTATUS:
    ret = put_user(wdt->boot_status, p);
    break;
    case WDIOC_SETOPTIONS:
    ret = get_user(time, p);
    if (ret)
    break;
    if (time & WDIOS_DISABLECARD)
    at32_wdt_stop();
    if (time & WDIOS_ENABLECARD)
    at32_wdt_start();
    ret = 0;
    break;
    case WDIOC_KEEPALIVE:
    at32_wdt_pat();
    ret = 0;
    break;
    case WDIOC_SETTIMEOUT:
    ret = get_user(time, p);
    if (ret)
    break;
    ret = at32_wdt_settimeout(time);
    if (ret)
    break;
    /* Enable new time value */
    at32_wdt_start();
    /* fall through */
    case WDIOC_GETTIMEOUT:
    ret = put_user(wdt->timeout, p);
    break;
    }


    return ret;
    }

    上面就是函数的样子,这里能够看到主要的命令就是


    wdt_settimeout  设置看门狗的最长喂狗时间

    wdt_keepalive   喂狗函数命令

    他们都相应了自己的函数,这样就能够在上层进行调用了。

    接着向下分析。wdt_settimeout 

    get_user(time, p);
    if (ret)
    break;
    ret = at32_wdt_settimeout(time);
    if (ret)
    break;
    /* Enable new time value */
    at32_wdt_start();

    调用了三个函数 依次的作用是 

    get_user(time, p);  查看状态

    at32_wdt_settimeout(time);  设置时间间隔

    at32_wdt_start();势能看门狗

    函数还是能从名字看出来作用的

    喂狗函数相同的就是at32_wdt_pat()

    这里走进去看一下  static inline void at32_wdt_pat(void)
    {
    spin_lock(&wdt->io_lock);
    wdt_writel(wdt, CLR, 0x42);
    spin_unlock(&wdt->io_lock);
    }

    这里就能看出来就是想clr寄存器里面写一个0x42就等于是喂狗了  

    再来看看其它的函数吧

    static int at32_wdt_settimeout(int time)
    {
    /*
    * All counting occurs at 1 / SLOW_CLOCK (32 kHz) and max prescaler is
    * 2 ^ 16 allowing up to 2 seconds timeout.
    */
    if ((time < TIMEOUT_MIN) || (time > TIMEOUT_MAX))
    return -EINVAL;


    /*
    * Set new watchdog time. It will be used when at32_wdt_start() is
    * called.
    */
    wdt->timeout = time;
    return 0;
    }

    设置时间的函数就是推断一下时间是不是超出范围了  假设没有就设置下去好了

    start就不看了   就是启动之前检測一下是不是重新启动时间有没有设置  没有的话就设置一个最大值

    重点看一下关闭函数

    static int at32_wdt_close(struct inode *inode, struct file *file)
    {
    if (expect_release == 42) {
    at32_wdt_stop();
    } else {
    dev_dbg(wdt->miscdev.parent,
    "unexpected close, not stopping watchdog! ");
    at32_wdt_pat();
    }
    clear_bit(1, &wdt->users);
    expect_release = 0;
    return 0;
    }

    这里能够看到wdt 是一旦打开就不能关闭的   这样也是符合常理的  假设能够关闭 也就失去了存在的意义了 。存在被攻击的可能。

    下一次解释下ioctl的方法

  • 相关阅读:
    【Linux高频命令专题(24)】grep
    【PSR规范专题(6)】PSR-7 HTTP消息接口【转】
    【redis专题(10)】KEY设计原则与技巧
    【redis专题(9)】事务
    【redis专题(8)】命令语法介绍之通用KEY
    linux 之 jq
    PHP Rabbitmq 报错Broken pipe
    Laravel 跨框架队列交互
    解决Linux下编译.sh文件报错 unexpected operator Syntax error: word unexpected
    安装QConf 报错及解决方案
  • 原文地址:https://www.cnblogs.com/wzjhoutai/p/6901057.html
Copyright © 2011-2022 走看看