当前位置: 首页 > wzjs >正文

上海市建设工程设计文件审查管理事务中心网站免费网站建设制作

上海市建设工程设计文件审查管理事务中心网站,免费网站建设制作,微信网站建设企业,网页制作软件排行榜块概念 os文件系统访问磁盘,不是以扇区为单位的,而是以块为单位的,一般是4KB(也就是连续的8个扇区)(可以调整大小)。 磁盘就是⼀个三维数组,我们把它看待成为⼀个"⼀维数组&q…

块概念

os文件系统访问磁盘,不是以扇区为单位的,而是以块为单位的,一般是4KB(也就是连续的8个扇区)(可以调整大小)。

磁盘就是⼀个三维数组,我们把它看待成为⼀个"⼀维数组",数组下标就是LBA,每个元素都是扇区

每个扇区都有LBA,那么8个扇区⼀个块,每⼀个块的地址我们也能算出来。
知道LBA:块号 = LBA/8
知道块号:LAB=块号*8 + n. (n是块内第⼏个扇区)

文件系统使用磁盘块,是以4KB为单位的。   

分区

柱⾯是分区的最⼩单位,我们可以利⽤参考柱⾯号码的⽅式来进⾏分区,其本质就是设置每个区的起 始柱⾯和结束柱⾯号码。
柱⾯⼤⼩⼀致,扇区个数⼀致,那么其实只要知道每个分区的起始和结束柱⾯号,知道每 ⼀个柱⾯多少个扇区,那么该分区多⼤也就知道了。分区之后还可以再分组(分治的思想)。

inode

liunx下文件=文件内容+文件属性,并且内容和属性是分开存储的。文件内容存储在Data Block中。

文件的属性存储在inode table中。linux中任何的正常文件都要有自己的属性集合。虽然每一个文件的属性内容可能不一样,但是每一个文件都要有相同类型的属性,所以文件的属性可以用一个结构体来描述(大小就一定了)。这个结构体所连成的表上的一个节点就叫做inode(大小固定,一般是128bytes)

struct inode {struct hlist_node       i_hash;              /* 哈希表 */struct list_head        i_list;              /* 索引节点链表 */struct list_head        i_dentry;            /* 目录项链表 */unsigned long           i_ino;               /* 节点号 */atomic_t                i_count;             /* 引用记数 */umode_t                 i_mode;              /* 访问权限控制 */unsigned int            i_nlink;             /* 硬链接数 */uid_t                   i_uid;               /* 使用者id */gid_t                   i_gid;               /* 使用者id组 */kdev_t                  i_rdev;              /* 实设备标识符 */loff_t                  i_size;              /* 以字节为单位的文件大小 */struct timespec         i_atime;             /* 最后访问时间 */struct timespec         i_mtime;             /* 最后修改(modify)时间 */struct timespec         i_ctime;             /* 最后改变(change)时间 */unsigned int            i_blkbits;           /* 以位为单位的块大小 */unsigned long           i_blksize;           /* 以字节为单位的块大小 */unsigned long           i_version;           /* 版本号 */unsigned long           i_blocks;            /* 文件的块数 */unsigned short          i_bytes;             /* 使用的字节数 */spinlock_t              i_lock;              /* 自旋锁 */struct rw_semaphore     i_alloc_sem;         /* 索引节点信号量 */struct inode_operations *i_op;               /* 索引节点操作表 */struct file_operations  *i_fop;              /* 默认的索引节点操作 */struct super_block      *i_sb;               /* 相关的超级块 */struct file_lock        *i_flock;            /* 文件锁链表 */struct address_space    *i_mapping;          /* 相关的地址映射 */struct address_space    i_data;              /* 设备地址映射 */struct dquot            *i_dquot[MAXQUOTAS]; /* 节点的磁盘限额 */struct list_head        i_devices;           /* 块设备链表 */struct pipe_inode_info  *i_pipe;             /* 管道信息 */struct block_device     *i_bdev;             /* 块设备驱动 */unsigned long           i_dnotify_mask;      /* 目录通知掩码 */struct dnotify_struct   *i_dnotify;          /* 目录通知 */unsigned long           i_state;             /* 状态标志 */unsigned long           dirtied_when;        /* 首次修改时间 */unsigned int            i_flags;             /* 文件系统标志 */unsigned char           i_sock;              /* 可能是个套接字吧 */atomic_t                i_writecount;        /* 写者记数 */void                    *i_security;         /* 安全模块 */__u32                   i_generation;        /* 索引节点版本号 */union {void            *generic_ip;         /* 文件特殊信息 */};
};

每一个文件都有其对应的inode,里面包含了与该文件有关的一些信息。

