Chinaunix
标题:
明明白白我的心--fs series
[打印本页]
作者:
mtloveft
时间:
2010-08-17 20:16
标题:
明明白白我的心--fs series
明明白白我的心--fs series
文章地址:
http://blog.chinaunix.net/u3/114767/showart_2292149.html
作者:GTT
本文档归属
http://oldtown.cublog.cn/.
转载请注明出处!
请提出宝贵意见Mail:mtloveft@hotmail.com
Linux Version:2.6.33
提示:本文是关于file system 实现的介绍!
明明白白我的心--fs series系列是关于介绍linux文件系统的。学习linux文件系统普通都是从
VFS下手,然后再学习具体的文件系统,其实顺序有点问题,如果按照linux文件系统的发展学习,对
VFS可以很容易掌握的。
先整体看看文件系统的构成图
可以看出VSF在文件系统中是出于中心位置。VSF-即Virtual File System ,其它实际的文件系统可以看作是VFS的实例,而VSF可以看作是FS的抽象。
作者:
mtloveft
时间:
2010-08-17 20:19
明明白白我的心--fs series(2)
文章地址:
http://blog.chinaunix.net/u3/114767/showart_2292171.html
提起文件系统,基本都会想到harddisk上的文件系统,harddisk可以分区,每个分区可以安装一个文件系统,
关于分区,请参看下图
最初的一个扇区是启动扇区,只有512 Byte的大小。其中就有关于分区的信息,还有OS的引导代码。
minixFS的format如下
分区被分成Block进行管理,也就是块管理。
boot Block :引导块,负者OS的引导。
super Block :超级块,管理整个FS的信息
inode bitMaps :i节点位图块,可以有n个块,块数据中,每个bit位代表一个inode,1代表inode使用,0代表未使用
block bitMaps :数据块位图,可以有n个块,块数据中,每个bit位代表一个数据块,1代表数据块使用,0代表未使用
inodes blocks :inode数据结构占有的块,
data blocks :数据块,实际文件的数据,或者目录的子文件名和子目录名
再来看看ext2Fs的format
是不是MinixFS和Ext2FS很像啊,其实Ext2名字就能看出来,他是根据minix进行的第二次扩展。所以叫ext2,在minixFS的基础上又包了一层BlockGroup。其它没有什么特别的了。
上一篇介绍的VSF就是在这些文件系统之后抽象出来的,不是先有VSF的。最初是用minix1.0, 后来进行扩展,再扩展,再再扩展,又再再扩展,即ext,ext2,ext3, ext4。
作者:
mtloveft
时间:
2010-08-17 20:25
明明白白我的心--fs series(3)
文章地址:
http://blog.chinaunix.net/u3/114767/showart_2292187.html
先来看看minix在早期linux版本中的实现,以下代码是linux0.11版本的。
超级块的定义如下
struct super_block {
unsigned short s_ninodes;
unsigned short s_nzones;
unsigned short s_imap_blocks;
unsigned short s_zmap_blocks;
unsigned short s_firstdatazone;
unsigned short s_log_zone_size;
unsigned long s_max_size;
unsigned short s_magic;
/* These are only in memory */
struct buffer_head * s_imap[8];
struct buffer_head * s_zmap[8];
unsigned short s_dev;
struct m_inode * s_isup;
struct m_inode * s_imount;
unsigned long s_time;
struct task_struct * s_wait;
unsigned char s_lock;
unsigned char s_rd_only;
unsigned char s_dirt;
}
复制代码
相关说明如下
字段名称 説明
s_ninodes i节点数
s_nzones 数据块数
s_imap_blocks i 节点位图占有的块数
s_zmap_blocks 数据块位图占有的块数
s_firstdatazone 数据块中第一个数据块的块号
s_log_zone_size disk块数/逻辑块
s_max_size 最大文件长度
s_magic 文件系统的幻数
所以super block 对于FS来说是最重要的数据结构了。
通过SB可以知道Block的安排了。当然就知道了FS的大小了。通过inode bitmaps 就可以知道那个inode还没有被使用,通过block bitmaps就知道数据块中还有哪块没有被使用。整个文件系统就可以被管理了。
i节点的定义如下
struct m_inode {
unsigned short i_mode;
unsigned short i_uid;
unsigned long i_size;
unsigned long i_mtime;
unsigned char i_gid;
unsigned char i_nlinks;
unsigned short i_zone[9];
/* these are in memory also */
struct task_struct * i_wait;
unsigned long i_atime;
unsigned long i_ctime;
unsigned short i_dev;
unsigned short i_num;
unsigned short i_count;
unsigned char i_lock;
unsigned char i_dirt;
unsigned char i_pipe;
unsigned char i_mount;
unsigned char i_seek;
unsigned char i_update;
}
复制代码
相关说明如下
字段名称 説明
i_mode 文件类型和属性
i_uid 用户 id
i_size 文件长度
i_mtime 修改时间
i_gid 组id
i_nlinks 链接数
i_zone[9] 文件占用的逻辑快数组
zone[0]-zone[6]是直接块号
zone[7]是一次间接块号
zone[8]是二次间接块号
根据i_zone, 知道了i节点,就知道了对应的数据放到了什么位置。
还有关于目录项的定义
struct dir_entry {
unsigned short inode;
char name[NAME_LEN];
}
复制代码
文件的定义如下
struct file {
unsigned short f_mode;
unsigned short f_flags;
unsigned short f_count;
struct m_inode * f_inode;
off_t f_pos;
}
复制代码
看到了什么,文件中有inode的指针。对文件的动作,最好都会根据inode来对实际数据进行操作。
再来看看minixFS是如何进行数据管理的
i3 即inode3如果他是个目录节点的话,它的i_zone[0]将是一个目录数据块号,数据内容将是dir_entry数据结构的数组。这样目录下的
文件名和目录名将全部能产看到。如果目录下文件或者子目录很多的话,可以通过i_zone[7]继续查找到,还有根多的子文件或者
子目录的话,就通过i_zone[8]进行2次间接查找。
D3 即dir_entry3 它的inode 指向i2, 而i2是个二进制文件,那么i_zone[0]将指向一个有实际数据的数据块。
如果知道根节点,那么顺着根节点,可以找到所有的文件和目录,所以根节点是必须设定的。
给定一个i节点,这个i节点下的文件和目录也将可以查找到。有了理论,程序就很容易实现了。
而文件的数据结构struct file根inode关联起来,这样文件的读,写就根据inode可以找到数据的位置了。
minix得结构还是比较简单的,如果了解了minix,其他再复杂的文件系统,也会很快理解的了。
data block 的号码是逻辑号码,读写数据就直接交给harddisk的驱动程序处理,驱动程序根据分区和data block 的号码算出实际的扇区号进行读写。
读出的数据先放到buffer cache,写入的数据也是先放到buffer cache.这样,文件系统就只要和buffer cache 交互就可以了,可以提高工作效率。
我认为minix的几个问题是文件放置的效率,还有,如果super block坏了的话文件系统就崩溃了,可以说无法修复的。因为无法知道根接点的数据
放到什么位置了。安区性问题很严重。当然minixFS 得容量也很小。不过对于教学研究,是很值得研究的文件系统。
作者:
mtloveft
时间:
2010-08-17 20:29
明明白白我的心--fs series(4)
文章地址:
http://blog.chinaunix.net/u3/114767/showart_2292196.html
再来看看linux 2.6.33中ext2的结构图
super block的定义如下
struct ext2_super_block {
__le32 s_inodes_count; /* Inodes count */
__le32 s_blocks_count; /* Blocks count */
__le32 s_r_blocks_count; /* Reserved blocks count */
__le32 s_free_blocks_count; /* Free blocks count */
__le32 s_free_inodes_count; /* Free inodes count */
__le32 s_first_data_block; /* First Data Block */
__le32 s_log_block_size; /* Block size */
__le32 s_log_frag_size; /* Fragment size */
__le32 s_blocks_per_group; /* # Blocks per group */
__le32 s_frags_per_group; /* # Fragments per group */
__le32 s_inodes_per_group; /* # Inodes per group */
__le32 s_mtime; /* Mount time */
__le32 s_wtime; /* Write time */
__le16 s_mnt_count; /* Mount count */
__le16 s_max_mnt_count; /* Maximal mount count */
__le16 s_magic; /* Magic signature */
__le16 s_state; /* File system state */
__le16 s_errors; /* Behaviour when detecting errors */
__le16 s_minor_rev_level; /* minor revision level */
__le32 s_lastcheck; /* time of last check */
__le32 s_checkinterval; /* max. time between checks */
__le32 s_creator_os; /* OS */
__le32 s_rev_level; /* Revision level */
__le16 s_def_resuid; /* Default uid for reserved blocks */
__le16 s_def_resgid; /* Default gid for reserved blocks */
__le32 s_first_ino; /* First non-reserved inode */
__le16 s_inode_size; /* size of inode structure */
__le16 s_block_group_nr; /* block group # of this superblock */
__le32 s_feature_compat; /* compatible feature set */
__le32 s_feature_incompat; /* incompatible feature set */
__le32 s_feature_ro_compat; /* readonly-compatible feature set */
__u8 s_uuid[16]; /* 128-bit uuid for volume */
char s_volume_name[16]; /* volume name */
char s_last_mounted[64]; /* directory where last mounted */
__le32 s_algorithm_usage_bitmap;/* For compression */
__u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
__u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
__u16 s_padding1;
__u8 s_journal_uuid[16]; /* uuid of journal superblock */
__u32 s_journal_inum; /* inode number of journal file */
__u32 s_journal_dev; /* device number of journal file */
__u32 s_last_orphan; /* start of list of inodes to delete */
__u32 s_hash_seed[4]; /* HTREE hash seed */
__u8 s_def_hash_version; /* Default hash version to use */
__u8 s_reserved_char_pad;
__u16 s_reserved_word_pad;
__le32 s_default_mount_opts;
__le32 s_first_meta_bg; /* First metablock block group */
__u32 s_reserved[190]; /* Padding to the end of the block */
};
复制代码
inode的定义如下
struct ext2_inode {
__le16 i_mode; /* File mode */
__le16 i_uid; /* Low 16 bits of Owner Uid */
__le32 i_size; /* Size in bytes */
__le32 i_atime; /* Access time */
__le32 i_ctime; /* Creation time */
__le32 i_mtime; /* Modification time */
__le32 i_dtime; /* Deletion Time */
__le16 i_gid; /* Low 16 bits of Group Id */
__le16 i_links_count; /* Links count */
__le32 i_blocks; /* Blocks count */
__le32 i_flags; /* File flags */
union {
struct {
__le32 l_i_reserved1;
} linux1;
struct {
__le32 h_i_translator;
} hurd1;
struct {
__le32 m_i_reserved1;
} masix1;
} osd1; /* OS dependent 1 */
__le32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
__le32 i_generation; /* File version (for NFS) */
__le32 i_file_acl; /* File ACL */
__le32 i_dir_acl; /* Directory ACL */
__le32 i_faddr; /* Fragment address */
union {
struct {
__u8 l_i_frag; /* Fragment number */
__u8 l_i_fsize; /* Fragment size */
__u16 i_pad1;
__le16 l_i_uid_high; /* these 2 fields */
__le16 l_i_gid_high; /* were reserved2[0] */
__u32 l_i_reserved2;
} linux2;
struct {
__u8 h_i_frag; /* Fragment number */
__u8 h_i_fsize; /* Fragment size */
__le16 h_i_mode_high;
__le16 h_i_uid_high;
__le16 h_i_gid_high;
__le32 h_i_author;
} hurd2;
struct {
__u8 m_i_frag; /* Fragment number */
__u8 m_i_fsize; /* Fragment size */
__u16 m_pad1;
__u32 m_i_reserved2[2];
} masix2;
} osd2; /* OS dependent 2 */
};
复制代码
而目录项的定义如下
struct ext2_dir_entry_2 {
__le32 inode; /* Inode number */
__le16 rec_len; /* Directory entry length */
__u8 name_len; /* Name length */
__u8 file_type;
char name[EXT2_NAME_LEN]; /* File name */
};
复制代码
再来看看ext2FS是如何进行数据管理的
看上去只是比minixFS,多了一个3次间接索引。这样ext2FS的单个文件的Size可以更大。
上图中b-no等我就是随便起的名字,意思就是数据块的内容是block number.
追加一些内容,忘了写了,就是在现在版本中对文件的定义,因为不说这个队VFS的实现就有点困难了。
定义如下
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;
spinlock_t f_lock; /* f_ep_links, f_flags, no IRQ */
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
}
复制代码
其它Field可以先不考虑,但是struct path f_path这项得关注。
他的定义如下
struct path {
struct vfsmount *mnt;
struct dentry *dentry;
};
复制代码
为什么要提这个呢,因为他包含了一个dentry的指针,而dentry又有inode的指针。
这样有和早期MinixFS的实现基本对应上了,早期MinixFS的文件结构中直接放的inode指针。其实就是换汤不换药。这样对以后抽象出来VFS很关键的。
作者:
mtloveft
时间:
2010-08-17 20:31
本帖最后由 mtloveft 于 2010-08-24 19:23 编辑
明明白白我的心--fs series(5)
文章地址:
http://blog.chinaunix.net/u3/114767/showart_2300161.html
根据minix和ext2文件系统结构知识我们可以抽象出以下概念。
对文件操作最终会转化为对inode得操作,因为inode才知道数据放置什么位置,
目录也是文件,是特殊的文件,他的inode对应的数据内容是目录数据的集合。
也就是dentry,通过dentry就可以知道子目录和子文件的名称和对应的inode了。
而inode又被super block来管理,super block 可以知道还有多少inode没被使用,同时可以分配inode,销毁inode.
只要知道了root inode ,文件系统下的所有文件和目录都可以顺着root inode找到。
所以现在版本的linux kernel 就是按照这么个逻辑抽象出来了几个数据结构。
file_system_type :文件系统
super_block :超级块
inode :i节点
dentry :目录项
file :文件
早期的linux 只有一个文件系统,当然也就无文件系统下再安装文件系统的概念了。
而现在版本linux都可以在文件系统下再安装文件系统。也就是mount命令。
这就出现了有一个概念,vfsmount, 为什么会有这个数据结构,
其实就是为了管理安装了的文件系统,file_system_type只是定义了文件系统,
每个安装的文件系统可以看作是file_system_type的instance。
先来看看整体概念图
俺的系统中,EA有时候简体中文会乱码。只能用日文的。NND。
这样文件系统的结构定义不用说你也知道他怎么定义的啦,
上定义:
struct file_system_type {
const char *name;
int fs_flags;
int (*get_sb) (struct file_system_type *, int, const char *, void *, struct vfsmount *);
void (*kill_sb) (struct super_block *);
struct module *owner;
struct file_system_type *next;
struct list_head fs_supers;
struct lock_class_key s_lock_key;
struct lock_class_key s_umount_key;
struct lock_class_key i_lock_key;
struct lock_class_key i_mutex_key;
struct lock_class_key i_mutex_dir_key;
struct lock_class_key i_alloc_sem_key;
};
复制代码
稍微解释一下,
get_sb, kill_sb当然就是为了得到和销毁super block 了。name是unique的,因为文件系统可以mount多次,所以,
对于一个文件系统,要管理n个super block,所以这些super block 就被fs_supers这个链表链接起来,方便查找。
Linux系统中有多个文件系统,为了对文件系统的管理,注册文件系统时,把所有的文件系统都链接到file_systems
这个结构上,通过next连接的。其他字段可以先不用考虑,影响不大。
结构关系图如下
下面说说文件系统注册,
为了使用文件系统,必须要进行文件系统注册。注册的过程比较简单,就是把
定义的file_system_type结构链接到file_systems上。
根据name 到file_systems上查找,没找到的话,把file_system_type结构加入到file_systems这个所谓的链上,
当然找到了的话就说明是重复注册了。
注册的代码如下
int register_filesystem(struct file_system_type * fs)
{
int res = 0;
struct file_system_type ** p;
BUG_ON(strchr(fs->name, '.'));
if (fs->next)
return -EBUSY;
INIT_LIST_HEAD(&fs->fs_supers);
write_lock(&file_systems_lock);
p = find_filesystem(fs->name, strlen(fs->name));
if (*p)
res = -EBUSY;
else
*p = fs;
write_unlock(&file_systems_lock);
return res;
}
复制代码
find_filesystem的代码如下,比较简单,不废话了。
static struct file_system_type **find_filesystem(const char *name, unsigned len)
{
struct file_system_type **p;
for (p=&file_systems; *p; p=&(*p)->next)
if (strlen((*p)->name) == len &&
strncmp((*p)->name, name, len) == 0)
break;
return p;
}
复制代码
注销文件系统的代码就更简单了。就不贴出来了。
作者:
mtloveft
时间:
2010-08-24 19:19
明明白白我的心--fs series
文章地址
明明白白我的心--fs series(1) :
http://blog.chinaunix.net/u3/114767/showart_2292149.html
明明白白我的心--fs series(2) :
http://blog.chinaunix.net/u3/114767/showart_2292171.html
明明白白我的心--fs series(3) :
http://blog.chinaunix.net/u3/114767/showart_2292187.html
明明白白我的心--fs series(4) :
http://blog.chinaunix.net/u3/114767/showart_2292196.html
明明白白我的心--fs series(5) :
http://blog.chinaunix.net/u3/114767/showart_2300161.html
明明白白我的心--fs series(6) :
http://blog.chinaunix.net/u3/114767/showart_2300171.html
明明白白我的心--fs series(7) :
http://blog.chinaunix.net/u3/114767/showart_2300174.html
明明白白我的心--fs series( 8 ) :
http://blog.chinaunix.net/u3/114767/showart_2300176.html
明明白白我的心--fs series(9) :
http://blog.chinaunix.net/u3/114767/showart_2300215.html
明明白白我的心--fs series(10) :
http://blog.chinaunix.net/u3/114767/showart_2301357.html
明明白白我的心--fs series(11) :
http://blog.chinaunix.net/u3/114767/showart_2306935.html
明明白白我的心--fs series(12) :
http://blog.chinaunix.net/u3/114767/showart_2306955.html
欢迎光临 Chinaunix (http://bbs.chinaunix.net/)
Powered by Discuz! X3.2