【linux】内核中根据inode得到文件名

内核编程中,操作的对象往往是inode,但是如何根据inode得到文件名呢,或者找到对应于文件系统的位置呢?

527 struct inode {
528         umode_t                 i_mode;
529         unsigned short          i_opflags;
530         kuid_t                  i_uid;
531         kgid_t                  i_gid;
532         unsigned int            i_flags;
533 
534 #ifdef CONFIG_FS_POSIX_ACL
535         struct posix_acl        *i_acl;
536         struct posix_acl        *i_default_acl;
537 #endif
538 
539         const struct inode_operations   *i_op;
540         struct super_block      *i_sb;
541         struct address_space    *i_mapping;
542 
543 #ifdef CONFIG_SECURITY
544         void                    *i_security;
545 #endif
546 
547         /* Stat data, not accessed from path walking */
548         unsigned long           i_ino;
549         /*
550          * Filesystems may only read i_nlink directly.  They shall use the
551          * following functions for modification:
552          *
553          *    (set|clear|inc|drop)_nlink
554          *    inode_(inc|dec)_link_count
555          */
556         union {
557                 const unsigned int i_nlink;
558                 unsigned int __i_nlink;
559         };
560         dev_t                   i_rdev;
561         loff_t                  i_size;
562         struct timespec         i_atime;
563         struct timespec         i_mtime;
564         struct timespec         i_ctime;
565         spinlock_t              i_lock; /* i_blocks, i_bytes, maybe i_size */
566         unsigned short          i_bytes;
567         unsigned int            i_blkbits;
568         blkcnt_t                i_blocks;
569 
570 #ifdef __NEED_I_SIZE_ORDERED
571         seqcount_t              i_size_seqcount;
572 #endif
573 
574         /* Misc */
575         unsigned long           i_state;
576         struct mutex            i_mutex;
577 
578         unsigned long           dirtied_when;   /* jiffies of first dirtying */
579 
580         struct hlist_node       i_hash;
581         struct list_head        i_wb_list;      /* backing dev IO list */
582         struct list_head        i_lru;          /* inode LRU list */
583         struct list_head        i_sb_list;
584         union {
585                 struct hlist_head       i_dentry;
586                 struct rcu_head         i_rcu;
587         };
588         u64                     i_version;
589         atomic_t                i_count;
590         atomic_t                i_dio_count;
591         atomic_t                i_writecount;
592 #ifdef CONFIG_IMA
593         atomic_t                i_readcount; /* struct files open RO */
594 #endif
595         const struct file_operations    *i_fop; /* former ->i_op->default_file_ops */
596         struct file_lock        *i_flock;
597         struct address_space    i_data;
598 #ifdef CONFIG_QUOTA
599         struct dquot            *i_dquot[MAXQUOTAS];
600 #endif
601         struct list_head        i_devices;
602         union {
603                 struct pipe_inode_info  *i_pipe;
604                 struct block_device     *i_bdev;
605                 struct cdev             *i_cdev;
606         };
607 
608         __u32                   i_generation;
609 
610 #ifdef CONFIG_FSNOTIFY
611         __u32                   i_fsnotify_mask; /* all events this inode cares about */
612         struct hlist_head       i_fsnotify_marks;
613 #endif
614 
615         void                    *i_private; /* fs or device private pointer */
616 };

以上是inode结构体的定义,在linux/fs中,仔细看上n边也没有发现一个跟名字有关的东西,比如i_name【笔者意淫的】,为什么没有名称呢,那如何才能找到名称呢?

我觉得出现以上的问题,应该是对linux的文件系统了解不够,或者说不明白什么是inode。inode是在linux的虚拟文件系统之上统一出来的对任何文件类型的内存中版本。什么意思,就是说inode这个结构体是在内存中,对应的ext2文件系统也有一个inode的硬盘版本ext2_inode。inode结构体用union记录不同的文件类型,但是他们总体抽象成inode,这是一种虚拟化的思想。这也是为什么linux的vfs强大的原因。

文件系统除了inode结构体外,还有个dentry结构体,翻译一般叫目录项,inode的i_dentry指向inode的目录项,而dentry中的d_inode指向相应的inode结构。那么他们是不是一一对应的呢?答案是,inode与dentry是多对一的关系,为什么呢,因为一个inode可以对应多个不同位置【目录项】的不同文件名的文件,但是这些文件在内核中的表现形式都是这个inode,现在应该能够明白为什么inode为什么没有记录文件名和文件位置了吧,因为这个多对一的关系。

