Linux内核中根据inode获取文件属性

在Linux内核中,inode 是描述文件系统对象(如文件、目录等)元数据的核心数据结构。通过 inode 可以获取以下关键属性:


1. 关键属性字段(定义在 include/linux/fs.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct inode {
umode_t i_mode; // 文件类型和权限 (e.g., S_IFREG, S_IFDIR)
kuid_t i_uid; // 所有者用户ID
kgid_t i_gid; // 所有者组ID
loff_t i_size; // 文件大小(字节)
struct timespec64 i_atime; // 最后访问时间
struct timespec64 i_mtime; // 最后修改时间
struct timespec64 i_ctime; // 最后状态变更时间
unsigned long i_ino; // inode 号
dev_t i_rdev; // 设备号(特殊文件)
unsigned int i_blkbits; // 块大小(位)
blkcnt_t i_blocks; // 分配的磁盘块数
// ... 其他字段(文件系统相关私有数据等)
};

2. 获取属性的常用方法

(1) 文件类型与权限 (i_mode)

1
2
3
4
5
6
7
8
9
10
11
12
13
umode_t mode = inode->i_mode;

// 检查文件类型
if (S_ISREG(mode)) printk("常规文件");
if (S_ISDIR(mode)) printk("目录");
if (S_ISCHR(mode)) printk("字符设备");
if (S_ISBLK(mode)) printk("块设备");
if (S_ISFIFO(mode)) printk("FIFO/管道");
if (S_ISSOCK(mode)) printk("套接字");
if (S_ISLNK(mode)) printk("符号链接");

// 提取权限位(e.g., 0755)
unsigned short perm = mode & 0777;

(2) 所有权信息

1
2
3
4
5
6
kuid_t uid = inode->i_uid;  // 用户ID
kgid_t gid = inode->i_gid; // 组ID

// 转换为可读形式(需启用用户空间辅助函数)
char *user = from_kuid(&init_user_ns, uid);
char *group = from_kgid(&init_user_ns, gid);

(3) 时间戳

1
2
3
4
5
6
7
struct timespec64 atime = inode->i_atime;  // 访问时间
struct timespec64 mtime = inode->i_mtime; // 修改时间
struct timespec64 ctime = inode->i_ctime; // 元数据变更时间

// 转换为秒和纳秒
time_t atime_sec = atime.tv_sec;
long atime_nsec = atime.tv_nsec;

(4) 大小与磁盘使用

1
2
3
loff_t size = inode->i_size;          // 逻辑大小(字节)
blkcnt_t blocks = inode->i_blocks; // 分配的512B扇区数
unsigned int blksize = 1 << inode->i_blkbits; // 块大小(字节)

(5) 特殊文件信息

1
2
3
4
5
if (S_ISCHR(mode) || S_ISBLK(mode)) {
dev_t dev = inode->i_rdev; // 设备号
unsigned major = MAJOR(dev); // 主设备号
unsigned minor = MINOR(dev); // 次设备号
}

3. 示例:内核函数中的使用

以下函数展示了如何通过 inode 获取属性并打印:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <linux/fs.h>
#include <linux/printk.h>

void print_inode_info(struct inode *inode) {
// 文件类型
if (S_ISREG(inode->i_mode)) printk("Type: Regular File\n");
else if (S_ISDIR(inode->i_mode)) printk("Type: Directory\n");

// 权限(八进制)
printk("Permissions: %o\n", inode->i_mode & 0777);

// 大小和块信息
printk("Size: %lld bytes\n", inode->i_size);
printk("Blocks: %lu (512B sectors)\n", inode->i_blocks);

// 时间戳(秒级)
printk("Last Access: %lld seconds\n", inode->i_atime.tv_sec);
}

4. 注意事项

  • 上下文要求:操作 inode 通常需在内核上下文中(如系统调用处理、VFS 函数)。
  • 锁机制:访问 inode 前通常需加锁(如 inode_lock()i_rwsem 读写信号量)。
  • 文件系统差异:实际数据可能由底层文件系统通过 inode->i_op->getattr 方法动态填充。
  • 内存inode vs 磁盘inode:内核中的 inode 是内存缓存,可能与磁盘上的inode不同步(需同步机制)。

通过操作 inode 结构体,内核可以高效管理文件元数据,为文件操作提供基础支持。