镇江网站建设包括哪些网站公司做的比较好

web/2025/9/30 15:13:05/文章来源:
镇江网站建设包括哪些,网站公司做的比较好,北京产品设计公司,asp网站搭建教程文件系统 Linux将文件系统分为了两层#xff1a;VFS#xff08;虚拟文件系统#xff09;、具体文件系统#xff0c;如下图所示#xff1a; VFS#xff08;Virtual Filesystem Switch#xff09;称为虚拟文件系统或虚拟文件系统转换#xff0c;是一个内核软件层#…文件系统 Linux将文件系统分为了两层VFS虚拟文件系统、具体文件系统如下图所示 VFSVirtual Filesystem Switch称为虚拟文件系统或虚拟文件系统转换是一个内核软件层在具体的文件系统之上抽象的一层用来处理与Posix文件系统相关的所有调用表现为能够给各种文件系统提供一个通用的接口使上层的应用程序能够使用通用的接口访问不同文件系统同时也为不同文件系统的通信提供了媒介。 VFS并不是一种实际的文件系统它只存在于内存中不存在任何外存空间VFS在系统启动时建立在系统关闭时消亡。 Linux系统中存在很多的文件系统例如常见的ext2ext3ext4sysfsrootfsproc等等。 从用户的使用角度Linux下的文件系统中宏观上主要分为三层 1上层的文件系统的系统调用Systemcall ,产生软中断2虚拟文件系统VFSVirtual File System层3挂载到VFS中的各种实际文件系统。 Linux系统的User使用GLIBC啥fopen等函数POSIX标准、GUN C运行时库作为应用程序的运行时库然后通过操作系统将其转换为系统调用SCIsystemcall interfaceSCI是操作系统内核定义的系统调用接口这层抽象允许用户程序的IO操作转换为内核的接口调用。此时触发0x80软中断进入内核态 再控制VFS进行后续的操作 2 用户如何透明的去处理文件 我们知道每个文件系统是独立的有自己的组织方法操作方法。那么对于用户来说不可能所有的文件系统都了解那么怎么做到让用户透明的去处理文件呢 例如我想写文件那就直接read就OK不管你是什么文件系统具体怎么去读这里就需要引入虚拟文件系统。 所以虚拟文件系统就是对于一个system可以存在多个“实际的文件系统”例如ext2ext3fat32ntfs例如我现在有多个分区对于每一个分区我们知道可以是不同的“实际文件系统”。 例如现在三个磁盘分区分别是ext2ext3fat32那么每个“实际的文件系统”的操作和数据结构肯定不一样那么用户怎么能透明使它们呢 这个时候就需要VFS作为中间一层用户直接和VFS打交道。 VFS是一种软件机制只存在于内存中每次系统初始化期间Linux都会先在内存中构造一棵VFS的目录树也就是源码中的namespace。 VFS主要的作用是对上层应用屏蔽底层不同的调用方法提供一套统一的调用接口二是便于对不同的文件系统进行组织管理。 VFS提供了一个抽象层将POSIX API接口与不同存储设备的具体接口实现进行了分离使得底层的文件系统类型、设备类型对上层应用程序透明。 例如readwrite那么映射到VFS中就是sysreadsyswrite那么VFS可以根据你操作的是哪个“实际文件系统”哪个分区来进行不同的实际的操作这个技术也是很熟悉的“钩子结构”技术来处理的。 其实就是VFS中提供一个抽象的struct结构体然后对于每一个具体的文件系统要把自己的字段和函数填充进去这样就解决了异构问题内核很多子系统都大量使用了这种机制。 Linux虚拟文件系统7大对象 为了对文件系统进行统一的管理与组织Linux创建了一个公共根目录和全局文件系统树。要访问一个文件系统中的文件必须先将这个文件系统挂载在全局文件系统树的某个根目录下这一挂载过程被称作文件系统的挂载所挂载的目录称为挂载点。 传统的文件系统在磁盘上的布局如下 文件系统拿取磁盘数据详细分析: 上面这个图,和inode和文件和磁盘的对应关系 磁盘分成了一个个块,上面每个格子都是块,都有自己的块id,那我们的文件系统要读取哪一个块,直接放松对应的块id 就能拿到相应的数据内容 每一个块的大小是固定的,我们先假定为4kb,一个id的大小为64位,那大小就是8字节 如果所有文件大小都不超过4kb,那就能用磁盘块id作为文件名字 但目前情况每个文件大小不确定,需要多个块才能保存,所以就有了inode数据结构,记录了文件和多个块id的对应关系 一个块是4kb,颗粒度有些粗,不可能所有文件都是4kb的倍数给inode记录 所以在inode记录了这个文件对应磁盘的多个块和文件的大小(单位byte)和元数据 同时每个inode应该占多少块呢 inode不能太小,不然存的数据也小,也会限制到文件的大小 假设一个文件有4GB:这个文件就用了100万个块(一个块4kb,块id大小8字节),那存储id就8MB了 如果每个inode预留8MB,其实不划算 所以inode指向多级inode再指向数据块 所有inode都放在一起,保存在磁盘头部的inode表,这个表就像一个大数组每一项都对应一个inode,每个inode都大小一样 这样每个inode都用数组对应的下表作为这个inode的名字:第一个inoded就是inode0,第二个inode就是inode1 这个索引也叫inode号(inode number) 所以看得出来 磁盘中inode号就能表示一个文件 在inode中增加另一个字段来表示这个是目录inode还是普通inode, 把inode号对应的字符串名字记录在它的上级目录中,就形成了目录树 tips:inode大小和块大小完全没关系,通常一个快里面放了多个inode 图片9-4和上面的布局一一对应,超级快后面的分配信息也叫节点位图,说明了哪个块没被使用,哪个inode没被使用仅此而已 小结一下:如果要找/bin/app_run这个文件时候 1.文件系统找到根目录的inode,通常在inode表的第一个 2.根据inode找到对应文件的块id 3.读取磁盘块id获得数据,找到 bin 字符串,通过字符串找到inode号 (这时候理解还在/目录) 4.根据bin的inode号,就能知道bin的目录inode在哪 (这时候理解进入bin目录) 5.同理根据bin的inode知道了bin的数据,分析字符串app_run的inode_Id在哪 6.获得了app_run的数据 上面得知了 文件名是存在它的父目录的 ,和自身的inode没有关系 继续介绍 由上图可知文件系统的开头通常是由一个磁盘扇区所组成的引导块该部分的主要目的是用于对操作系统的引导。一般只在启动操作系统时使用。 随后是超级块超级块主要存放了该物理磁盘中文件系统结构的相关信息并且对各个部分的大小进行说明,记录了后面四个区的位置。 操作系统mount磁盘的时候也是首先读取超级块来确定后面的位置 最后由i节点位图逻辑块位图、i节点、逻辑块这几部分分布在物理磁盘上。 Linux为了对超级块i节点逻辑块这三部分进行高效的管理Linux创建了几种不同的数据结构分别是文件系统类型、inode、dentry等几种。 超级块则是反映了文件系统整体的控制信息。超级块能够以多种的方式存在对于基于磁盘的文件系统它以特定的格式存在于磁盘的固定区域取决于文件系统类型上。在挂载文件系统时该超级块中的内容被读入磁盘中从而构建出位于内存中的新的超级块。 inode则反映了文件系统对象中的一般元数据信息。 dentry则是反映出某个文件系统对象在全局文件系统树中的位置(没有磁盘实体只在内存中)。 linux怎么把不同的分区进行链接呢 我们在linux输入ls可以看见下面的各种目录结构 它其实是一棵目录树(没有画全) 对于linux怎么把各种有不同文件系统的分区进行链接 现在只要记住两个重要链表 1文件系统链表 2每一个文件系统的mount挂载点链表。 我们看到Linux系统的文件目录树就是靠上图中的这一系列的链表穿针引线给串在一起的就像缝制一件衣服一样最终的成衣就是我们看到的Linux系统目录树而缝制这件成衣的线以及指导走线的规则便是VFS本身了。 VFS之所有可以将机制大相径庭的完全不同的文件系统对外统一成一个样子完全就是依靠了它的统一的对POSIX文件调用的接口该接口的结构看上去是下面的样子 结构体关系1 超级块super block 超级块一个超级块对应一个文件系统已经安装的文件系统类型如ext2此处是实际的文件系统不是VFS。 之前我们已经说了文件系统用于管理这些文件的数据格式和操作之类的系统文件有系统文件自己的文件系统同时对于不同的磁盘分区也有可以是不同的文件系统。那么一个超级块对于一个独立的文件系统。保存文件系统的类型、大小、状态等等。 “文件系统”和“文件系统类型”不一样一个文件系统类型下可以包括很多文件系统即很多的superblock) 就是之前的图文件系统链表 既然我们知道对于不同的文件系统有不同的superblock那么对于不同的superblock的操作肯定也是不同的所以我们在下面的superblock结构中可以看到上面说的抽象的struct结构例如下面的struct superoperations linux内核3141246 struct super_block 1247 struct list_head s_list;//指向超级块链表指针,把所有超级快链接 1248 dev_t s_dev; search index;//块设备的设备号等 1249 unsigned char s_blocksize_bits; 1250 unsigned long s_blocksize; 1251 loff_t s_maxbytes; Max file size 1252 struct file_system_type *s_type;//这个文件系统的文件类型(fat32,ext32) 1253 const struct super_operations *s_op;//指向具体的文件系统用于对超级块的函数操作集合 1254 const struct dquot_operations *dq_op;//某个特定的具体文件系统用于限额操作的函数集合 1255 const struct quotactl_ops *s_qcop;//于配置磁盘限额的的方法 1256 const struct export_operations *s_export_op; 1257 unsigned long s_flags; 1258 unsigned long s_magic; 1259 struct dentry *s_root; 1260 struct rw_semaphore s_umount; 1261 int s_count; 1262 atomic_t s_active; 1263 #ifdef CONFIG_SECURITY 1264 void *s_security; 1265 #endif 1266 const struct xattr_handler **s_xattr; 1267 1268 struct list_head s_inodes; all inodes 1269 struct hlist_bl_head s_anon; anonymous dentries for nfs exporting 1270 struct list_head s_mounts; list of mounts; _not_ for fs use1271 struct block_device *s_bdev; 1272 struct backing_dev_info *s_bdi; 1273 struct mtd_info *s_mtd; 1274 struct hlist_node s_instances; 1275 struct quota_info s_dquot; Diskquota specific options 1276 1277 struct sb_writers s_writers; 1278 1279 char s_id[32]; Informational name 1280 u8 s_uuid[16]; UUID 1281 1282 void *s_fs_info; Filesystem private info 1283 unsigned int s_max_links; 1284 fmode_t s_mode; 1285 1286 Granularity of cmatime in ns 1287 Cannot be worse than a second 1288 u32 s_time_gran; 1289 1290 1291 * The next field is for VFS *only* No filesystems have any business 1292 * even looking at it You had been warned 1293 1294 struct mutex s_vfs_rename_mutex; Kludge 1295 1296 1297 * Filesystem subtype If nonempty the filesystem type field 1298 * in procmounts will be typesubtype 1299 1300 char *s_subtype; 1301 1302 1303 * Saved mount options for lazy filesystems using 1304 * generic_show_options 1305 1306 char __rcu *s_options; 1307 const struct dentry_operations *s_d_op; default d_op for dentries 1308 1309 1310 * Saved pool identifier for cleancache 1 means none 1311 1312 int cleancache_poolid; 1313 1314 struct shrinker s_shrink; persb shrinker handle 1315 1316 Number of inodes with nlink 0 but still referenced 1317 atomic_long_t s_remove_count; 1318 1319 Being remounted readonly 1320 int s_readonly_remount; 1321 1322 AIO completions deferred from interrupt context 1323 struct workqueue_struct *s_dio_done_wq; 1324 1325 1326 * Keep the lru lists last in the structure so they always sit on their 1327 * own individual cachelines 1328 1329 struct list_lru s_dentry_lru ____cacheline_aligned_in_smp; 1330 struct list_lru s_inode_lru ____cacheline_aligned_in_smp; 1331 struct rcu_head rcu; 1332 ;针对上面的操作超级块的函数操作集 struct super_operations {//该函数在给定的超级块下创建并初始化一个新的索引节点对象struct inode *(*alloc_inode)(struct super_block *sb);//释放指定的索引结点 。 void (*destroy_inode)(struct inode *);//VFS在索引节点被修改时会调用此函数。void (*dirty_inode) (struct inode *, int flags);// 将指定的inode写回磁盘。 int (*write_inode) (struct inode *, struct writeback_control *wbc);//删除索引节点。 int (*drop_inode) (struct inode *);void (*evict_inode) (struct inode *);//用来释放超级块 void (*put_super) (struct super_block *);//使文件系统的数据元素与磁盘上的文件系统同步,wait参数指定操作是否同步。 int (*sync_fs)(struct super_block *sb, int wait); int (*freeze_fs) (struct super_block *); int (*unfreeze_fs) (struct super_block *);//获取文件系统状态。把文件系统相关的统计信息放在statfs中 int (*statfs) (struct dentry *, struct kstatfs *); int (*remount_fs) (struct super_block *, int *, char *); void (*umount_begin) (struct super_block *);int (*show_options)(struct seq_file *, struct dentry *); int (*show_devname)(struct seq_file *, struct dentry *); int (*show_path)(struct seq_file *, struct dentry *); int (*show_stats)(struct seq_file *, struct dentry *); #ifdef CONFIG_QUOTA ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t); ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t); #endif int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t); long (*nr_cached_objects)(struct super_block *, int); long (*free_cached_objects)(struct super_block *, long, int); };结构体关系2 索引节点inode 索引节点inode保存的其实是实际的数据的一些信息这些信息称为“元数据”也就是对文件属性的描述) 例如文件大小设备标识符用户标识符用户组标识符文件模式扩展属性文件读取或修改的时间戳链接数量指向存储该内容的磁盘区块的指针文件分类等等。 真实数据放在数据块里,可以通过索引节点找到数据块 注意数据分成元数据数据本身 同时注意inode有两种一种是VFS的inode一种是具体文件系统的inode。前者在内存中后者在磁盘中。所以每次其实是将磁盘中的inode调进填充内存中的inode这样才是算使用了磁盘文件inode。 inode怎样生成的 每个inode节点的大小一般是128字节或256字节。inode节点的总数在格式化时就给定现代OS可以动态变化一般每2KB就设置一个inode。 一般文件系统中很少有文件小于2KB的所以预定按照2KB分一般inode是用不完的。所以inode在文件系统安装的时候会有一个默认数量后期会根据实际的需要发生变化。 注意inode号inode号是唯一的表示不同的文件。其实在Linux内部的时候访问文件都是通过inode号来进行的所谓文件名仅仅是给用户容易使用的。 当我们打开一个文件的时候首先系统找到这个文件名对应的inode号然后通过inode号得到inode信息最后由inode找到文件数据所在的block现在可以处理文件数据了。 inode和文件的关系 当创建一个文件的时候就给文件分配了一个inode。一个inode只对应一个实际文件一个文件也会只有一个inode。inodes最大数量就是文件的最大数量。 接下来看看inode的结构体 527 struct inode { 528 umode_t i_mode; 访问权限控制 529 unsigned short i_opflags; 530 kuid_t i_uid; 使用者的id 531 kgid_t i_gid; 使用组id 532 unsigned int i_flags; 文件系统标志 533 534 #ifdef CONFIG_FS_POSIX_ACL 535 struct posix_acl *i_acl; 536 struct posix_acl *i_default_acl; 537 #endif 538 539 const struct inode_operations *i_op; 索引节点操作表 540 struct super_block *i_sb; 相关的超级块 541 struct address_space *i_mapping; 相关的地址映射 542 543 #ifdef CONFIG_SECURITY 544 void *i_security; 545 #endif 546 547 Stat data, not accessed from path walking 548 unsigned long i_ino; 索引节点号 549 550 * Filesystems may only read i_nlink directly. They shall use the 551 * following functions for modification: 552 * 553 * (set|clear|inc|drop)_nlink 554 * inode_(inc|dec)_link_count 555 556 union { 557 const unsigned int i_nlink; 558 unsigned int __i_nlink; 硬连接数 559 }; 560 dev_t i_rdev; 实际设备标识符号 561 loff_t i_size; 562 struct timespec i_atime; 最后访问时间 563 struct timespec i_mtime; 最后修改时间 564 struct timespec i_ctime; 最后改变时间 565 spinlock_t i_lock; i_blocks, i_bytes, maybe i_size 566 unsigned short i_bytes; 使用的字节数 567 unsigned int i_blkbits; 568 blkcnt_t i_blocks; 文件的块数 569 570 #ifdef __NEED_I_SIZE_ORDERED 571 seqcount_t i_size_seqcount;572 #endif 573 574 Misc 575 unsigned long i_state; 576 struct mutex i_mutex; 577 578 unsigned long dirtied_when; jiffies of first dirtying 首次修改时间 579 580 struct hlist_node i_hash; hash值,提高查找效率 581 struct list_head i_wb_list; backing dev IO list 582 struct list_head i_lru; inode LRU list 未使用的inode 583 struct list_head i_sb_list; 链接一个文件系统中所有inode的链表 584 union { 585 struct hlist_head i_dentry; 目录项链表 586 struct rcu_head i_rcu; 587 }; 588 u64 i_version; 589 atomic_t i_count; 引用计数 590 atomic_t i_dio_count; 591 atomic_t i_writecount; 写者计数 592 const struct file_operations *i_fop; former -i_op-default_file_ops 文件操作 593 struct file_lock *i_flock; 文件锁链表 594 struct address_space i_data; 表示被inode读写的页面 595 #ifdef CONFIG_QUOTA 596 struct dquot *i_dquot[MAXQUOTAS]; 节点的磁盘限额 597 #endif 598 struct list_head i_devices; 设备链表(共用同一个驱动程序的设备形成的链表。) 599 union { 600 struct pipe_inode_info *i_pipe; 管道信息 601 struct block_device *i_bdev; 块设备驱动节点 602 struct cdev *i_cdev; 字符设备驱动节点 603 }; 604 605 __u32 i_generation; 索引节点版本号 606 607 #ifdef CONFIG_FSNOTIFY 608 __u32 i_fsnotify_mask; all events this inode cares about 609 struct hlist_head i_fsnotify_marks; 610 #endif 611 612 #ifdef CONFIG_IMA 613 atomic_t i_readcount; struct files open RO 614 #endif 615 void *i_private; fs or device private pointer 用户私有数据 616 };对inode操作的函数操作集 目前感觉是看后面的图 这些结构体的关系 进程先通过 file_struct结构体找 在进程的哪个fd[]中,找到对应file结构体 再找到dentry结构体再找到inode结构体,调用里面的i_fop的函数,触发系统调用的80软中断 最后碰到了内核态和VFS 节点方法struct inode_operations {//lookup()查找指定文件的dentry struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int); void * (*follow_link) (struct dentry *, struct nameidata *); int (*permission) (struct inode *, int); struct posix_acl * (*get_acl)(struct inode *, int);int (*readlink) (struct dentry *, char __user *,int); void (*put_link) (struct dentry *, struct nameidata *, void *);int (*create) (struct inode *,struct dentry *, umode_t, bool);//create()如果该inode描述一个目录文件,那么当在该目录下创建或打开一个文件时,内核必须为这个文件创建一个inode。//VFS通过调用该inode的i_op-create()函数来完成上述新inode的创建。// 该函数的第一个参数为该目录的 inode第二个参数为要打开新文件的dentry//第三个参数是对该文件的访问权限。如果该inode描述的是一个普通文件那么该inode永远都不会调用这个create函数 int (*link) (struct dentry *,struct inode *,struct dentry *);//link()用于在指定目录下创建一个硬链接。这个link函数最终会被系统调用link()调用。//该函数的第一个参数是原始文件的dentry,第二个参数即为上述指定目录的inode,第三个参数是链接文件的dentry。 int (*unlink) (struct inode *,struct dentry *); int (*symlink) (struct inode *,struct dentry *,const char *);//symlink ()在某个目录下新建mkdir()在指定的目录下创建一个子目录,当前目录的inode会调用i_op-mkdir()。该函数会被系统调用mkdir()调用。//第一个参数即为指定目录的inode,第二个参数为子目录的dentry,第三个参数为子目录权限; int (*mkdir) (struct inode *,struct dentry *,umode_t);//mknod()在指定的目录下创建一个特殊文件,比如管道、设备文件或套接字等。 int (*rmdir) (struct inode *,struct dentry *);//rmdir ()从inode所描述的目录中删除一个指定的子目录时,该函数会被系统调用rmdir()最终调用 int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t); int (*rename) (struct inode *, struct dentry *,struct inode *, struct dentry *); int (*rename2) (struct inode *, struct dentry *,struct inode *, struct dentry *, unsigned int); int (*setattr) (struct dentry *, struct iattr *); int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); int (*setxattr) (struct dentry *, const char *,const void *,size_t,int); ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); ssize_t (*listxattr) (struct dentry *, char *, size_t); int (*removexattr) (struct dentry *, const char *); int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,u64 len); int (*update_time)(struct inode *, struct timespec *, int); int (*atomic_open)(struct inode *, struct dentry *,struct file *, unsigned open_flag,umode_t create_mode, int *opened); int (*tmpfile) (struct inode *, struct dentry *, umode_t); int (*set_acl)(struct inode *, struct posix_acl *, int); } ____cacheline_aligned;结构体关系3.目录项(dentry) 目录项是描述文件的逻辑属性,只存在于内存中,并没有实际对应的磁盘上的描述,更确切的说是存在于内存的目录项缓存,为了提高查找性能而设计。 注意不管是文件夹还是最终的文件,都是属于目录项,所有的目录项在一起构成一颗庞大的目录树。 例如:open一个文件/home/xxx/yyy.txt,那么/、home、xxx、yyy.txt都是一个目录项,VFS在查找的时候,根据一层一层的目录项找到对应的每个目录项的inode,那么沿着目录项进行操作就可以找到最终的文件。 注意:目录也是一种文件(所以也存在对应的inode)。打开目录,实际上就是打开目录文件。 108 struct dentry { 109 RCU lookup touched fields 110 unsigned int d_flags; protected by d_lock 111 seqcount_t d_seq; per dentry seqlock 112 struct hlist_bl_node d_hash; lookup hash list 113 struct dentry *d_parent; parent directory 父目录 114 struct qstr d_name; 115 struct inode *d_inode; Where the name belongs to NULL is 116 * negative 与该目录项关联的inode 117 unsigned char d_iname[DNAME_INLINE_LEN]; small names 短文件名 118 119 Ref lookup also touches following 120 struct lockref d_lockref; perdentry lock and refcount 121 const struct dentry_operations *d_op; 目录项操作 122 struct super_block *d_sb; The root of the dentry tree 这个目录项所属的文件系统的超级块(目录项树的根) 123 unsigned long d_time; used by d_revalidate 重新生效时间 124 void *d_fsdata; fsspecific data 具体文件系统的数据 125 126 struct list_head d_lru; LRU list 未使用目录以LRU 算法链接的链表 127 128 * d_child and d_rcu can share memory 129 130 union { 131 struct list_head d_child; child of parent list 目录项通过这个加入到父目录的d_subdirs中 132 struct rcu_head d_rcu; 133 } d_u; 134 struct list_head d_subdirs; our children 本目录的所有孩子目录链表头 135 struct hlist_node d_alias; inode alias list 索引节点别名链表 136 };一个有效的dentry结构必定有一个inode结构,这是因为一个目录项要么代表着一个文件,要么代表着一个目录,而目录实际上也是文件。 所以,只要dentry结构是有效的,则其指针d_inode必定指向一个inode结构。但是inode却可以对应多个。 整个结构其实就是一棵树,目录其实就是文件(kobject、inode)再加上一层封装,这里所谓的封装主要就是增加两个指针,一个是指向父目录,一个是指向该目录所包含的所有文件(普通文件和目录)的链表头。 这样才能有我们的目录操作(比如回到上次目录,只需要一个指针步骤【…】,而进入子目录需要链表索引需要多个步骤) 下面的dentry相关的操作函数集(inode里面已经包含了mkdir,rmdir,mknod之类的操作了) struct dentry_operations {该函数判断目录对象是否有效。VFS准备从dcache中使用一个目录项时,会调用该函数. int (*d_revalidate)(struct dentry *, unsigned int); int (*d_weak_revalidate)(struct dentry *, unsigned int);该目录生成散列值,当目录项要加入到散列表时,VFS要调用此函数。 int (*d_hash)(const struct dentry *, struct qstr *); 该函数来比较name1和name2这两个文件名。使用该函数要加dcache_lock锁。 int (*d_compare)(const struct dentry *, const struct dentry *,unsigned int, const char *, const struct qstr *);当d_count0时,VFS调用次函数。使用该函数要叫 dcache_lock锁。 int (*d_delete)(const struct dentry *);当该目录对象将要被释放时,VFS调用该函数。 void (*d_release)(struct dentry *); void (*d_prune)(struct dentry *);当一个目录项丢失了其索引节点时,VFS就掉用该函数。 void (*d_iput)(struct dentry *, struct inode *); char *(*d_dname)(struct dentry *, char *, int); struct vfsmount *(*d_automount)(struct path *); int (*d_manage)(struct dentry *, bool); } ____cacheline_aligned;结构体关系4.文件对象(file) 文件对象描述的是进程已经打开的文件。因为一个文件可以被多个进程打开,所以一个文件可以存在多个文件对象。但是由于文件是唯一的,那么inode就是唯一的,目录项也是定的 进程其实是通过文件描述符来操作文件的,每个文件都有一个32位的数字来表示下一个读写的字节位置,这个数字叫做文件位置。 一般情况下打开文件后,打开位置都是从0开始,除非一些特殊情况。Linux用file结构体来保存打开的文件的位置,所以file称为打开的文件描述。file结构形成一个双链表,称为系统打开文件表。 结构体:file 775 struct file { 776 union { 777 struct llist_node fu_llist; 每个文件系统中被打开的文件都会形成一个双链表 778 struct rcu_head fu_rcuhead; 779 } f_u; 780 struct path f_path; 781 #define f_dentry f_path.dentry 782 struct inode *f_inode; cached value 783 const struct file_operations *f_op; 指向文件操作表的指针 784 785 786 * Protects f_ep_links, f_flags. 787 * Must not be taken from IRQ context. 788 789 spinlock_t f_lock; 790 atomic_long_t f_count; 文件对象的使用计数 791 unsigned int f_flags; 打开文件时所指定的标志 792 fmode_t f_mode; 文件的访问模式(权限等) 793 struct mutex f_pos_lock; 794 loff_t f_pos; 文件当前的位移量 795 struct fown_struct f_owner; 796 const struct cred *f_cred; 797 struct file_ra_state f_ra; 预读状态 798 799 u64 f_version; 版本号 800 #ifdef CONFIG_SECURITY 801 void *f_security; 安全模块 802 #endif 803 needed for tty driver, and maybe others 804 void *private_data; 私有数据 805 806 #ifdef CONFIG_EPOLL 807 Used by fs/eventpoll.c to link all the hooks to this file 808 struct list_head f_ep_links; 809 struct list_head f_tfile_llink; 810 #endif #ifdef CONFIG_EPOLL 811 struct address_space *f_mapping; 页缓存映射 812 #ifdef CONFIG_DEBUG_WRITECOUNT 813 unsigned long f_mnt_write_state; 814 #endif 815 } __attribute__((aligned(4))); lest something weird decides that 2 is OK重点解释一些重要字段: 首先,f_flags、f_mode和f_pos代表的是这个进程当前操作这个文件的控制信息。 这个非常重要,因为对于一个文件,可以被多个进程同时打开,那么对于每个进程来说,操作这个文件是异步的,所以这个三个字段就很重要了。 对于引用计数f_count,当我们关闭一个进程的某一个文件描述符时候,其实并不是真正的关闭文件,仅仅是将f_count减一,当f_count0时候,才会真的去关闭它。 对于dup,fork这些操作来说,都会使得f_count增加,具体的细节,以后再说。f_op也是很重要的是涉及到所有的文件的操作结构体。例如:用户使用read,最终都会调用file_operations中的读操作,而file_operations结构体是对于不同的文件系统不一定相同。里面一个重要的操作函数式release函数,当用户执行close时候,其实在内核中是执行release函数,这个函数仅仅将f_count减一,这也就解释了上面说的,用户close一个文件其实是将f_count减一。只有引用计数减到0才关闭文件。 注意:对于“正在使用”和“未使用”的文件对象分别使用一个双向链表进行管理。 另一个结构体 files_struct 上面的file只是对一个文件而言,对于一个进程(用户)来说,可以同时处理多个文件,所以需要另一个结构来管理所有的files 即:用户打开文件表-files_struct 172 struct files_struct { 173 atomic_t count; 174 rwlock_t file_lock; Protects all the below members. Nests inside tsk-alloc_lock 175 int max_fds; 176 int max_fdset; 177 int next_fd; 178 struct file ** fd; current fd array 179 fd_set *close_on_exec; 180 fd_set *open_fds; 181 fd_set close_on_exec_init; 182 fd_set open_fds_init; 183 struct file * fd_array[NR_OPEN_DEFAULT]; 184 };解释一些字段: 字段描述count引用计数file_lock锁,保护下面的字段max_fds当前文件对象的最大的数量max_fdset文件描述符最大数next_fd已分配的最大的文件描述符1fd指向文件对象指针数组的指针,一般就是指向最后一个字段fd_arrray,当文件数超过NR_OPEN_DEFAULT时候,就会重新分配一个数组,然后指向这个新的数组指针close_on_exec执行exec()时候需要关闭的文件描述符open_fds指向打开的文件描述符的指针close_on_exec_init执行exec()时候需要关闭的文件描述符初始化值open_fds_init文件描述符初值集合fd_array文件对象指针的初始化数组fs_struct 那同时因为打开了文件 也会有对应的操作函数file_operations file_operations { struct module *owner; loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t); ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t); ssize_t (*read_iter) (struct kiocb *, struct iov_iter *); ssize_t (*write_iter) (struct kiocb *, struct iov_iter *); int (*iterate) (struct file *, struct dir_context *); unsigned int (*poll) (struct file *, struct poll_table_struct *); long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); long (*compat_ioctl) (struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); int (*flush) (struct file *, fl_owner_t id); int (*release) (struct inode *, struct file *); int (*fsync) (struct file *, loff_t, loff_t, int datasync); int (*aio_fsync) (struct kiocb *, int datasync); int (*fasync) (int, struct file *, int); int (*lock) (struct file *, int, struct file_lock *); ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); int (*check_flags)(int); int (*flock) (struct file *, int, struct file_lock *); ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); int (*setlease)(struct file *, long, struct file_lock **); long (*fallocate)(struct file *file, int mode, loff_t offset,loff_t len); int (*show_fdinfo)(struct seq_file *m, struct file *f); };应该是用户空间的调用总结: 每个进程都有自己的namespace。 fs_struct用于表示进程与文件系统之间的结构关系,比如当前的工作目录,进程的根目录等等。 files_struct 用于表示当前进程打开的文件。 而对于每一个打开的文件,由file对象来表示。 Linux中,常常用文件描述符(file descriptor)来表示一个打开的文件,这个描述符的值往往是一个大于或等于0的整数。而这个整数,其实就是在files_struct中file数组fd的下标。对于所有打开的文件, 这些文件描述符会存储在open_fds的位图中。 从图中可知进程通过taskstruct中的一个域filesfilesstruct 来了解它当前所打开的文件对象而我们通常所说的文件描述符其实是进程打开的文件对象数组的索引值。文件对象通过域fdentry找到它对应的dentry对象再由dentry对象的域dinode找到它对应的索引节点通过索引节点又可以得到超级块的信息也就可以得到最终操作文件的方法在open文件的时候就是使用这样一个过程这样就建立了文件对象与实际的物理文件的关联。文件对象所对应的文件操作函数列表是通过索引节点的域ifop得到的而ifop最终又是通过struct superoperations sop来初始化的。 VFS文件系统中的inode和dentry与实际文件系统的inode和dentry有一定的关系但不能等同。 真实磁盘文件的inode是存在于物理外存上的但VFS中的inode和dentry是存在于内存中的系统读取外存中的inode信息进行一定加工后生成内存中的inode和dentry。 虚拟的文件系统也具有inode和dentry结构只是这是系统根据相应的规则生成的不存在于实际外存中。 用户空间和内核空间和系统调用和泽呢么知道这个文件的file_operation http://wed.xjx100.cn/news/162453.html?actiononClick 目前还在看这个文章 https://blog.csdn.net/marlos/article/details/130234691 上面这个文章是vfs文件系统,怎么被应用open调用再调用到不同的文件系统的 估计还要从之前 迅维的文档看看驱动创建的时候 有个file_opeartion是不是能关联起来 https://blog.csdn.net/qq_45172832/article/details/129242285 https://blog.csdn.net/wenfengliaoshuzhai/article/details/131776900 上面两个文章都是说驱动文件的open怎么和应用程序的open对应起来 https://blog.csdn.net/uunubt/article/details/127278292 上面是主要参考的文章 分手了时间真多

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/84513.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