文件系统先格式化出 inode 和 block 块,假设某文件的权限和属性信息存放到 inode 4 号位置,这个 inode 记录了实际存储文件数据的 block 号,由此,操作系统就能快速地找到文件数据的存储位置。

注意:

1. Linux下⽂件的存储是属性和内容分离存储的
2. Linux下,保存⽂件属性的集合叫做inode,⼀个⽂件,⼀个inode,inode内有⼀个唯⼀ 的标识符,叫做inode号。

3. Linux系统内部不使用文件名,而使用inode号码来识别文件。对于系统来说,文件名只是inode号码便于识别的别称或者绰号。表面上,用户通过文件名,打开文件。实际上,系统内部这个过程分成三步:首先,系统找到这个文件名对应的inode号码;其次,通过inode号码,获取inode信息;最后,根据inode信息,分析 inode 所记录的权限与用户是否符合,找到文件数据所在的block,读出数据。

4. ⽂件名属性并未纳⼊到inode数据结构内部

5.  inode的⼤⼩⼀般是128字节或者256
6. 任何⽂件的内容⼤⼩可以不同,但是属性⼤⼩⼀定是相同的

ext2文件系统

上面已经介绍了块和inode结构体(先描述),可是操作系统是怎么将这些管理起来的呢(再组织)?

我们想要在硬盘上储⽂件,必须先把硬盘格式化为某种格式的⽂件系统,才能存储⽂件。⽂件系统的⽬的就是组织和管理硬盘中的⽂件。
ext2⽂件系统将整个分区划分成若⼲个同样⼤⼩的块组 (Block Group),如下图所⽰。只要能管理⼀个 分区就能管理所有分区,也就能管理所有磁盘⽂件。

Boot Sector

上图中启动块(Boot Block/Sector)的⼤⼩是确定的,为1KB,由PC标准规定,⽤来存储磁盘分区信息和启动信息,任何⽂件系统都不能修改启动块。启动块之后才是ext2⽂件系统的开始。

Super Block

ext2⽂件系统会根据分区的⼤⼩划分为数个Block Group。⽽每个Block Group都有着相同的结构组
成。 对于每一个区最开始都有一个Boot Sector并且对于每一个block group都有一个Super block。superblock存放的是 ⽂件系统本⾝的结构信息,描述整个分区的⽂件系统信息。记录的信息主要有:bolck 和 inode的 总量,未使⽤的block和inode的数量,⼀个block和inode的⼤⼩,最近⼀次挂载的时间,最近⼀次写 ⼊数据的时间,最近⼀次检验磁盘的时间等其他⽂件系统的相关信息。Super Block的信息被破坏,可 以说整个⽂件系统结构就被破坏了。
注意:
超级块在每个块组的开头都有⼀份拷⻉(第⼀个块组必须有,后⾯的块组可以没有)。 为了保证⽂ 件系统在磁盘部分扇区出现物理问题的情况下还能正常⼯作,就必须保证⽂件系统的super block信 息在这种情况下也能正常访问。所以⼀个⽂件系统的super block会在多个block group中进⾏备份, 这些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 */
__le16 s_inode_size; /* size of inode structure */
。。。。。。。
};

GDP(group descriptor table)

块组描述符表(是用来管理这个组块的),描述块组的属性信息,整个分区分为多少个块组就有多少个块组描述符表。每一个块组描述表都存放着一个块组的信息,如这个块组从哪开始是inode Table,从哪里开始是Data Blocks,空闲的inode和数据块还有多少个等等。

注意块组描述描述符表在每一个块组的开头都有一份拷贝。

struct ext2_group_desc
{
__le32 bg_block_bitmap; /* Blocks bitmap block */
__le32 bg_inode_bitmap; /* Inodes bitmap */
__le32 bg_inode_table; /* Inodes table block*/
__le16 bg_free_blocks_count; /* Free blocks count */
__le16 bg_free_inodes_count; /* Free inodes count */
__le16 bg_used_dirs_count; /* Directories count */
__le16 bg_pad;
__le32 bg_reserved[3];
};

Block Bitmap(块位图)

每个位(bit)对应块组(block group)中的一个数据块(data block)。

  • 1 表示对应的数据块已被占用。

  • 0 表示数据块空闲可用。
    用于快速分配和释放数据块。

Inode Bitmap (inode位图)

每个位对应块组中的一个inode(索引节点)。

  • 1 表示对应的inode已被占用。

  • 0 表示inode空闲。
    用于管理文件/目录的元数据(如权限、大小等)的分配。

注意:
  • 物理存储
    每个位图占用一个完整的块(block),块大小由文件系统定义(如1KB、4KB等)。

    • 例如,4KB的块可存储 4 * 1024 * 8 = 32,768 个位,管理对应数量的数据块或inode。

  • 逻辑表示
    位数组按顺序排列,索引从0开始,直接映射到块组内的资源。

  • 与块组的关系

  • 每个块组独立维护自己的block bitmap和inode bitmap,实现分布式管理,减少竞争和碎片化。

  • 超级块(superblock)和组描述符(group descriptor)记录位图的位置(前面提到了)

