2021SC@SDUSC
以下是系统调用ioctl()的操作命令,通过以下参数来对常规的系统调用进行扩充,其作用类似“补漏”,所有比较细小的、不需要专门设置一个系统调用的操作都归入ioctl。而且在对特殊设备的驱动进行适配时,也常常通过增设新的ioctl命令来实现。
#define EXT2_IOC_GETVERSION FS_IOC_GETVERSION
#define EXT2_IOC_SETVERSION FS_IOC_SETVERSION
#define EXT2_IOC_GETRSVSZ _IOR('f', 5, long)
#define EXT2_IOC_SETRSVSZ _IOW('f', 6, long)
#define EXT2_IOC32_GETVERSION FS_IOC32_GETVERSION//ioctl commands in 32 bit emulation
#define EXT2_IOC32_SETVERSION FS_IOC32_SETVERSION
磁盘上inode结构包括文件的基本信息如创建者、创建时间等等,文件的读写权限等,以及文件的时间戳:ctime指inode上一次变动的时间,mtime指文件内容上一次变动的时间,atime指文件上一次打开的时间。
一个inode指向一个文件,但多个文件名可以指向一个inode,文件名与inode之间的关系可以分为硬链接和软连接两种。硬链接是对原文件的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; __le32 i_block[EXT2_N_BLOCKS]; __le32 i_generation; __le32 i_file_acl; __le32 i_dir_acl; __le32 i_faddr; union { struct { __u8 l_i_frag; __u8 l_i_fsize; __u16 i_pad1; __le16 l_i_uid_high; __le16 l_i_gid_high; __u32 l_i_reserved2; } linux2; struct { __u8 h_i_frag; __u8 h_i_fsize; __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; __u8 m_i_fsize; __u16 m_pad1; __u32 m_i_reserved2[2]; } masix2; } osd2; };
这是mount()系统调用的参数,mount是挂载文件系统的函数,文件系统只有被挂载才能使用。
#define EXT2_MOUNT_OLDALLOC 0x000002 #define EXT2_MOUNT_GRPID 0x000004 #define EXT2_MOUNT_DEBUG 0x000008 #define EXT2_MOUNT_ERRORS_CONT 0x000010 #define EXT2_MOUNT_ERRORS_RO 0x000020 #define EXT2_MOUNT_ERRORS_PANIC 0x000040 #define EXT2_MOUNT_MINIX_DF 0x000080 #define EXT2_MOUNT_NOBH 0x000100 #define EXT2_MOUNT_NO_UID32 0x000200 #define EXT2_MOUNT_XATTR_USER 0x004000 #define EXT2_MOUNT_POSIX_ACL 0x008000 #define EXT2_MOUNT_XIP 0x010000 #define EXT2_MOUNT_USRQUOTA 0x020000 #define EXT2_MOUNT_GRPQUOTA 0x040000 #define EXT2_MOUNT_RESERVATION 0x080000 #define EXT2_MOUNT_DAX 0x100000 #define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt #define set_opt(o, opt) o |= EXT2_MOUNT_##opt #define test_opt(sb, opt) (EXT2_SB(sb)->s_mount_opt & \ EXT2_MOUNT_##opt) #define EXT2_DFL_MAX_MNT_COUNT 20 #define EXT2_DFL_CHECKINTERVAL 0 #define EXT2_ERRORS_CONTINUE 1 #define EXT2_ERRORS_RO 2 #define EXT2_ERRORS_PANIC 3 #define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE
每个文件系统都有一个超级块结构,超级块是文件系统用于记录和管理信息的地方,当磁盘文件系统被挂载到操作系统上时,超级块也会被读入内存中生成新的超级块。利用内存中的超级块,可以找到各个文件所对应的inode。
struct ext2_super_block { __le32 s_inodes_count; __le32 s_blocks_count; __le32 s_r_blocks_count; __le32 s_free_blocks_count; __le32 s_free_inodes_count; __le32 s_first_data_block; __le32 s_log_block_size; __le32 s_log_frag_size; __le32 s_blocks_per_group; __le32 s_frags_per_group; __le32 s_inodes_per_group; __le32 s_mtime; __le32 s_wtime; __le16 s_mnt_count; __le16 s_max_mnt_count; __le16 s_magic; __le16 s_state; __le16 s_errors; __le16 s_minor_rev_level; __le32 s_lastcheck; __le32 s_checkinterval; __le32 s_creator_os; __le32 s_rev_level; __le16 s_def_resuid; __le16 s_def_resgid; __le32 s_first_ino; __le16 s_inode_size; __le16 s_block_group_nr; __le32 s_feature_compat; __le32 s_feature_incompat; __le32 s_feature_ro_compat; __u8 s_uuid[16]; char s_volume_name[16]; char s_last_mounted[64]; __le32 s_algorithm_usage_bitmap; __u8 s_prealloc_blocks; __u8 s_prealloc_dir_blocks; __u16 s_padding1; __u8 s_journal_uuid[16]; __u32 s_journal_inum; __u32 s_journal_dev; __u32 s_last_orphan; __u32 s_hash_seed[4]; __u8 s_def_hash_version; __u8 s_reserved_char_pad; __u16 s_reserved_word_pad; __le32 s_default_mount_opts; __le32 s_first_meta_bg; __u32 s_reserved[190]; };
修订级别,可以确定文件系统是否支持只有在这种文件系统特定修订下才有的特性,即兼容性,是否支持新的特征。
#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV
#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV
#define EXT2_GOOD_OLD_INODE_SIZE 128
dentry是文件的逻辑属性,它指向的是文件的inode而非其在磁盘上的物理地址,只存在于内存中,是为了提高查找速度而后设计的。如下所示,一个有效的dentry结构必定有一个inode结构,所有的dentry结构组成了完整的目录树。 ext2_dir_entry_2是较新的版本。
struct ext2_dir_entry { __le32 inode; /* Inode number */ __le16 rec_len; /* Directory entry length */ __le16 name_len; /* Name length */ char name[]; /* File name, up to EXT2_NAME_LEN */ }; struct ext2_dir_entry_2 { __le32 inode; __le16 rec_len; __u8 name_len; __u8 file_type; char name[]; };
从磁盘读入的索引节点中的信息是原始的、未加工的,称为raw_inode。而内存中的索引节点分为两部分,一部分属于VFS层,适用于所有的文件系统;另一部分属于具体的某个文件系统类型,如下所示。
在ext2_inode_info结构中i_data[15]是最重要的数据,其中存放着一些指针,直接或间接的指向磁盘中存储该文件内容的所有块,指针共有15项,前12个为直接指针,后三个分别为“一次间接指针”、“二次间接指针”、“三次间接指针”。
struct ext2_inode_info { __le32 i_data[15]; __u32 i_flags; __u32 i_faddr; __u8 i_frag_no; __u8 i_frag_size; __u32 i_file_acl; __u16 i_state; __u32 i_dir_acl; __u32 i_dtime; __u32 i_block_group; struct ext2_block_alloc_info *i_block_alloc_info; __u32 i_dir_start_lookup; #ifdef CONFIG_EXT2_FS_XATTR struct rw_semaphore xattr_sem; #endif rwlock_t i_meta_lock; struct mutex truncate_mutex; struct inode vfs_inode; struct list_head i_orphan; #ifdef CONFIG_QUOTA struct dquot *i_dquot[MAXQUOTAS]; #endif };
之后的代码都是具体的文件操作方法的原型,例如inode的读写、新节点的分配等等。之后分析其具体实现方法。
extern int ext2_bg_has_super(struct super_block *sb, int group); extern unsigned long ext2_bg_num_gdb(struct super_block *sb, int group); extern ext2_fsblk_t ext2_new_block(struct inode *, unsigned long, int *); extern ext2_fsblk_t ext2_new_blocks(struct inode *, unsigned long, unsigned long *, int *); extern int ext2_data_block_valid(struct ext2_sb_info *sbi, ext2_fsblk_t start_blk, unsigned int count);
......