安庆

导航

linux 2.6.32文件系统 fd与file*之间的关系

给定如下一定情况:

crash> files
PID: 7739   TASK: ffff8817facd2100  CPU: 11  COMMAND: "slabtop"
ROOT: /    CWD: /
 FD       FILE            DENTRY           INODE       TYPE PATH
  0 ffff881810117680 ffff880c115a5cc0 ffff881811fa7a78 CHR  /dev/null
  1 ffff880af6bf2200 ffff88180c64e440 ffff88180dc02438 REG  /dev/shm/zxdfs/moni_sys.log
  2 ffff88180ef619c0 ffff881811a263c0 ffff880c0eabf118 CHR  /dev/console
  3 ffff880c9ddbba80 ffff8818014b1540 ffff88100a8117f8 REG  /proc/slabinfo---------------请注意,第二列就是对应的file*,第三列就是dentry,第四列就是对应的inode,用来验证

比如对于fd为3,如何快速获取对应的file* 信息?虽然这个命令输出的时候,第二列就是对应的file*,第三列就是dentry,第四列就是对应的inode,但是今天我们通过代码找到的file*是否正确。

对于fd来说,一般会根据 fget_light-->fcheck_files来获取file*,(注意,这里无关fget 还是 fget_light,因为最终都是调用fcheck_files)

结构就是当前进程task中的:

struct files_struct *files = current->files;
然后根据这个files_struct成员,找到fdt指针:
static inline struct file * fcheck_files(struct files_struct *files, unsigned int fd)
{
    struct file * file = NULL;
    struct fdtable *fdt = files_fdtable(files);

    if (fd < fdt->max_fds)
        file = rcu_dereference(fdt->fd[fd]);
    return file;
}

fdt中的fd数组中,就是按照fd下标存放的file*指针,如下:

crash> task
PID: 7739   TASK: ffff8817facd2100  CPU: 11  COMMAND: "slabtop"

crash> struct task_struct.files ffff8817facd2100
  files = 0xffff88130c8bec00
crash> struct fdtable.fd 0xffff88126d2f4900
  fd = 0xffff880c976ad000


crash> rd 0xffff880c976ad000 4
ffff880c976ad000:  ffff881810117680 ffff880af6bf2200   .v......."......
ffff880c976ad010:  ffff88180ef619c0 ffff880c9ddbba80   ................

所以对于fd为3来说,取到的file*指针就是ffff880c9ddbba80   ,(这个指针也和我们files命令打印的一致)我们来验证一下这个file*指针:

crash> struct file.f_path.dentry ffff880c9ddbba80
  f_path.dentry = 0xffff8818014b1540
crash> struct dentry.d_iname 0xffff8818014b1540
  d_iname = "slabinfo\000_offset\000ndler.py\000m\000\000\000\000"

d_iname就是对应的文件路径最后一段文件名,说明我们取的file*指针是对了,有了file* 指针,我们就可以将对应的vfs的其他结构全部串起来。

 不过需要注意的是,操作这个fdt的时候,需要关注rcu锁,具体可以查看files.txt里面的说明,获取到的file*指针,如果

if (atomic_long_inc_not_zero(&file->f_count))
*fput_needed = 1;

这个满足的话,是需要put的,否则file*指针不能用。也就是说,当file->f_count为0时,是不直接增加计数的,这个和pagecache中的lockless用法一样。

取到的file指针,用rcu保证有效性,然后这个get之后,用file->f_count来保证计数的有效性。

其实,crash中的files命令,除了能快速查看到对应的file*,dentry,inode等,带参数的files 命令还有更多的输出:

crash> files -d ffff8818014b1540
     DENTRY           INODE           SUPERBLK     TYPE PATH
ffff8818014b1540 ffff88100a8117f8 ffff880c1188cc00 REG  /.root_tmpfs/proc/slabinfo

具体可以hlep files 来验证。

posted on 2018-08-27 10:44  _备忘录  阅读(414)  评论(0编辑  收藏  举报