免费网站免费网站平台重庆市场所码图片

前天5月14号,一个平静的日子。我去参加了np的bsci考试,但不幸的是一进去看到考题就发晕了。题变了,后来才知道,我去考试的时间是变题的第二天。但万幸的是经过艰苦的努力,我终于看到了Congratulations,出来…

网站设计的方法青岛网站建设q479185700棒

在某个项目中,需要开发一个与native相对应的web前端app,后台用的是java restful接口,请求数据时需要用的3des加密。如果想要请求接口,则需要javascript的加密与java相同,于是在baidu与google进行了大量搜索&#xff0c…

开发区网站建设方案ps软件下载2022

文章目录 风景示例动物示例人物动作示例 Runway旗下的视频生成产品Gen-1和Gen-2已彻底开放,任何人都可注册一个账号免费尝试。免费的时长是105s,每个视频生成4s。 看gen-2官网和各公众号放出来的示例,非常震撼,不禁感慨现在文生视…

网页设计新手制作的网站代码mip网站怎么做匹配

在前面的文章中,我们使用libvlc_media_player_set_hwnd设置了视频的显示的窗口。 libvlc_media_player_set_hwnd(vlc_mediaPlayer, (void *)ui.widgetShow->winId()); 如果我们想要提取每一帧数据,将数据渲染到QWidget上,该如何操作呢&a…