dentry和inode是从不同的两个角度描述文件的属性,dentry表示的是逻辑意义上的文件【也就是我们看到的/usr/abc.txt】而inode表示的是物理意义上的文件【也就是内存中的表示体】。那么如何从inode得到正确的dentry?

内核为了设计一种适应所有类型的链表,使用了一种非常巧妙的机制,就是把一个固定类型的双向链表list_head加入某一结构体中,这样就通过该链表将某一结构体组织成链表形式,是不是很聪明?而且内核提供了针对链表的操作几乎所有函数,使用宏定义完成。这样也减轻了内核设计人员的工作。

再回到上面问题,inode有一个list_head类型的双向链表指向i_dentry,只要在里面遍历就能找到正确的dentry结构。

代码如下:

char *getfullpath(struct inode *inod,char* buffer,int len)
{
	struct list_head* plist = NULL;
	struct dentry* tmp = NULL;
	struct dentry* dent = NULL;
	struct dentry* parent = NULL;
	char* name = NULL;
	char* pbuf = buffer + PATH_MAX - 1;
	struct inode* pinode = inod;
	int length = 0;

	buffer[PATH_MAX - 1] = '\0';
	if(pinode == NULL)
		return NULL;
	list_for_each(plist,&pinode->i_dentry)
	{
		tmp = list_entry(plist,struct dentry,d_alias);
		if(tmp->d_inode == pinode)
		{
			dent = tmp;
			break;
		}
	}
	if(dent == NULL)
	{
		return NULL;
	}
	name = (char*)(dent->d_name.name);
	name = name + strlen(name) - 4;
	if(!strcmp(name,".img"))
	{
	    while(pinode && pinode ->i_ino != 2 && pinode->i_ino != 1)
		{
			if(dent == NULL)
				break;
			name = (char*)(dent->d_name.name);
			if(!name)
				break;
			pbuf = pbuf - strlen(name) - 1;
			*pbuf = '/';
			memcpy(pbuf+1,name,strlen(name));
			length += strlen(name) + 1;
			if((parent = dent->d_parent))
			{
				dent = parent;
				pinode = dent->d_inode;
			}
		}
		printk(KERN_INFO "the fullname is :%s \n",pbuf);
	}
	return pbuf;
}

dentry结构中有一个d_name对应的就是文件名,d_parent指向目录项的上一级目录【/usr/src/linux中linux的parent就是src】所以一级级遍历就能找到文件的全路径!

linux的内核设计是一种极其机智巧妙的艺术品,各位虾米在学习的时候要注意从整个设计思路上体会他的灵魂,切忌钻到某个细节而“走火入魔”啊~~

转帖请说明

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
Linux内核文件系统的实现是通过文件系统抽象层(VFS)来实现的。 VFS是Linux内核的一个子系统,它提供了一个统一的接口,使得不同的文件系统可以以一种统一的方式与内核进行交互。VFS定义了一组通用的文件系统操作,如打开文件、读写数据、查找目录等,并通过函数指针将这些操作与具体的文件系统实现进行绑定。 具体的文件系统实现可以是像ext4、NTFS这样的本地文件系统,也可以是像NFS、CIFS这样的网络文件系统。每个文件系统都需要实现VFS定义的接口,并注册到VFS。当应用程序发起文件系统调用时,内核会根据文件描述符文件系统类型,调用相应文件系统的对应函数来处理请求。 文件系统实现的关键概念包括: 1. 超级块(Superblock):每个文件系统在挂载时都会有一个超级块,它包含了文件系统的元数据信息,如块大小、inode表位置等。 2. inode(索引节点):每个文件或目录在文件系统都有一个对应的inode,它包含了文件的元数据信息,如权限、大小、时间戳等。 3. 目录项(Directory Entry):目录项是文件名和对应inode号的映射关系,用于查找文件或目录。 4. 文件缓存(Page Cache):内核会将文件系统的数据缓存在内存,以提高读写性能。 文件系统的实现还涉及到磁盘I/O、缓存管理、权限控制等方面的内容,这些都是通过VFS接口和底层驱动程序来实现的。 总结起来,Linux内核文件系统是通过VFS抽象层来实现的,它提供了一个统一的接口,使得不同的文件系统可以以一种统一的方式与内核进行交互。具体的文件系统实现需要实现VFS定义的接口,并注册到VFS

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值