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

转帖请说明

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值