Data Block

数据区:存放文件的内容,也就是一个一个的Block。
对于普通⽂件,⽂件的数据存储在数据块中。
对于⽬录,该⽬录下的所有⽂件名和⽬录名存储在所在⽬录的数据块中,除了⽂件名外,ls -l命令
看到的其它信息保存在该⽂件的inode中。
Block 号按照分区划分,不可跨分区。

inode和Datablock映射

inode内部存在 __le32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */ ,
EXT2_N_BLOCKS =15,就是⽤来进⾏inode和block映射的
这样⽂件=内容+属性,就都能找到了。
知道了inode号怎么找到对应的文件:
首先应该确定这个inode在哪一个分区,因为每一个分区中的超级块有一个字段是s_inodes_count,这个字段存储的就是这个分区中总的inode数量,然后同过该分区的其实inode号即可确认这个inode数否属于该分区。

然后需要确定该inode号属于哪个块组。每个块组中的inode数量应该是固定的,可以通过超级块中的s_inodes_per_group字段获得。假设超级块中有这个信息,那么块组号应该是(inode号 - 1)除以每个块组的inode数量,因为inode号通常从1开始。例如,如果每个块组有8192个inode,那么inode号8193属于第二个块组(索引从0开始的话,可能是块组1)。

确定了块组之后,接下来需要找到该块组的组描述符。组描述符里会有该块组的inode表的起始块号。然后,计算在该块组内的inode索引,即(inode号 - 1)% s_inodes_per_group。接着,用这个索引乘以inode的大小(比如128字节或256字节,由超级块中的s_inode_size决定),得到在inode表中的偏移量。这样就能找到该inode的具体位置了。

读取到inode结构之后,里面应该包含文件的元数据,比如模式(文件类型和权限)、用户和组ID、大小、时间戳等等。另外,inode中有直接块指针、间接指针、双重间接、三重间接指针等,用于定位文件的数据块。对于小文件,直接块指针就足够了;大文件则需要通过间接块来扩展寻址。

然后,要获取文件的内容,需要根据inode中的块指针读取相应的数据块。每个块指针指向一个数据块,数据块中存储着文件的实际内容。如果是目录的话,数据块中的内容会是目录条目,包含文件名和对应的inode号等信息。但题目中已经知道inode号,所以如果是普通文件,直接读取这些数据块即可得到文件内容。

我们在来看一下新建一个文件是如何完成的吧:

创建⼀个新⽂件主要有以下4个操作:
1. 存储属性
内核先找到⼀个空闲的i节点(这⾥是263466)。内核把⽂件信息记录到其中。
2. 存储数据
该⽂件需要存储在三个磁盘块,内核找到了三个空闲块:300,500,800。将内核缓冲区的第⼀块
数据复制到300,下⼀块复制到500,以此类推。
3. 记录分配情况
⽂件内容按顺序300,500,800存放。内核在inode上的磁盘分布区记录了上述块列表。
4. 添加⽂件名到⽬录
新的⽂件名abc。linux如何在当前的⽬录中记录这个⽂件?内核将⼊⼝(263466,abc)添加到
⽬录⽂件。⽂件名和inode之间的对应关系将⽂件名和⽂件的内容及属性连接起来。

目录和文件名

目录是文件,磁盘上是没有目录的概念的,都是文件属性+文件内容,对于目录的属性就不用多说了,目录的内容保存的是文件名+文件对应的inode号。

所以可以看到对于一个你要访问的文件,以一定要知道这个文件的路径,只有知道了路径你才能找打这个文件所在的文件夹,然后才能通过你提供的文件名来找到对应的inode号,才算是真正地找到了文件。

所以, 访问⽂件必须要知道当前⼯作⽬录,本质是必须能打开当前⼯作⽬录⽂件,查看⽬录⽂件的
内容!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[]) {if (argc != 2) {fprintf(stderr, "Usage: %s <directory>\n", argv[0]);exit(EXIT_FAILURE);}DIR *dir = opendir(argv[1]); // 系统调⽤,⾃⾏查阅if (!dir) {perror("opendir");exit(EXIT_FAILURE);}struct dirent *entry;while ((entry = readdir(dir)) != NULL) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..")== 0) continue;printf("Filename: %s, Inode: %lu\n", entry->d_name, (unsigned long)entry->d_ino);}closedir(dir);return 0;
}

路径解析

聪明的读者已经发现了问题,我们当前工作目录也是一个文件,所以要访问他还是需要打开他的上级目录,那就还要打开他的上上级目录。。。。

