文件系统----概述(Kernel-2.4)

一、文件系统在操作系统中的位置

在操作系统中,从两个角度看文件系统,

        用来管理文件的系统。----用户角度

        定义并实现了对文件操作的机制。----系统调用

linux为了支持各种不同的文件系统,提供了统一的、抽象的、虚拟的文件系统界面。----VFS。

VFS的主体是struct file_operations{}.

二、文件系统的逻辑结构

文件系统中的文件在内存中是以struct file来“描述”的。而file结构中的dentry和inode从不同角度描述文件的属性,file_operations提供了文件操作的不同方法。

1.dentry逻辑意义上的文件描述及dentry的操作方法dentry_operations。

struct dentry {
____atomic_t d_count;
____unsigned int d_flags;
____struct inode  * d_inode;____/* Where the name belongs to - NULL is negative */
____struct dentry * d_parent;___/* parent directory */
____struct list_head d_vfsmnt;
____struct list_head d_hash;____/* lookup hash list */
____struct list_head d_lru;_____/* d_count = 0 LRU list */
____struct list_head d_child;___/* child of parent list */
____struct list_head d_subdirs;_/* our children */
____struct list_head d_alias;___/* inode alias list */
____struct qstr d_name;
____unsigned long d_time;_______/* used by d_revalidate */
____struct dentry_operations  *d_op;
____struct super_block * d_sb;__/* The root of the dentry tree */
____unsigned long d_reftime;____/* last time referenced */
____void * d_fsdata;________/* fs-specific data */
____unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */
};                                                                                

2.inode物理意义上的文件描述及inode的操作方法inode_operations。

struct inode {
____struct list_head____i_hash;
____struct list_head____i_list;
____struct list_head____i_dentry;
____
____struct list_head____i_dirty_buffers;

____unsigned long_______i_ino;
____atomic_t________i_count;
____kdev_t__________i_dev;
____umode_t_________i_mode;
____nlink_t_________i_nlink;
____uid_t___________i_uid;
____gid_t___________i_gid;
____kdev_t__________i_rdev;
____loff_t__________i_size;
____time_t__________i_atime;
____time_t__________i_mtime;
____time_t__________i_ctime;
____unsigned long_______i_blksize;
____unsigned long_______i_blocks;
____unsigned long_______i_version;
____struct semaphore____i_sem;
____struct semaphore____i_zombie;
____struct inode_operations_*i_op;
____struct file_operations__*i_fop;_/* former ->i_op->default_file_ops */
____struct super_block__*i_sb;
____wait_queue_head_t___i_wait;                                          
____struct file_lock____*i_flock;
____struct address_space____*i_mapping;
____struct address_space____i_data;_
____struct dquot________*i_dquot[MAXQUOTAS];
____struct pipe_inode_info__*i_pipe;
____struct block_device_*i_bdev;

____unsigned long_______i_dnotify_mask; /* Directory notify events */
____struct dnotify_struct___*i_dnotify; /* for directory notifications */

____unsigned long_______i_state;

____unsigned int________i_flags;
____unsigned char_______i_sock;

____atomic_t________i_writecount;                                        
____unsigned int________i_attr_flags;
______u32___________i_generation;
____union {
________struct minix_inode_info_____minix_i;
________struct ext2_inode_info______ext2_i;
________struct hpfs_inode_info______hpfs_i;
________struct ntfs_inode_info______ntfs_i;
________struct msdos_inode_info_____msdos_i;
________struct umsdos_inode_info____umsdos_i;
________struct iso_inode_info_______isofs_i;
________struct nfs_inode_info_______nfs_i;
________struct sysv_inode_info______sysv_i;
________struct affs_inode_info______affs_i;
________struct ufs_inode_info_______ufs_i;
________struct efs_inode_info_______efs_i;
________struct romfs_inode_info_____romfs_i;
________struct shmem_inode_info_____shmem_i;
________struct coda_inode_info______coda_i;
________struct smb_inode_info_______smbfs_i;
________struct hfs_inode_info_______hfs_i;
________struct adfs_inode_info______adfs_i;
________struct qnx4_inode_info______qnx4_i;
________struct bfs_inode_info_______bfs_i;
________struct udf_inode_info_______udf_i;
________struct ncp_inode_info_______ncpfs_i;
________struct proc_inode_info______proc_i;
________struct socket___________socket_i;
________struct usbdev_inode_info        usbdev_i;
________void________________*generic_ip;
____} u;
};

每个inode都有一个i节点号,在一个文件系统中,每个i节点号是唯一的。内核中有时会使用i节点号和节点号的hash值一起寻找inode结构。

3.file_opertaions

三、文件系统与进程之间的关系

进程中通过open,建立文件系统与进程之间的连接,这种连接以一个file数据结构为代表,更确切的应该是file中的file_operations结构,dentry结构中的dentry_operations,inode结构中的inode_operations。

