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

来源:互联网 发布:华能辞职知乎 编辑:程序博客网 时间:2024/06/07 21:55

在做一个在内核态下分布式的文件系统,想知道在内核中,没有后备存储介质写入的时候,目录项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);}}
然后就得到了正常的,本该出现的信息。



0 0
原创粉丝点击