Skip to content

Commit 3be53a6

Browse files
committed
learning inode
1 parent 35e2d42 commit 3be53a6

File tree

1 file changed

+150
-2
lines changed

1 file changed

+150
-2
lines changed

为了工作/Linux/内核层/Linux Virtual Filesystem.md

Lines changed: 150 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ categories:
55
- 内核层
66
abbrlink: f548d964
77
date: 2024-12-24 16:05:00
8-
updated: 2024-12-25 16:10:00
8+
updated: 2024-12-25 17:30:00
99
---
1010

1111
<meta name="referrer" content="no-referrer"/>
@@ -85,7 +85,7 @@ dentry 将 inode 和 文件名关联起来,存储以下信息:
8585
1. 用于标识 inode 的整数。
8686
2. 表示文件名的字符串。
8787

88-
dentry 是目录或文件路径的特定部分。例如,对于路径 `/bin/vi`,为 `/`, `bin``vi` 创建共 3 个 dentry 对象。
88+
dentry 是目录或文件路径的特定部分。例如,对于路径 `/bin/vi`,为 `/``bin``vi` 创建共 3 个 dentry 对象。
8989

9090
dentry 在磁盘上有对应物,但对应关系不是直接的。每个文件系统都有特定的方式维护 dentry。
9191

@@ -373,6 +373,154 @@ struct buffer_head
373373
1. S_ISDIR(inode->i_mode):用于检查索引节点是否为目录。
374374
2. S_ISREG(inode->i_mode):用于检查索引节点是否为普通文件(非链接或设备文件)。
375375

