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中的:
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 来验证。