dev/watchdog 下会有watchdog 和 watchdog0等等。这里先给出结论watchdog和watchdog0代表的是同一个硬件,即使他们的字符设备的major和minor 不一样
linux-hice:~ # ls /dev/watchdog
watchdog watchdog0 watchdog1
linux-hice:/dev # ls -al | grep watchdog
crw------- 1 root root 10, 130 Jun 7 04:38 watchdog
crw------- 1 root root 252, 0 Jun 7 04:38 watchdog0
crw------- 1 root root 252, 1 Jun 7 04:38 watchdog1
一般在watchdog的probe函数中都会调用watchdog_register_device 来在dev下注册设备,就是如上面的/dev/watchdog等
watchdog_register_device->__watchdog_register_device->watchdog_dev_register
int watchdog_dev_register(struct watchdog_device *wdd)
{
struct device *dev;
dev_t devno;
int ret;
devno = MKDEV(MAJOR(watchdog_devt), wdd->id);
ret = watchdog_cdev_register(wdd, devno);
if (ret)
return ret;
//这里就注册dev/watchdog0
dev = device_create_with_groups(&watchdog_class, wdd->parent,
devno, wdd, wdd->groups,
"watchdog%d", wdd->id);
if (IS_ERR(dev)) {
watchdog_cdev_unregister(wdd);
return PTR_ERR(dev);
}
ret = watchdog_register_pretimeout(wdd);
if (ret) {
device_destroy(&watchdog_class, devno);
watchdog_cdev_unregister(wdd);
}
return ret;
}
static int watchdog_cdev_register(struct watchdog_device *wdd, dev_t devno)
{
struct watchdog_core_data *wd_data;
int err;
wd_data = kzalloc(sizeof(struct watchdog_core_data), GFP_KERNEL);
if (!wd_data)
return -ENOMEM;
kref_init(&wd_data->kref);
mutex_init(&wd_data->lock);
wd_data->wdd = wdd;
wdd->wd_data = wd_data;
if (!watchdog_wq)
return -ENODEV;
INIT_DELAYED_WORK(&wd_data->work, watchdog_ping_work);
//如果id是0的话,就调用misc_register 来注册/dev/watchdog,注意这个/dev/watchdog 对应的watchdog_device *wdd 和调用cdev_add 添加的字符设备用的同一个watchdog_device *wdd,所以才说他们对应的是同一个hw,以上层应用不管是打开dev/watchdog还是dev/watchdog0 都是一样的.
if (wdd->id == 0) {
old_wd_data = wd_data;
watchdog_miscdev.parent = wdd->parent;
err = misc_register(&watchdog_miscdev);
if (err != 0) {
pr_err("%s: cannot register miscdev on minor=%d (err=%d).\n",
wdd->info->identity, WATCHDOG_MINOR, err);
if (err == -EBUSY)
pr_err("%s: a legacy watchdog module is probably present.\n",
wdd->info->identity);
old_wd_data = NULL;
kfree(wd_data);
return err;
}
}
/* Fill in the data structures */
cdev_init(&wd_data->cdev, &watchdog_fops);
wd_data-> = wdd->ops->owner;
/* Add the device */
err = cdev_add(&wd_data->cdev, devno, 1);
if (err) {
pr_err("watchdog%d unable to add device %d:%d\n",
wdd->id, MAJOR(watchdog_devt), wdd->id);
if (wdd->id == 0) {
misc_deregister(&watchdog_miscdev);
old_wd_data = NULL;
kref_put(&wd_data->kref, watchdog_core_data_release);
}
return err;
}
/* Record time of most recent heartbeat as 'just before now'. */
wd_data->last_hw_keepalive = jiffies - 1;
/*
* If the watchdog is running, prevent its driver from being unloaded,
* and schedule an immediate ping.
*/
if (watchdog_hw_running(wdd)) {
__module_get(wdd->ops->owner);
kref_get(&wd_data->kref);
queue_delayed_work(watchdog_wq, &wd_data->work, 0);
}
return 0;
}
之所以要注册/dev/watchog 是为来兼容老的接口