linux下一切皆文件,大致可分为以下几类:目录、普通文件、硬连接、软连接、字符设备、块设备、FIFO、Socket,其在物理存储体内存储按inode和数据块存储,inode代表元数据,是除实际数据外的所有(属性)数据。根据不同的文件类型有以下几种情况:

》对于常规文件,文件的数据存储在数据块中,其他数据(即属性)存储在inode中。

》对于目录,该目录下的所有文件名和目录名存储在数据块中,注意文件名保存在它所在目录的数据块中,除文件名之外,ls -l命令看到的其它信息都保存在该文件的inode中。注意这个概念:目录也是一种文件,是一种特殊类型的文件。

》对于硬链接,其只是在硬链接所在目录的数据块中增加或修改文件名,并修改硬链接目标inode的链接数(ls显示属性的第二项),并不会增加inode或数据块。

》对于符号链接,如果目标路径名较短则直接保存在inode中以便更快地查找,如果目标路径名较长则分配一个数据块来保存。

》设备文件、FIFO和socket等特殊文件没有数据块,设备文件的主设备号和次设备号保存在inode中。

inode结构体定义在linux/fs.h中:

/*
* Keep mostly read-only and often accessed (especially for
* the RCU path lookup and 'stat' data) fields at the beginning
* of the 'struct inode'
*/
struct inode {
umode_t i_mode;
unsigned short i_opflags;
uid_t i_uid;
gid_t i_gid;
unsigned int i_flags; #ifdef CONFIG_FS_POSIX_ACL
struct posix_acl *i_acl;
struct posix_acl *i_default_acl;
#endif const struct inode_operations *i_op;
struct super_block *i_sb;
struct address_space *i_mapping; #ifdef CONFIG_SECURITY
void *i_security;
#endif /* Stat data, not accessed from path walking */
unsigned long i_ino;
/*
* Filesystems may only read i_nlink directly. They shall use the
* following functions for modification:
*
* (set|clear|inc|drop)_nlink
* inode_(inc|dec)_link_count
*/
union {
const unsigned int i_nlink;
unsigned int __i_nlink;
};
dev_t i_rdev; /* 若是设备文件,此字段将记录设备的设备号 */
struct timespec i_atime;
struct timespec i_mtime;
struct timespec i_ctime;
spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
unsigned short i_bytes;
blkcnt_t i_blocks;
loff_t i_size; #ifdef __NEED_I_SIZE_ORDERED
seqcount_t i_size_seqcount;
#endif /* Misc */
unsigned long i_state;
struct mutex i_mutex; unsigned long dirtied_when; /* jiffies of first dirtying */ struct hlist_node i_hash;
struct list_head i_wb_list; /* backing dev IO list */
struct list_head i_lru; /* inode LRU list */
struct list_head i_sb_list;
union {
struct list_head i_dentry;
struct rcu_head i_rcu;
};
atomic_t i_count;
unsigned int i_blkbits;
u64 i_version;
atomic_t i_dio_count;
atomic_t i_writecount;
const struct file_operations *i_fop; /* former ->i_op->default_file_ops */
struct file_lock *i_flock;
struct address_space i_data; #ifdef CONFIG_QUOTA
struct dquot *i_dquot[MAXQUOTAS];
#endif
struct list_head i_devices;
union {
struct pipe_inode_info *i_pipe;
struct block_device *i_bdev; /* 若是块设备,为其对应的block_device结构体指针 */
struct cdev *i_cdev; /* 若是字符设备,为其对应的cdev结构体指针 */
}; __u32 i_generation; #ifdef CONFIG_FSNOTIFY
__u32 i_fsnotify_mask; /* all events this inode cares about */
struct hlist_head i_fsnotify_marks;
#endif #ifdef CONFIG_IMA
atomic_t i_readcount; /* struct files open RO */
#endif
void *i_private; /* fs or device private pointer */
};

inode是linux管理文件系统的最基本单位,也是文件系统连接任何子目录、文件的桥梁。

ls -li显示属性各字段含义介绍

stat函数读取文件的inode,然后把inode中的各种文件属性填入一个struct stat结构体传出给调用者。ls或stat可查看inode属性。

struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for file system I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};

普通文件

~$ls -li wang
588946 -rw-rw-r-- 1 yuxi yuxi 9045 Feb 12 18:37 wang

st_ino  file_type  st_mode  st_nlink  st_uid  st_gid  st_size  st_mtime  file_name

目录

712708 drwxrwxr-x 2 yuxi yuxi    4096 Oct  6 15:52 file

st_ino  file_type  st_mode  st_nlink  st_uid  st_gid  st_size  st_mtime  dir_name

硬链接

~$ln wang hard_wang
~$ls -li wang hard_wang
588946 -rwxrwxr-x 2 yuxi yuxi 9045 Feb 12 18:37 hard_wang
588946 -rwxrwxr-x 2 yuxi yuxi 9045 Feb 12 18:37 wang