石家庄建设厅网站首页单页主题 wordpress

文章目录 一、PhPstudy下载、安装二、Sqli-libs下载、搭建三、启用Sqli-libs phpstudy地址:https://www.xp.cn/ sqli-libs地址:https://github.com/Audi-1/sqli-labs 一、PhPstudy下载、安装 1、下载–解压–安装,安装完成如下图 2、更换php…

网站制作哪家实惠源码之家网站模板

Eclipse GlassFish 5.1的发布是Jakarta EE的重要里程碑! 首先,这证实了Oracle提供的GlassFish源代码可以在Eclipse Infrastructure上构建和组装。 第二, 通过通过Java EE 8兼容性测试,它可以验证所贡献的代码是否符合Java EE 8…

因脉网站建设公司怎么呀韩国开发一个淘宝app需要多少钱

Java面试:技巧与实践 在当今的IT行业中,Java已经成为了一种非常流行的编程语言。它以其跨平台、面向对象、安全性高等特点,吸引了无数的开发人员。然而,掌握Java并不是一件容易的事情,尤其是在面试过程中。本文将为您…

什么网站免费建设wordpress获取首页id

琪琪格的私人日记! 不要的就干脆放弃,不要再回头看往情留下的痕迹,自己终究要逃离这个圈,选择走自己该走的路,给他留下百分的祝福,已足够。拥有过爱情的人才知这份难舍的痛楚,为了自己爱的他而离…

