当调用device_create时parent参数为空时,新添加的设备位于sys/devices//sys/devices/virtual目录
以下面代码的为例
my_newcharled.myclass = class_create(THIS_MODULE,dtled);
my_newcharled.mydevice = device_create(my_newcharled.myclass,NULL,my_newcharled.newcharled_devt,NULL,dtled);最终新添加的类 在/sys/class
通过在/sys/class进入设备
新添加的设备在/sys/devices/virtual
当按照字符设备标准驱动过程新建字符设备时,当调用device_create时parent参数为空时
device_create()
—>device_create_vargs
------>device_create_groups_vargs
--------->device_add
--------------->get_device_parent
------------------->virtual_device_parent 此时在/sys/devices/virtual中新增新的设备
主要是device_add中get_device_parent实现(device_add()函数其它功能学习后再分析)
int device_add(struct device *dev)
{
struct device *parent;
struct kobject *kobj;
struct class_interface *class_intf;
int error = -EINVAL;
struct kobject *glue_dir = NULL;
dev = get_device(dev);
if (!dev)
goto done;
if (!dev->p) {
error = device_private_init(dev);
if (error)
goto done;
}
if (dev->init_name) {
dev_set_name(dev, "%s", dev->init_name);
dev->init_name = NULL;
}
/* subsystems can specify simple device enumeration */
if (!dev_name(dev) && dev->bus && dev->bus->dev_name)
dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id);
if (!dev_name(dev)) {
error = -EINVAL;
goto name_error;
}
pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
parent = get_device(dev->parent);
kobj = get_device_parent(dev, parent);
if (IS_ERR(kobj)) {
error = PTR_ERR(kobj);
goto parent_error;
}
…………
}
EXPORT_SYMBOL_GPL(device_add);
get_device_parent()
static struct kobject *get_device_parent(struct device *dev,
struct device *parent)
{
if (dev->class) {
struct kobject *kobj = NULL;
struct kobject *parent_kobj;
struct kobject *k;
//获取/sys/devices/virtual目录对应的kobj
if (parent == NULL)
parent_kobj = virtual_device_parent(dev);
else if (parent->class && !dev->class->ns_type)
return &parent->kobj;
else
parent_kobj = &parent->kobj;
mutex_lock(&gdp_mutex);
//查看设备父目录是否存在
//k->parent如果指定的话
//k->parent如果没指定,但不是第一次创建时
/* find our class-directory at the parent and reference it */
spin_lock(&dev->class->p->glue_dirs.list_lock);
list_for_each_entry(k, &dev->class->p->glue_dirs.list, entry)
if (k->parent == parent_kobj) {
kobj = kobject_get(k);
break;
}
spin_unlock(&dev->class->p->glue_dirs.list_lock);
if (kobj) {
mutex_unlock(&gdp_mutex);
return kobj;
}
//k->parent如果没指定,且是第一次创建时
//在/sys/devices/virtual中创建新的设备目录
/* or create a new class-directory at the parent device */
k = class_dir_create_and_add(dev->class, parent_kobj);
/* do not emit an uevent for this simple "glue" directory */
mutex_unlock(&gdp_mutex);
return k;
}
/* subsystems can specify a default root directory for their devices */
if (!parent && dev->bus && dev->bus->dev_root)
return &dev->bus->dev_root->kobj;
if (parent)
return &parent->kobj;
return NULL;
}
virtual_device_parent()
struct kobject *virtual_device_parent(struct device *dev)
{
static struct kobject *virtual_dir = NULL;
if (!virtual_dir)
virtual_dir = kobject_create_and_add("virtual", &devices_kset->kobj);
return virtual_dir;
}