dentry_operations和inode_operations只在文件操作的“底层”使用,不像file_operations作为各种文件系统操作的集合。

struct file_operations {
____struct module *owner;
____loff_t (*llseek) (struct file *, loff_t, int);
____ssize_t (*read) (struct file *, char *, size_t, loff_t *);                       
____ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
____int (*readdir) (struct file *, void *, filldir_t);
____unsigned int (*poll) (struct file *, struct poll_table_struct *);
____int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
____int (*mmap) (struct file *, struct vm_area_struct *);
____int (*open) (struct inode *, struct file *);
____int (*flush) (struct file *);
____int (*release) (struct inode *, struct file *);
____int (*fsync) (struct file *, struct dentry *, int datasync);
____int (*fasync) (int, struct file *, int);
____int (*lock) (struct file *, int, struct file_lock *);
____ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);
____ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
};

下面是open系统调用的详细的过程:

最终open系统调用会执行想要打开文件所属的文件系统中的file_operations中的open函数。

========fs/open.c========
asmlinkage long sys_open(const char * filename, int flags, int mode)
{
    ...
    fd = get_unused_fd();
    if (fd >= 0) {
        struct file *f = filp_open(tmp, flags, mode);
        fd_install(fd, f);
    ...
    return fd;
}

struct file *filp_open(const char * filename, int flags, int mode)
{
    ...
    dentry_open(nd.dentry, nd.mnt, flags);
    ...
}

struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
{
    ____struct file * f;
    ....
    ____f = get_empty_filp();
    ....
    if (f->f_op && f->f_op->open) {    
____error = f->f_op->open(inode,f);
    ....
    }
    f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);

    return f;
}

四、文件系统的层次结构

文件系统层包含:

  • 磁盘文件
  • 设备文件
  • 特殊文件

磁盘文件:所谓“文件”就是按一定的组织形式存储在介质上的信息,所以一个“文件”其实包含了两方面的信息,一是存储的数据本身,还有就是关于该文件的组织和管理信息

设备文件:设备文件同样包含有用于组织和管理的信息,同样有存储介质上的索引节点和目录项,但却不一定有存储着的数据。

特殊文件:特殊文件在内存中有inode数据结构和dentry数据结构,但不一定在存储介质上有索引节点和目录项。特殊文件一般与外部设备无关,所涉及的介质通常是内存和CPU。

以上三种类型的文件,有一个共同点,就是他们都有一些关于组织和管理的信息。因此每种文件都含有一个inode。

以Ext2为例,磁盘上的记录块(扇区),一部分用于索引节点,一部分用于文件的数据。

虽然在inode结构中包含了部分文件组织和管理的信息,但还有一项关键的信息,文件名,并不在其中。显然我们需要一种机制,通过文件名,就可以找到文件在磁盘中的索引节点,从而在内存中建立起代表该文件的inode结构。这种机制就是文件系统的目录树

文件系统的目录树,包含有从“/”根节点开始,中间目录以及最底层的“叶子”节点。中间目录,其实也是一种文件,是一种特殊的磁盘文件,文件名就是目录名,也有索引节点和数据部分,所不同的是数据部分的内容只包含“目录项”。

以Ext2文件系统为例,目录项就是ext2_dir_entry。dentry与ext2_dir_entry_2之间和inode与ext2_inode之间,其实是VFS与具体Ext2文件系统之间的对应关系,前者除了包含动态信息外,还是对后者的抽象和扩充。

VFS                file/inode/dentry/superblock

-----------------------------------

Ext2/Ext4        ext2_inode/ext2_dir_entry_2/ext2_super_block

/*                                                    
 * Structure of an inode on the disk                  
 */                                                   
struct ext2_inode {                                   
______u16___i_mode;_____/* File mode */               
______u16___i_uid;______/* Low 16 bits of Owner Uid */
______u32___i_size;_____/* Size in bytes */           
______u32___i_atime;____/* Access time */             
______u32___i_ctime;____/* Creation time */           
______u32___i_mtime;____/* Modification time */       
______u32___i_dtime;____/* Deletion Time */           
______u16___i_gid;______/* Low 16 bits of Group Id */ 
______u16___i_links_count;__/* Links count */         
______u32___i_blocks;___/* Blocks count */            
______u32___i_flags;____/* File flags */              
____union {                                           
    ....
    }osd1;_____________/* OS dependent 1 */
______u32___i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
______u32___i_generation;___/* File version (for NFS) */
______u32___i_file_acl;_/* File ACL */                     
______u32___i_dir_acl;__/* Directory ACL */                
______u32___i_faddr;____/* Fragment address */             
____union {
____} osd2;_____________/* OS dependent 2 */
};