布吉网站的建设wordpress站群管理系统

我们都知道模板一般会用到继承,导航栏就是一个很好的例子,但是导航栏的数据如何共享,比如有个导航的文件叫在view/navigation.blade.php为了简单一点,文件里只有设置了一个变量1{{ $cqh }}现在的要求是每个页面都会用到这个变量&a…

各大网站ip地址上海展览公司

stringstring是常用的类型,它具有不可变性:就是一旦赋值,就不可变,如果再赋值 ,就重新开辟内存空间;保留性:如果一个字符串存在,另一个与其相同,他们会指向同一个地址&am…

深圳网站设计哪家好易语言做网站登录

指定的字符串: 白天走在街道上,伸手不见五指,周围的建筑全被雾笼罩了,在家里通过窗户往外望去,外面就像仙境一般,雾把所有的东西都淹没了,能看到的,只有白色的雾。!文件…

湖南自考网站建设与管理非物质文化遗产网站怎么做

是的,标题没错。C#其中一份新提案假定,所有的引用类型在默认情况下都是不可空的。在新语法下,你需要显式地标明一个引用变量是可空的,就像对值类型所做的那样。 和值类型一样,T是指不可空类型,而T?是指可…

大型网站服务器架构沧州网站建设报价

Redis中的Lua脚本到底能不能保证原子性? Redis中Lua脚本的执行,可以保证并发编程中不可再拆分的这个原子性,但是没有保证数据库ACID中要么都执行要么都回滚的这个原子性。Lua脚本执行过程中命令产生错误,是不会回滚的&#xff0c…