st_ino  file_type  st_mode  st_nlink  st_uid  st_gid  st_size  st_mtime  file_name

符号链接

2011 lrwxrwxrwx  1 root root          15 Mar 19 10:01 stdout -> /proc/self/fd/1

st_ino  file_type  st_mode  st_nlink  st_uid  st_gid  st_size(软链接文件名大小)  st_mtime  file_name

字符设备

1904 crw-rw-rw-  1 root tty       5,   0 Mar 19 10:01 tty

st_ino  file_type  st_mode  st_nlink  st_uid  st_gid  st_rdev  st_mtime  dev_name

块设备

7502 brw-rw----  1 root disk      8,   0 Mar 19 10:01 sda

st_ino  file_type  st_mode  st_nlink  st_uid  st_gid  st_rdev  st_mtime  dev_name

socket

9252 srw-rw-rw-  1 root root           0 Mar 19 10:01 log

st_ino  file_type  st_mode  st_nlink  st_uid  st_gid  st_size  st_mtime  file_name

inode与RAM建立连接

所有文件都是通过open或类open函数将inode与file建立联系,release将file结构体的修改更新inode。用inode填充file结构体(file为RAM结构体),实现了物理结构体与RAM结构体的分离,之后的read、write等file_operations函数直接操作file结构体即可完成对文件的所有更改。

int (*open) (struct inode *, struct file *);
extern struct file * dentry_open(struct dentry *, struct vfsmount *, int, const struct cred *);
extern int dcache_dir_open(struct inode *, struct file *);
int (*release) (struct inode *, struct file *);

file结构体定义于linux/fs.h,如下:

struct file {
/*
* fu_list becomes invalid after file_free is called and queued via
* fu_rcuhead for RCU freeing
*/
union {
struct list_head fu_list;
struct rcu_head fu_rcuhead;
} f_u;
struct path f_path;
#define f_dentry f_path.dentry
#define f_vfsmnt f_path.mnt
const struct file_operations *f_op; /*
* Protects f_ep_links, f_flags, f_pos vs i_size in lseek SEEK_CUR.
* Must not be taken from IRQ context.
*/
spinlock_t f_lock;
#ifdef CONFIG_SMP
int f_sb_list_cpu;
#endif
atomic_long_t f_count;
unsigned int f_flags;
fmode_t f_mode;
loff_t f_pos;
struct fown_struct f_owner;
const struct cred *f_cred;
struct file_ra_state f_ra; u64 f_version;
#ifdef CONFIG_SECURITY
void *f_security;
#endif
/* needed for tty driver, and maybe others */
void *private_data; #ifdef CONFIG_EPOLL
/* Used by fs/eventpoll.c to link all the hooks to this file */
struct list_head f_ep_links;
#endif /* #ifdef CONFIG_EPOLL */
struct address_space *f_mapping;
#ifdef CONFIG_DEBUG_WRITECOUNT
unsigned long f_mnt_write_state;
#endif
};

字符文件open函数调用过程记录:

在用户空间调用的open()函数传入的参数是文件路径,通过文件路径可以找到文件的inode节点,实际上inode与文件路径间建立了一一映射关系。

一个路径是/opt/file,则查找的顺序是:

1. 读出inode表中第2项,也就是根目录的inode,从中找出根目录数据块的位置

2. 从根目录的数据块中找出文件名为opt的记录,从记录中读出它的inode号

3. 读出opt目录的inode,从中找出它的数据块的位置

4. 从opt目录的数据块中找出文件名为file的记录,从记录中读出它的inode号

5. 读出file文件的inode

file即表示一个进程内打开的文件,它是与进程对应的。已打开的文件在内核中用file结构体表示,文件描述符表中的指针指向file结构体。

linux文件系统与设备驱动

应用程序和VFS之间的接口是系统调用,而VFS与磁盘文件系统以及普通设备之间的接口是file_operations结构体成员函数,这个结构体包含对文件进行打开、关闭、读写、控制的一系列函数。

由于字符设备的上层没有磁盘文件系统,所以字符设备的file_operations成员函数就直接由设备驱动提供,file_operations正是字符设备驱动的核心。

而对于块存储设备而言,ext2、fat、jffs2等文件系统中会实现针对VFS的file_operations成员函数,设备驱动层将看不到file_operations的存在。磁盘文件系统和设备驱动会将对磁盘上文件的访问最终转换成对磁盘上柱面和扇区的访问。

在设备驱动程序的设计中,一般而言,会关心结构体file和inode。

本节摘自《linux设备驱动开发详解》--宋宝华。

参考:

1. linux虚拟文件系统vfs

2. ext2文件系统了解

3. inode表原数据,存储在物理存储体上

4. 解析 Linux 中的 VFS 文件系统机制