/*
 * The new version of the directory entry.  Since EXT2 structures are
 * stored in intel byte order, and the name_len field could never be 
 * bigger than 255 chars, it's safe to reclaim the extra byte for the
 * file_type field.
 */
struct ext2_dir_entry_2 {                               
______u32___inode;__________/* Inode number */
______u16___rec_len;________/* Directory entry length */
______u8____name_len;_______/* Name length */
______u8____file_type;
____char____name[EXT2_NAME_LEN];____/* File name */
};

 * Structure of the super block                                       
 */                                                                   
struct ext2_super_block {                                             
______u32___s_inodes_count;_____/* Inodes count */                    
______u32___s_blocks_count;_____/* Blocks count */                    
______u32___s_r_blocks_count;___/* Reserved blocks count */           
______u32___s_free_blocks_count;____/* Free blocks count */           
______u32___s_free_inodes_count;____/* Free inodes count */           
______u32___s_first_data_block;_/* First Data Block */                
______u32___s_log_block_size;___/* Block size */                      
______s32___s_log_frag_size;____/* Fragment size */                   
______u32___s_blocks_per_group;_/* # Blocks per group */              
______u32___s_frags_per_group;__/* # Fragments per group */           
______u32___s_inodes_per_group;_/* # Inodes per group */              
______u32___s_mtime;________/* Mount time */                          
______u32___s_wtime;________/* Write time */                          
______u16___s_mnt_count;________/* Mount count */                     
______s16___s_max_mnt_count;____/* Maximal mount count */             
______u16___s_magic;________/* Magic signature */                     
______u16___s_state;________/* File system state */                   
______u16___s_errors;_______/* Behaviour when detecting errors */     
______u16___s_minor_rev_level; _/* minor revision level */            
______u32___s_lastcheck;________/* time of last check */              
______u32___s_checkinterval;____/* max. time between checks */        
______u32___s_creator_os;_______/* OS */                              
______u32___s_rev_level;________/* Revision level */                  
______u16___s_def_resuid;_______/* Default uid for reserved blocks */ 
______u16___s_def_resgid;_______/* Default gid for reserved blocks */ 
____/*                                                                   
____ * These fields are for EXT2_DYNAMIC_REV superblocks only.           
____ *                                                                   
____ * Note: the difference between the compatible feature set and       
____ * the incompatible feature set is that if there is a bit set        
____ * in the incompatible feature set that the kernel doesn't           
____ * know about, it should refuse to mount the filesystem.             
____ *                                                                   
____ * e2fsck's requirements are more strict; if it doesn't know         
____ * about a feature in either the compatible or incompatible          
____ * feature set, it must abort and not try to meddle with             
____ * things it doesn't understand...                                   
____ */                                                                  
______u32___s_first_ino; _______/* First non-reserved inode */           
______u16   s_inode_size; ______/* size of inode structure */            
______u16___s_block_group_nr; __/* block group # of this superblock */   
______u32___s_feature_compat; __/* compatible feature set */             
______u32___s_feature_incompat; ____/* incompatible feature set */       
______u32___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 */   
______u32___s_algorithm_usage_bitmap; /* For compression */              
____/*                                                                   
____ * Performance hints.  Directory preallocation should only           
____ * happen if the EXT2_COMPAT_PREALLOC flag is on.                    
____ */                                                                  
______u8____s_prealloc_blocks;__/* Nr of blocks to try to preallocate*/  
______u8____s_prealloc_dir_blocks;__/* Nr to preallocate for dirs */     
______u16___s_padding1;                                                  
______u32___s_reserved[204];____/* Padding to the end of the block */    
};                                                                       

};

每一个“文件系统”,即每一个格式化成某种文件系统的存储设备上都有一个根目录,同时又都有一个“超级块”(superblock),根目录的位置以及文件系统的其他一些参数都在超级块中。

系统在初始化时,要将一个存储设备作为整个系统的“根”设备,它的根目录就是整个文件系统的总根,就是“/”。更确切地说,就是把根设备的根目录“安装”在文件系统的总根“/”上。有了根设备以后,也可以把其他存储设备也安装到其他目录下。

所谓“安装”,就是1)从一个存储设备上读入超级块,在内存中建立super_block结构。2)再进而将次设备上的根目录与文件系统中已经存在的一个空白目录挂上钩。这样从根目录开始,根据全路径名称,就可以找到文件系统中的任何一个文件。

对与普通文件的读写,文件系统层要通过磁盘或其他存储介质的驱动程序读写。就Ext2文件系统而言,对存储介质的访问可以涉及4中不同的目标:

  • 文件的数据:包括目录的内容,即目录项ext2_dir_entry_2数据结构。
  • 文件的组织和管理信息:即索引节点ext2_inode数据结构。
  • 磁盘的超级块:如果磁盘被划分为若干分区,那就包含每个分区的超级块。
  • 引导块。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值