通过目录的dentry获得目录中文件的dentry

本文探讨了在内核态下分布式文件系统的实现原理,重点分析了目录项dentry的管理方式及其在内存中的组织结构。通过源码解析,详细介绍了dentry的创建过程及子目录项的获取方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在做一个在内核态下分布式的文件系统,想知道在内核中,没有后备存储介质写入的时候,目录项dentry是如何管理的,所以,一直想知道怎么就可以得到子文件的目录项,并把名字打印出来看看。

第一次,沿着open函数不断深入,发现和lookup_one_len一样,创造dentry的过程中,查找是否有同名的dentry的时候都是调用的是d_lookup。但是,尝试了好久,由于采用的是hash策略,然而那个d_hash函数无法外部调用,其中的参数也需要内部定义并初始化,无奈,最后放弃,linux 为了效率做得很好,但是很难理解并采用。

第二次,关于dentry的介绍中,linux 2.32.21内核介绍是这样子的:

struct dentry {
	atomic_t d_count;
	unsigned int d_flags;		/* protected by d_lock */
	spinlock_t d_lock;		/* per dentry lock */
	int d_mounted;
	struct inode *d_inode;		/* Where the name belongs to - NULL is
					 * negative */
	/*
	 * The next three fields are touched by __d_lookup.  Place them here
	 * so they all fit in a cache line.
	 */
	struct hlist_node d_hash;	/* lookup hash list */
	struct dentry *d_parent;	/* parent directory */
	struct qstr d_name;

	struct list_head d_lru;		/* LRU list */
	/*
	 * d_child and d_rcu can share memory
	 */
	union {
		struct list_head d_child;	/* child of parent list */
	 	struct rcu_head d_rcu;
	} d_u;
    //在这个地方谁都会认为这就是子文件目录项的起始地址吧,根据双向循环链表的读取规则可以得到子文件目录项的指针
  struct list_head d_subdirs; /* our children */

struct list_head d_alias; /* inode alias list */unsigned long d_time; /* used by d_revalidate */const struct dentry_operations *d_op;struct super_block *d_sb; /* The root of the dentry tree */void *d_fsdata; /* fs-specific data */unsigned char d_iname[DNAME_INLINE_LEN_MIN];
 /* small names */};


就是在这个地方,并不是这么回事,尝试无数次无果之后,我决定研究源码:

创建一个新的dentry,在函数d_alloc中:

struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
{
	struct dentry *dentry;
	char *dname;

	dentry = kmem_cache_alloc(dentry_cache, GFP_KERNEL);
	if (!dentry)
		return NULL;

	if (name->len > DNAME_INLINE_LEN-1) {
		dname = kmalloc(name->len + 1, GFP_KERNEL);
		if (!dname) {
			kmem_cache_free(dentry_cache, dentry); 
			return NULL;
		}
	} else  {
		dname = dentry->d_iname;
	}	
	dentry->d_name.name = dname;

	dentry->d_name.len = name->len;
	dentry->d_name.hash = name->hash;
	memcpy(dname, name->name, name->len);
	dname[name->len] = 0;

	atomic_set(&dentry->d_count, 1);
	dentry->d_flags = DCACHE_UNHASHED;
	spin_lock_init(&dentry->d_lock);
	dentry->d_inode = NULL;
	dentry->d_parent = NULL;
	dentry->d_sb = NULL;
	dentry->d_op = NULL;
	dentry->d_fsdata = NULL;
	dentry->d_mounted = 0;
	INIT_HLIST_NODE(&dentry->d_hash);
	INIT_LIST_HEAD(&dentry->d_lru);
	INIT_LIST_HEAD(&dentry->d_subdirs);
	INIT_LIST_HEAD(&dentry->d_alias);

	if (parent) {
		dentry->d_parent = dget(parent);
		dentry->d_sb = parent->d_sb;
	} else {
		INIT_LIST_HEAD(&dentry->d_u.d_child);
	}

	spin_lock(&dcache_lock);
	if (parent)
		list_add(&dentry->d_u.d_child, &parent->d_subdirs);  //在这个地方的时候被惊艳到了,合计插入的并不是d_subdirs啊
	dentry_stat.nr_dentry++;
	spin_unlock(&dcache_lock);

	return dentry;
}
深入理解linux内核这部经典著作是这么写的:

d_subdirs  :对目录而言,子目录项链表的头

d_child: 对目录而言,用于同一父目录中的目录项链表的指针

现在想想,说的很对,然而书上就这么写的,一点额外注释都木有,可是光看书,这怎么可能理解到原来是这么回事,只能说内核真是博大精深,光看书是肯定不够的了

得到一个目录项dentry之后,获取到目录中子目录项的代码就要变化一下子了:

        printk("a dentry name : %s\n",a_dentry->d_name.name);
	struct dentry *a_parent_dentry = a_dentry->d_parent;
	printk(KERN_EMERG"根目录名称 %s\n",a_parent_dentry->d_name.name);

	struct list_head *plist;
	struct dentry *sub_dentry;

	list_for_each(plist, &(a_parent_dentry->d_subdirs))
	{
		sub_dentry = list_entry(plist, struct dentry, d_u.d_child);
		if(sub_dentry)
		{
			printk(KERN_EMERG"subdirs_dentry %s\n",sub_dentry->d_name.name);
			printk(KERN_EMERG"sub_dentry %ld\n",sub_dentry);
		}
	}
然后就得到了正常的,本该出现的信息。



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值