文件存储结构inode与RAM结构建立联系的更多相关文章

  1. 【Linux】文件存储结构

    大部分的Linux文件系统(如ext2.ext3)规定,一个文件由目录项.inode和数据块组成: 目录项:包括文件名和inode节点号.  Inode:又称文件索引节点,包含文件的基础信息以及数据块 ...

  2. Innodb、MYISAM的文件存储结构

    MySQL的每个数据库都对应存放在一个与数据库同名的文件夹中,MySQL数据库文件包括MySQLserver所创建的数据库文件和MySQL所用存储引擎创建的数据库文件. 查看MySql数据库物理文件存 ...

  3. PostgreSQL的存储系统二:REDOLOG文件存储结构二

    REDOLOG文件里的用户数据和数据文件里的用户数据存储结构相同 几个月前同事给台湾一家公司培训<pg9 ad admin>时,有个学员提及WAL里记录的内容为Query时的SQL语句(比 ...

  4. SQLServer存储引擎——05.索引的结构和分类

    5. SQLServer存储引擎——索引的结构和分类 关系型数据库中以二维表来表达关系模型,表中的数据以页的形式存储在磁盘上,在SQL SERVER中,数据页是磁盘上8k的连续空间,那么,一个表的所有 ...

  5. Linux基础篇学习——Linux文件系统之文件存储与读取:inode,block,superblock

    Linux文件类型 代表符号 含义 - 常规文件,即file d directory,目录文件 b block device,块设备文件,支持以"block"为单位进行随机访问 c ...

  6. ceph rbd块存储挂载及文件存储建立

    一.rbd块存储挂载 1 创建一个OSD pool # ceph osd pool create rbd1 128 查询存储空间使用 # ceph df GLOBAL: SIZE AVAIL RAW ...

  7. Linux文件系统十问---深入理解文件存储方式(rhel6.5,EXT4)【转】

    本文转载自:https://blog.csdn.net/tongyijia/article/details/52832236 前几天在红黑联盟上看了一篇博客<Linux文件系统十问—深入理解文件 ...

  8. Kafka与RocketMq文件存储机制对比

    一个商业化消息队列的性能好坏,其文件存储机制设计是衡量一个消息队列服务技术水平和最关键指标之一. 开头问题 kafka文件结构和rocketMQ文件结构是什么样子?特点是什么? 一.目录结构 Kafk ...

  9. 海量小文件存储与Ceph实践

    海量小文件存储(简称LOSF,lots of small files)出现后,就一直是业界的难题,众多博文(如[1])对此问题进行了阐述与分析,许多互联网公司也针对自己的具体场景研发了自己的存储方案( ...

随机推荐

  1. 微信小程序API·目录

    网络 媒体 文件 数据缓存 位置 设备 界面 第三方平台 开放接口 数据 更新 多线程 监控 调试接口 日志

  2. python 文件操作与集合

    对文件的操作 1.打开文件,获取句柄 2.根据句柄操作文件 3.关闭文件 现有文档 poem.txt 一天很短, 短得来不及拥抱清晨, 就已经手握黄昏. 一年很短, 短得来不及细品初春殷红窦绿, 就要 ...

  3. tomcat官网

    http://tomcat.jaxmao.org/appdev/index.html 配置 http://www.cnblogs.com/starhu/p/5599773.html

  4. NHibernate官方文档中文版--只读实体类型(Read-only entities)

    重点 NHIbernate处理只读对象的方式可能和你在别处看到的不同.不正确的使用方式可能造成不可预料的结果. 当一个实体是只读的时候: NHIbernate不会对实体的简单属性和单向关联数据检查数据 ...

  5. 修改 CentOS 6.3 时区 和 时间

    1.查看当前时区和时间 date -R 2.CentOS中时区是以文件形式存在,当前时区文件位于 /etc/localtime 其他时区文件位于 /usr/share/zoneinfo下,其中中国时区 ...

  6. Bootstrap标签Tabs

    <!--标签--> <ul class="nav nav-tabs" role="tablist"> <li class=&quo ...

  7. 起步X5 UI模型使用的新的JAVASCRIPT UI库 DHTMLX (简称DHX)

    最近学习新版本的起步X5,发现 UI控件有很多变化,按培训师的解释,X5平台界面设计引入了新的JAVASCRIPT UI库 DHTMLX. 参考:DHX   http://www.dhtmlx.com ...

  8. projecteuler----&gt;problem=11----Largest product in a grid

    In the 2020 grid below, four numbers along a diagonal line have been marked in red. 08 02 22 97 38 1 ...

  9. Django入门与实践

    安装: 1.https://www.djangoproject.com/查找最新版本 2.pip install Django==1.10.6安装Django   创建项目: 1.打开命令行,进入想要 ...

  10. HA分布式集群一hadoop+zookeeper

    一:HA分布式配置的优势: 1,防止由于一台namenode挂掉,集群失败的情形 2,适合工业生产的需求 二:HA安装步骤: 1,安装虚拟机 1,型号:VMware_workstation_full_ ...