一步一步粗谈linux文件系统(八)---- subsystem_register

总结写在最前面,后面代码解释,我自己都看着烦躁:

subsystem_register它首先是要有一个subsystem结构的数据,然后这个结构里的kset需要设置,而kset最重要的是kobjectkobject中的又要有目录项之类的,而这个目录文件要是没有指定父节点,缺省状态下是挂载在sysfs的根目录下的。


从这行代码subsystem_register(&fs_subsys);来简单分析subsystem_register

Fs_subsys定义:

	decl_subsys(fs, NULL, NULL);
		#define decl_subsys(_name,_type,_uevent_ops) \
		struct subsystem _name##_subsys = { \
			.kset = { \
				.kobj = { .name = __stringify(_name) }, \
				.ktype = _type, \
				.uevent_ops =_uevent_ops, \
			} \
		}

subsystem的数据结构:

struct subsystem {
	struct kset		kset;
	struct rw_semaphore	rwsem;
};

 

/**

 *        subsystem_register - register a subsystem.

 *        @s:        thesubsystem we're registering.

 *

 *        Oncewe register the subsystem, we want to make sure that

 *        thekset points back to this subsystem for correct usage of

 *        therwsem.

 */

 红字部分清晰的说明了这个函数的作用,就是用来注册一个子系统的

intsubsystem_register(struct subsystem * s)

{

……

if(!(error = kset_add(&s->kset)))

……

}

 

/**

 *        kset_add- add a kset object to the hierarchy.

 *        @k:        kset.

 *

 *        Simply, this adds the kset's embedded kobject to the

 *        hierarchy.

 *        Wealso try to make sure that the kset's embedded kobject

 *        hasa parent before it is added. We only care if the embedded

 *        kobjectis not part of a kset itself, since kobject_add()

 *        assignsa parent in that case.

 *        Ifthat is the case, and the kset has a controlling subsystem,

 *        thenwe set the kset's parent to be said subsystem.

 */

正如红字注释所说,这个函数的功能是增加kset自身的kobject

int kset_add(structkset * k)

{

if(!k->kobj.parent && !k->kobj.kset &&k->subsys)        //如果没有父节点,没有kset,有subsys

k->kobj.parent=&k->subsys->kset.kobj;        //父节点为子节点的设置对象

 

return kobject_add(&k->kobj);//增加对象

}

增加kset的对象到它所要求的阶层,红字代码为具体操作

 

/**

 *        kobject_add- add an object to the hierarchy.

 *        @kobj:        object.

 */

intkobject_add(struct kobject * kobj)

{

returnkobject_shadow_add(kobj, NULL);

}

 

/**

 *        kobject_add- add an object to the hierarchy.

 *        @kobj:        object.   //如果是device之类的subsystem,这里的kobj已经是k->kset->kobj了,且只有name属性

 *        @shadow_parent:sysfs directory to add to.

 */

intkobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent)

 

注意红字部分的NULLshadow_parent,可以看出注册fs这个子系统的时候,shadow_parentNULL还要特别关注它的类型,dentry,是不是很亲切,就是文件系统中的目录

 

截取个人认为kobject_shadow_add函数中最重要的几行代码

if (kobj->kset) {	//前提是kset要存在,如果是device,fs的subsystem 这项应该不存在
	spin_lock(&kobj->kset->list_lock);

	if (!parent)
		parent = kobject_get(&kobj->kset->kobj);	//如果父节点不存在,kset的对象就是父节点
							//如platform_type_bus的kobj->kset->kobj  就是device_subsys->kset->kobj
							//其实可以这么理解,如果父节点也没,kset也没,就直接挂在sys下
							//如果有父节点就挂在父节点下,如果有kset就挂在kset下

	list_add_tail(&kobj->entry,&kobj->kset->list);	//将kobj->entry加到kset的链表中spin_unlock(&kobj->kset->list_lock);
}
kobj->parent = parent;

error = create_dir(kobj, shadow_parent);	//初始化话生成一个dentry,顺带引出inode和sd(sysfs dirent)
					//kobj->dentry=dentry

上面的两段红字代码很关键,第一个红字代码是要找到挂载对象的父节点;第二个红字代码是要将对象挂载到父节点上


static intcreate_dir(struct kobject * kobj, struct dentry *shadow_parent)

 

/**

 *        sysfs_create_dir- create a directory for an object.

 *        @kobj:                objectwe're creating directory for.

 *        @shadow_parent:        parentparent object.

 */

 

intsysfs_create_dir(struct kobject * kobj, struct dentry *shadow_parent)

如果shadow_parentNULL,且kobj->parentNULL,那么就挂载sysfs的根目录下

parent =sysfs_mount->mnt_sb->s_root;        //sysfs文件系统的根目录

error =create_dir(kobj,parent,kobject_name(kobj),&dentry);        //对象,父节点,名字,要赋值的dentry

//这个函数的功能就是初始化dentry,顺带inode,sd(sysfsdirent)

//dentry->d_fsdata=sd,dentry->d_inode=inode ,sd->elememt=kobj,dentry->d_parent=partent 

static int create_dir(struct kobject * k, struct dentry * p,
		      const char * n, struct dentry ** d)
{
	int error;
	umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;

	mutex_lock(&p->d_inode->i_mutex);
	*d = lookup_one_len(n, p, strlen(n));	//查找是否已经存在,
								//不存在alloc一个dentry,且d_parent为p
	if (!IS_ERR(*d)) {
 		if (sysfs_dirent_exist(p->d_fsdata, n))	//如果存在相同元素,返回错误
  			error = -EEXIST;
  		else
			error = sysfs_make_dirent(p->d_fsdata, *d, k, mode,
								SYSFS_DIR);	//生成一个新的sd,sd->s_sibing挂载p->fsdata->s_children
								//dentry->d_fsdata=sd
								//上面两行注释结合,得出子sb挂载在父sb上
								//sd->elememt=kobj
								//dentry->d_op赋值
		if (!error) {	//sysfs_make_dirent这个执行成功
			error = sysfs_create(*d, mode, init_dir);	//init_dir是初始化一个新的inode
									//创建一个新的索引节点inode
									//d->d_inode =inode    //d:dentry
			if (!error) {
				inc_nlink(p->d_inode);
				(*d)->d_op = &sysfs_dentry_ops;
				d_rehash(*d);
			}
		}
		if (error && (error != -EEXIST)) {
			struct sysfs_dirent *sd = (*d)->d_fsdata;
			if (sd) {
 				list_del_init(&sd->s_sibling);
				sysfs_put(sd);
			}
			d_drop(*d);
		}
		dput(*d);
	} else
		error = PTR_ERR(*d);
	mutex_unlock(&p->d_inode->i_mutex);
	return error;
}

综上所述,再结合上面的图,sysfs也有inodedentry,但是多了一个新的东西,sd(sysfs dentry),这个结构是sysfs特有的,它挂载dentry->d_fsdata上,且它的s_element指向了kobj。另外一层的意义,即使不用dentry,也可以用sd来索引目录,操作之类的。

struct sysfs_dirent{

atomic_t                s_count;

structlist_head        s_sibling;

structlist_head        s_children;

void                        *s_element;

int                        s_type;

umode_t                        s_mode;

structdentry                *s_dentry;

structiattr                *s_iattr;

atomic_t                s_event;

};


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值