在dev->class 成立的情况下,
(1)对于没有指定dev->parent的dev都将被添加到/sys/devices/virtual/tty/ 目录下
(2)如果指定了dev ->parent , 那么同时该dev ->class存在 , 同时parent -> class存在 ,那么该dev ->name目录将被添加到parent->class所在目录下 [ luther . gliethttp ]
luther@gliethttp : ~ $ ll / sys / class / tty / console
lrwxrwxrwx 1 root root 0 2009 - 06 - 30 09 : 40 / sys / class / tty / console - > . . / . . / devices / virtual / tty / console
luther@gliethttp : ~ $ ll / sys / devices / virtual / tty / console /
total 0
- rw - r - - r - - 1 root root 4 . 0K 2009 - 06 - 30 10 : 51 uevent
drwxr - xr - x 2 root root 0 2009 - 06 - 30 10 : 51 power
lrwxrwxrwx 1 root root 0 2009 - 06 - 30 10 : 57 subsystem - > . . / . . / . . / . . / class / tty
- r - - r - - r - - 1 root root 4 . 0K 2009 - 06 - 30 10 : 57 dev
来看看linux2 . 6 . 25内核源码 , 是怎么做得 .
device_create ( tty_class , NULL , MKDEV ( TTYAUX_MAJOR , 1 ) , "console" ) ;
= = > device_register
= = > device_add
= = > setup_parent
= = > get_device_parent
= = > dev - > kobj . parent = kobj ( "/sys/devices/virtual/tty" ) ; //所以所有的文件添加都将指向该目录[luther.gliethttp]
# ifdef CONFIG_SYSFS_DEPRECATED
static struct kobject * get_device_parent ( struct device * dev ,
struct device * parent )
{
/* class devices without a parent live in /sys/class// */
if ( dev - > class & & ( ! parent | | parent - > class ! = dev - > class ) )
return & dev - > class - > subsys . kobj ;
/* all other devices keep their parent */
else if ( parent )
return & parent - > kobj ;
return NULL ;
}
# else
// 在我的ubnutu 8.10中使用的如下函数
static struct kobject * get_device_parent ( struct device * dev ,
struct device * parent )
{
int retval ;
if ( dev - > class ) {
struct kobject * kobj = NULL ;
struct kobject * parent_kobj ;
struct kobject * k ;
/*
* If we have no parent, we live in "virtual".
* Class-devices with a non class-device as parent, live
* in a "glue" directory to prevent namespace collisions.
*/
if ( parent = = NULL )
parent_kobj = virtual_device_parent ( dev ) ; // 获取/sys/devices/virtual目录对应的kobj
else if ( parent - > class )
return & parent - > kobj ;
else
parent_kobj = & parent - > kobj ;
/* find our class-directory at the parent and reference it */
spin_lock ( & dev - > class - > class_dirs . list_lock ) ;
// class->class_dirs本身就是一个kset
// 如果该kset的list链表上没有挂接到/sys/devices/virtual目录上的son,那么说明该class_dirs还没有在
// /sys/devices/virtual目录下创建,所以就需要创建该class名对应的目录[luther.gliethttp]
list_for_each_entry ( k , & dev - > class - > class_dirs . list , entry )
if ( k - > parent = = parent_kobj ) {
kobj = kobject_get ( k ) ;
break ;
}
spin_unlock ( & dev - > class - > class_dirs . list_lock ) ;
if ( kobj )
return kobj ;
// 创建/sys/devices/virtual/tty这个tty_class对应的目录
/* or create a new class-directory at the parent device */
k = kobject_create ( ) ;
if ( ! k )
return NULL ;
k - > kset = & dev - > class - > class_dirs ; // 名在/sys/devices/virtual/目录下创建以tty_class的name为目录名的目录[luther.gliethttp]
retval = kobject_add ( k , parent_kobj , "%s" , dev - > class - > name ) ; // 将kobj添加到parent_kobj对应目录下[luther.gliethttp]
if ( retval < 0 ) {
kobject_put ( k ) ;
return NULL ;
}
/* do not emit an uevent for this simple "glue" directory */
return k ;
}
if ( parent )
return & parent - > kobj ;
return NULL ;
}
#endif
static struct kobject *get_device_parent(struct device *dev,
struct device *parent)
{
if (dev->class) { //设备的类 存在,sys/class/目录下的的那一个类,例如video4linux 等
static DEFINE_MUTEX(gdp_mutex);
struct kobject *kobj = NULL;
struct kobject *parent_kobj;
struct kobject *k;
#ifdef CONFIG_BLOCK
/* block disks show up in /sys/block */
if (sysfs_deprecated && dev->class == &block_class) {
if (parent && parent->class == &block_class)
return &parent->kobj;
return &block_class.p->subsys.kobj;
}
#endif
/*
* If we have no parent, we live in "virtual".
* Class-devices with a non class-device as parent, live
* in a "glue" directory to prevent namespace collisions.
*/
if (parent == NULL) //如果父设备不存在,为空
parent_kobj = virtual_device_parent(dev); //虚拟设备父设备,对象为:sys/devices/virtual
接下来后面创建类目录
else if (parent->class && !dev->class->ns_type) //父设备类存在且设备类命名空间类型不存在
return &parent->kobj; 返回父设备的对象,退出此函数
else //父设备parent存在,parent->class不存在,dev->class->nstype存在
parent_kobj = &parent->kobj; 获取父设备对象,接下来后面会创建类
mutex_lock(&gdp_mutex);
/* 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;
}
/* 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;
}