⽽实际上,任何⽂件,都有路径,访问⽬标⽂件,⽐如: /home/whb/code/test/test/test.c 都要从根⽬录开始,依次打开每⼀个⽬录,根据⽬录名,依次访问每个⽬录下指定的⽬录,直到访问 到test.c。这个过程叫做Linux路径解析。

那么路径都是谁提供的:

你访问⽂件,都是指令/⼯具访问,本质是进程访问,进程有CWD!进程提供路径。
你open⽂件,提供了路径
可是最开始的路径从哪⾥来?
所以Linux为什么要有根⽬录, 根⽬录下为什么要有那么多缺省⽬录?
你为什么要有家⽬录,你⾃⼰可以新建⽬录?
上⾯所有⾏为:本质就是在磁盘⽂件系统中,新建⽬录⽂件。⽽你新建的任何⽂件,都在你或者系
统指定的⽬录下新建,这不就是天然就有路径了嘛!
系统+⽤⼾共同构建Linux路径结构。

路径缓存

访问任何⽂件,都要从/⽬录开始进⾏路径解析,原则上是这样,但是这样太慢,所以Linux会缓存历史路径结构。
Linux⽬录的概念,怎么产⽣的? 打开的⽂件是⽬录的话,由OS⾃⼰在内存中进⾏路径维护。
linux中,在内核中维护树状路径结构的内核结构体叫做struct dentry
struct dentry
{atomic_t d_count;unsigned int d_flags;  /* protected by d_lock */spinlock_t d_lock;     /* per dentry lock */struct inode *d_inode; /* Where the name belongs to - NULL is* negative *//** The next three fields are touched by __d_lookup. Place them here* so they all fit in a cache line.*/struct hlist_node d_hash; /* lookup hash list */struct dentry *d_parent; /* parent directory */struct qstr d_name;struct list_head d_lru; /* LRU list *//** d_child and d_rcu can share memory*/union{struct list_head d_child; /* child of parent list */struct rcu_head d_rcu;} d_u;struct list_head d_subdirs; /* our children */struct list_head d_alias;   /* inode alias list */unsigned long d_time;       /* used by d_revalidate */struct dentry_operations *d_op;struct super_block *d_sb; /* The root of the dentry tree */void *d_fsdata;           /* fs-specific data */
#ifdef CONFIG_PROFILINGstruct dcookie_struct *d_cookie; /* cookie, if any */
#endifint d_mounted;unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */
};

每个⽂件其实都要有对应的dentry结构,包括普通⽂件。这样所有被打开的⽂件,就可以在内存中

形成整个树形结构
整个树形节点也同时会⾪属于LRU(Least Recently Used,最近最少使⽤)结构中,进⾏节点淘汰
整个树形节点也同时会⾪属于Hash,⽅便快速查找
更重要的是,这个树形结构,整体构成了Linux的路径缓存结构,打开访问任何⽂件,都在先在这
棵树下根据路径进⾏查找,找到就返回属性inode和内容,没找到就从磁盘加载路径,添加dentry
结构,缓存新路径

 

http://www.dtcms.com/wzjs/12782.html

相关文章:

  • 自己怎么用h5做网站想建立自己的网站怎么建立
  • 长安网站优化百度企业
  • excel做邮箱网站怎么加3www高端定制网站建设公司
  • 重庆江北区网站建设公司刚刚济南发通知
  • 郑州做商城网站公司seo刷关键词排名软件
  • 兼职网站建设收费百度广告怎么推广
  • 网站建设公司模板宁波网站seo公司
  • 互联网创业项目网下载seo站长查询
  • 做3个网站需要多大的服务器品牌营销推广策划公司
  • 网站设计字体杭州seo网
  • 自己开发电商网站难吗全国今日新增疫情
  • 中石化十建公司官网网站排名优化课程
  • 上海崇明网站建设网站建设小程序开发
  • go 语言 做网站网站优化培训学校
  • 太原免费建站北京百度网站排名优化
  • 自适应式网站模板seo怎么优化关键词排名培训
  • 定制网站制作哪家好软文模板app
  • 企业电商网站开发指数网站
  • 在北京做兼职哪个网站好杭州上城区抖音seo有多好
  • 网站开发模板教务管理18种最有效推广的方式
  • 网站建设投网页设计需要学什么软件
  • 株洲企业网站建设品牌百度爱采购优化
  • 做僾免费观看网站企业营销案例
  • 哪个网站可以做身份证数据分析培训
  • 枣庄高端网站建设最近一周的重大新闻
  • 做fcr的网站扬州seo博客
  • 小程序搭建价格seoshanghai net
  • 用python做网站我那些怎样在网上做推广
  • 大学生个体创业的网站建设seo推广服务哪家好
  • 门户网站建设请示浙江百度推广