376+
# inode
377+
378+
inode 是文件系统的元数据(它包含信息的信息)。inode 是磁盘上文件的唯一标识,保存文件的信息(uid、gid、访问权限、访问时间以及指向数据块的指针等)。重要的一点是,inode 不保存文件名信息,文件名由相关的 `struct dentry` 结构保存。
379+
380+
inode 用于引用磁盘上的文件。对于进程打开的文件,使用 `struct file` 结构。一个 inode 可以关联一个或多个 `struct file` 结构。多个进程可以打开同一个文件,一个进程可以多次打开同一个文件。
381+
382+
inode 既存在于内存中的 VFS 结构,也存在于磁盘中(UNIX、HFS 以及 NTFS 等)。VFS 中的 inode 由 `struct inode` 结构表示。和 VFS 中的其他结构一样,`struct inode` 是通用结构,涵盖了所有支持的文件类型的选项,甚至包括那些没有关联磁盘实体的文件类型(例如 FAT 文件系统)。
383+
384+
## inode 结构
385+
386+
`struct inode` 定义如下:
387+
388+
```c
389+
struct inode
390+
{
391+
umode_t i_mode; // i_uid 以及 i_gid:访问权限、uid 以及 gid。
392+
unsigned short i_opflags;
393+
kuid_t i_uid;
394+
kgid_t i_gid;
395+
unsigned int i_flags;
396+
397+
#ifdef CONFIG_FS_POSIX_ACL
398+
struct posix_acl *i_acl;
399+
struct posix_acl *i_default_acl;
400+
#endif
401+
402+
const struct inode_operations *i_op; // 指向结构 inode_operations 的指针。
403+
struct super_block *i_sb; // inode 所属的文件系统的超级块结构。
404+
struct address_space *i_mapping; // i_mapping->a_ops 包含指向 struct address_space_operations 的指针。
405+
406+
#ifdef CONFIG_SECURITY
407+
void *i_security;
408+
#endif
409+
410+
/* Stat data, not accessed from path walking */
411+
unsigned long i_ino; // inode 的编号(在文件系统内唯一标识 inode)。
412+
/*
413+
* Filesystems may only read i_nlink directly. They shall use the
414+
* following functions for modification:
415+
*
416+
* (set|clear|inc|drop)_nlink
417+
* inode_(inc|dec)_link_count
418+
*/
419+
420+
// 使用此 inode 的名称条目(dentry)的数量;对于没有链接(既没有硬链接也没有符号链接)的文件系统,这个值总是设置为 1。
421+
union
422+
{
423+
const unsigned int i_nlink;
424+
unsigned int __i_nlink;
425+
};
426+
427+
dev_t i_rdev; // 挂载的文件系统所在的设备。
428+
loff_t i_size; // 文件/目录等的大小(以字节为单位)。
429+
struct timespec64 i_atime; // 访问时间。
430+
struct timespec64 i_mtime; // 修改时间。
431+
struct timespec64 i_ctime; // 创建时间。
432+
spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
433+
unsigned short i_bytes;
434+
u8 i_blkbits; // 块大小使用的比特数 == log2(块大小)。
435+
u8 i_write_hint;
436+
blkcnt_t i_blocks; // 文件使用的块数(所有块,不仅仅是数据块)。这仅由配额子系统使用。
437+
438+
#ifdef __NEED_I_SIZE_ORDERED
439+
seqcount_t i_size_seqcount;
440+
#endif
441+
442+
/* Misc */
443+
unsigned long i_state;
444+
struct rw_semaphore i_rwsem;
445+
446+
unsigned long dirtied_when; /* jiffies of first dirtying */
447+
unsigned long dirtied_time_when;
448+
449+
struct hlist_node i_hash;
450+
struct list_head i_io_list; /* backing dev IO list */
451+
#ifdef CONFIG_CGROUP_WRITEBACK
452+
struct bdi_writeback *i_wb; /* the associated cgroup wb */
453+
454+
/* foreign inode detection, see wbc_detach_inode() */
455+
int i_wb_frn_winner;
456+
u16 i_wb_frn_avg_time;
457+
u16 i_wb_frn_history;
458+
#endif
459+
struct list_head i_lru; /* inode LRU list */
460+
struct list_head i_sb_list;
461+
struct list_head i_wb_list; /* backing dev writeback list */
462+
union
463+
{
464+
struct hlist_head i_dentry;
465+
struct rcu_head i_rcu;
466+
};
467+
atomic64_t i_version;
468+
atomic64_t i_sequence; /* see futex */
469+
atomic_t i_count; // inode 计数器,指示有多少内核组件在使用它。
470+
atomic_t i_dio_count;
471+
atomic_t i_writecount;
472+
#if defined(CONFIG_IMA) || defined(CONFIG_FILE_LOCKING)
473+
atomic_t i_readcount; /* struct files open RO */
474+
#endif
475+
union
476+
{
477+
const struct file_operations *i_fop; // 指向结构 file_operations 的指针。former ->i_op->default_file_ops
478+
void (*free_inode)(struct inode *);
479+
};
480+
struct file_lock_context *i_flctx;
481+
struct address_space i_data;
482+
struct list_head i_devices;
483+
union
484+
{
485+
struct pipe_inode_info *i_pipe;
486+
struct cdev *i_cdev;
487+
char *i_link;
488+
unsigned i_dir_seq;
489+
};
490+
491+
__u32 i_generation;
492+
493+
#ifdef CONFIG_FSNOTIFY
494+
__u32 i_fsnotify_mask; /* all events this inode cares about */
495+
struct fsnotify_mark_connector __rcu *i_fsnotify_marks;
496+
#endif
497+
498+
#ifdef CONFIG_FS_ENCRYPTION
499+
struct fscrypt_info *i_crypt_info;
500+
#endif
501+
502+
#ifdef CONFIG_FS_VERITY
503+
struct fsverity_info *i_verity_info;
504+
#endif
505+
506+
void *i_private; /* fs or device private pointer */
507+
} __randomize_layout;
508+
```
509+
510+
一些可用于处理 inode 的函数如下:
511+
512+
1. new_inode():创建新的 inode,将 i_nlink 字段设置为 1,并初始化 i_blkbits, i_sb 和 i_dev。
513+
2. insert_inode_hash():将 inode 添加到 inode 哈希表中。这个调用的一个有趣的效果是,如果 inode 被标记为脏,它将被写入磁盘。
514+
3. mark_inode_dirty():将 inode 标记为脏,稍后它将被写入磁盘。
515+
4. iget_locked():从磁盘加载具有给定编号的 inode,如果它尚未加载。
516+
5. unlock_new_inode():与 iget_locked() 一起使用,释放对 inode 的锁定。
517+
6. iput():告诉内核对 inode 的操作已经完成。若没有其他进程在使用,它将被销毁(如果被标记为脏,则写入磁盘后再销毁)。
518+
7. make_bad_inode():告诉内核该 inode 无法使用;通常在从磁盘读取 inode 时发现无法读取的情况下使用,表示该 inode 无效。
519+
520+
## inode 操作
521+
522+
TODO
523+
376524
# 参考文章
377525

378526
1. [Linux Kernel Teaching — The Linux Kernel documentation](https://linux-kernel-labs.github.io/refs/heads/master/)

0 commit comments

Comments
 (0)