河南便宜网站建设费用郑州网络营销网站优化

收集了各大公司的面试经验,现整理出来,希望能给正在找工作的志同道合的小伙伴一些指引,本文会持续更新的哦。 1、 CPU 和 GPU的区别 一个是通用计算,一个是专用计算。 CPU主要负责操作系统和应用程序,GPU主要负责跟…

网站如何做手机端页面seo短视频新地址在哪里?

1、sex存为01还是男女? 存为01主要是为了国际化和节省存储空间。存为01很容易转换成不同语言表示的男女。 2、文件存储方案 MongoDB有GirdFS用来将文件直接保存到数据库,如果使用nginx,可以直接使用http读取GridFS里面的文件。 所以&…

药剂学教学网站的建设福田公司门口

国庆中秋特辑系列文章: 国庆中秋特辑(八)Spring Boot项目如何使用JPA 国庆中秋特辑(七)Java软件工程师常见20道编程面试题 国庆中秋特辑(六)大学生常见30道宝藏编程面试题 国庆中秋特辑&…

机关单位网站建设工作方案中国网站模板下载

强大的自愈能力是 Kubernetes 这类容器编排引擎的一个重要特性。自愈的默认实现方式是自动重启发生故障的容器。除此之外,用户还可以利用 Liveness 和 Readiness 探测机制设置更精细的健康检查,进而实现如下需求: 零停机部署。 避免部署无效…

广东企业移动网站建设哪家好上海好的设计公司

目录 一、预装软件 二、创建sftp管理组 三、SSH设置 三、创建用户家目录和设置home权限 四、创建用户并设置上传目录权限控制 五、用户初始化密码 六、说明 需求客户要求与第三方通过sftp交互文件,需要在Linux系统部署sftp服务器。考虑安全,计划对…

网站里的课程配图怎么做电子商务网站建设读书笔记

AWS Fargate 是一个由 Amazon Web Services (AWS) 提供的无服务器容器计算引擎。它使开发者能够运行容器化应用程序,而无需管理底层的服务器或虚拟机。简而言之,AWS Fargate 让你只需关注应用的容器本身,而不需要管理运行容器的基础设施&…

想做网站的公司好国家的企业信息网

上一篇我们学习了CSS基本样式和选择器,相信大家对于样式的使用有了初步认知。 本篇我们继续来学习CSS中的扩展选择器及CSS继承性,如何使用这些扩展选择器更好的帮助我们美化页面。 下一篇我们将会学习CSS中常用的属性。 喜欢的 【点赞】【关注】【收藏】…