您的位置:首页 > 文旅 > 美景 > 东莞招聘信息最新招聘2021_网站维护中是怎么回事_seo引擎优化是什么_百度关键词搜索排名

东莞招聘信息最新招聘2021_网站维护中是怎么回事_seo引擎优化是什么_百度关键词搜索排名

2025/2/23 12:46:29 来源:https://blog.csdn.net/2302_81171591/article/details/145795875  浏览:    关键词:东莞招聘信息最新招聘2021_网站维护中是怎么回事_seo引擎优化是什么_百度关键词搜索排名
东莞招聘信息最新招聘2021_网站维护中是怎么回事_seo引擎优化是什么_百度关键词搜索排名

理解硬件

磁盘、服务器、机柜、机房
 机械磁盘是计算机中唯一的一个机械设备
磁盘--- 外设,慢,容量大,价格便宜

 磁盘物理结构

  • 扇区是从磁盘读出和写入信息的最小单位,通常大小为 512 字节。
  • 磁头(head)数:每个盘片一般有上下两面,分别对应1个磁头,共2个磁头
  • 磁道(track)数:磁道是从盘片外圈往内圈编号0磁道,1磁道...,靠近主轴的同心圆用于停靠磁头,不存储数据
  •  柱面(cylinder)数:磁道构成柱面,数量上等同于磁道个数
  • 扇区(sector)数:每个磁道都被切分成很多扇形区域,每道的扇区数量相同
  • 圆盘(platter)数:就是盘片的数量
  • 磁盘容量=磁头数 × 磁道(柱面)数 × 每道扇区数 × 每扇区字节数 

磁盘的存储结构

 

扇区:是磁盘存储数据的基本单位,512字节,块设备

 如何定位一个扇区呢?

  • 可以先定位磁头(header)
  • 确定磁头要访问哪一个柱面(磁道)(cylinder)
  • 定位一个扇区(sector)
  • CHS地址定位

柱面(cylinder),磁头(head),扇区(sector),显然可以定位数据了,这就是数据定位(寻址)方式之一,CHS寻址方式。

 磁盘的逻辑结构

 磁带上面可以存储数据,我们可以把磁带“拉直”,形成线性结构

 那么磁盘本质上虽然是硬质的,但是逻辑上我们可以把磁盘想象成为卷在一起的磁带,那么磁盘的逻辑存储结构我们也可以类似于:

 这样每一个扇区,就有了⼀个线性地址(其实就是数组下标),这种地址叫做LBA

所以,磁盘的真实情况是:
磁道:
某一盘面的某一个磁道展开:


即:一维数组


柱面:
整个磁盘所有盘面的同一个磁道,即柱面展开: 

柱面上的每个磁道,扇区个数是一样的 

整盘:

整个磁盘不就是多张二维的扇区数组表(三维数组?)
所有,寻址一个扇区:先找到哪一个柱面(Cylinder) ,在确定柱面内哪一个磁道(其实就是磁头位置,Head),在确定扇区(Sector),所以就有了CHS。

所以,每一个扇区都有一个下标,我们叫做LBA(Logical Block Address)地址,其实就是线性地址。所以怎么计算得到这个LBA地址呢?

 LBA,1000,CHS 必须要! LBA地址转成CHS地址,CHS如何转换成为LBA地址。


OS只需要使用LBA就可以了!!LBA地址转成CHS地址,CHS如何转换成为LBA地址。谁做啊??磁盘自己来做!固件(硬件电路,伺服系统)

CHS && LBA地址 

CHS转成LBA:

  • 磁头数*每磁道扇区数 = 单个柱面的扇区总数
  • LBA = 柱面号C*单个柱面的扇区总数 + 磁头号H*每磁道扇区数 + 扇区号S - 1
  • 即:LBA = 柱面号C*(磁头数*每磁道扇区数) + 磁头号H*每磁道扇区数 + 扇区号S - 1
  • 扇区号通常是从1开始的,而在LBA中,地址是从0开始的
  • 柱面和磁道都是从0开始编号的
  • 总柱面,磁道个数,扇区总数等信息,在磁盘内部会自动维护,上层开机的时候,会获取到这些参数。

LBA转成CHS:

  • 柱⾯号C = LBA // (磁头数*每磁道扇区数)【就是单个柱面的扇区总数】
  • 磁头号H = (LBA % (磁头数*每磁道扇区数)) // 每磁道扇区数
  • 扇区号S = (LBA % 每磁道扇区数) + 1
  • "//": 表示除取整

所以:从此往后,在磁盘使用者看来,根本就不关心CHS地址,而是直接使用LBA地址,磁盘内部自己转换。所以:
从现在开始,磁盘就是一个 元素为扇区 的一维数组,数组的下标就是每一个扇区的LBA地址。OS使用磁盘,就可以用一个数字访问磁盘扇区了。

引入文件系统

引入"块"概念

其实硬盘是典型的“块”设备,操作系统读取硬盘数据的时候,其实是不会一个个扇区地读取,这样
效率太低,而是一次性连续读取多个扇区,即一次性读取一个”块”(block)。
硬盘的每个分区是被划分为一个个的”块”。一个”块”的大小是由格式化的时候确定的,并且不可
以更改,最常见的是4KB,即连续八个扇区组成一个 ”块”。”块”是文件存取的最小单位

  • 磁盘就是一个三维数组,我们把它看待成为一个"一维数组",数组下标就是LBA,每个元素都是扇区
  • 每个扇区都有LBA,那么8个扇区一个块,每一个块的地址我们也能算出来。
  • 知道LBA:块号 = LBA/8
  • 知道块号:LAB=块号*8 + n. (n是块内第几个扇区)

 引入"分区"概念

其实磁盘是可以被分成多个分区(partition)的,以Windows观点来看,你可能会有一块磁盘并且将它分区成C,D,E盘。那个C,D,E就是分区。分区从实质上说就是对硬盘的⼀种格式化。但是Linux的设备都是以⽂件形式存在,那是怎么分区的呢

柱面是分区的最小单位,我们可以利用参考柱面号码的方式来进行分区,其本质就是设置每个区的起始柱面和结束柱面号码。 此时我们可以将硬盘上的柱面(分区)进行平铺,将其想象成一个大的平面,如下图所示:

柱面大小一致,扇区个位一致,那么其实只要知道每个分区的起始和结束柱面号,知道每
一个柱面多少个扇区,那么该分区多大,其实和解释LBA是多少也就清楚了. 

引入"inode"概念 

之前我们说过 文件=数据+属性 ,我们使用 ls -l 的时候看到的除了看到文件名,还能看到文件元
数据(属性)。

每行包含7列:

  • 模式
  • 硬链接数
  • 文件所有者
  • 大小
  • 最后修改时间
  • 文件名

ls -l读取存储在磁盘上的文件信息,然后显示出来 

实这个信息除了通过这种方式来读取,还有一个stat命令能够看到更多信息 

 到这我们要思考一个问题,文件数据都储存在”块”中,那么很显然,我们还必须找到一个地方储存
文件的元信息(属性信息),比如文件的创建者、文件的创建日期、文件的大小等等。这种储存文件元信息的区域就叫做inode,中文译名为”索引节点”。

 每一个文件都有对应的inode,里面包含了与该文件有关的一些信息。为了能解释清楚inode,我们需要是深入了解⼀下文件系统。

注意:

  • Linux下文件的存储是属性和内容分离存储的
  • Linux下,保存文件属性的集合叫做inode,一个文件,一个inode,inode内有一个唯一
  • 的标识符,叫做inode号

所以一个文件的属性inode长什么样子呢?

/*
* Structure of an inode on the disk
*/
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 */
};
/*
* Constants relative to the data blocks
*/
#define EXT2_NDIR_BLOCKS
12
#define EXT2_IND_BLOCK
EXT2_NDIR_BLOCKS
#define EXT2_DIND_BLOCK
(EXT2_IND_BLOCK + 1)
#define EXT2_TIND_BLOCK
(EXT2_DIND_BLOCK + 1)
#define EXT2_N_BLOCKS
(EXT2_TIND_BLOCK + 1)
备注:EXT2_N_BLOCKS = 15

文件名属性并未纳入到inode数据结构内部

  • inode的大小一般是128字节或者256,我们后面统一128字节
  • 任何文件的内容大小可以不同,但是属性大小一定是相同的

ext2 文件系统

所有的准备工作都已经做完,是时候认识下文件系统了。我们想要在硬盘上储文件,必须先把硬盘格式化为某种格式的文件系统,才能存储文件。文件系统的目的就是组织和管理硬盘中的文件。在
Linux 系统中,最常见的是 ext2 系列的文件系统。其早期版本为 ext2,后来又发展出 ext3 和 ext4。
ext3 和 ext4 虽然对 ext2 进行了增强,但是其核心设计并没有发生变化,我们仍是以较老的 ext2 作为演示对象。
ext2文件系统将整个分区划分成若干个同样大小的块组 (Block Group),如下图所示。只要能管理一个分区就能管理所有分区,也就能管理所有磁盘文件。

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

Block Group

ext2文件系统会根据分区的大小划分为数个Block Group。而每个Block Group都有着相同的结构组
成。

Super Block(超级块)

存放文件系统本身的结构信息,描述整个分区的文件系统信息。记录的信息主要有:bolck 和 inode的总量,未使用的block和inode的数量,一个block和inode的大小,最近一次挂载的时间,最近一次写入数据的时间,最近一次检验磁盘的时间等其他文件系统的相关信息。Super Block的信息被破坏,可以说整个文件系统结构就被破坏了

超级块在每个块组的开头都有一份拷贝(第一个块组必须有,后面的块组可以没有)。 为了保证文件系统在磁盘部分扇区出现物理问题的情况下还能正常工作,就必须保证文件系统的super block信息在这种情况下也能正常访问。所以一个文件系统的super block会在多个block group中进行备份,这些super block区域的数据保持一致。

/*
* Structure of the 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 */
/*
* 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...
*/
__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 */
/*
* 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;
/*
* Journaling support valid if EXT3_FEATURE_COMPAT_HAS_JOURNAL set.
*/
__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 */
};

GDT(Group Descriptor Table)

块组描述符表,描述块组属性信息,整个分区分成多个块组就对应有多少个块组描述符。每个块组描述符存储一个块组 的描述信息,如在这个块组中从哪里开始是inode Table,从哪里开始是Data
Blocks,空闲的inode和数据块还有多少个等等。块组描述符在每个块组的开头都有一份拷贝。

// 磁盘级blockgroup的数据结构
/*
* Structure of a blocks group descriptor
*/
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)
Block Bitmap中记录着Data Block中哪个数据块已经被占用,哪个数据块没有被占用

inode位图(Inode Bitmap)
每个bit位表示一个inode是否空闲可用。

i节点表(Inode Table)

  • 存放文件属性 如 文件大小,所有者,最近修改时间等
  • 当前分组所有Inode属性的集合
  • inode编号以分区为单位,整体划分,不可跨分区

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号的情况下,在指定分区,请解释:对文件进行增、删、查、改是在
做什么?
 

[root@localhost linux]# touch abc
[root@localhost linux]# ls -i abc
263466 abc

 为了说明问题,我们将上图简化:

创建一个新文件主要有以下4个操作: 

存储属性

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

 目录与文件名
问题:
我们访问文件,都是用的文件名,没用过inode号啊?目录是文件吗?如何理解?
答案:
目录也是文件,但是磁盘上没有目录的概念,只有文件属性+文件内容的概念。目录的属性不用多说,内容保存的是:文件名和Inode号的映射关系

访问文件,必须打开当前目录,根据文件名,获得对应的inode号,然后进行文件访问
访问文件必须要知道当前工作目录,本质是必须能打开当前工作目录文件,查看目录文件的
内容!

路径解析
问题:

  打开当前工作目录⽂件,查看当前工作目录文件的内容?当前工作目录不也是文件吗?我们访问当前工作目录不也是只知道当前工作目录的文件名吗?要访问它,不也得知道当前工作目录的inode吗?
所以也要打开:当前工作目录的上级目录,额....,上级目录不也是目录吗??不还是上面的问题吗?
所以类似"递归",需要把路径中所有的目录全部解析,出口是"/"根目录。
而实际上,任何文件,都有路径,访问目标文件,比如:/home/whb/code/test/test/test.c
都要从根目录开始,依次打开每一个目录,根据目录名,依次访问每个目录下指定的目录,直到访问到test.c。这个过程叫做Linux路径解析。

要找到一个aa文件,就得找到对应的inode,通过映射关系打开文件(所以inode唯一,文件名字也唯一,不可重复),而该文件的inode又存放在它的上一级目录【学习代码】文件下,而要找到上一级的inode才能打开上一级目录,而上一级目录的inode又存放在上上一级目录【113】下,所以会一直递归找下去直到根目录,而根目录是操纵系统在开机下固定打开的,所以,系统找文件是从左向右依次找的,直到找到要打开的aa文件,打开home目录,找到xm目录的inode,通过映射关系打开,然后依次路径解析,再找113,再找学习代码,最后打开aa

我们找文件必须要有路径!平时我们创建文件或者ls找文件没有带路径是因为操作系统给我们记录下文件路径了

我们平时访问文件,操作指令等,但凡动一下都是通过转化给操作系统来完成,操作系统把用户操作转化位进程,而进程再pcb中就会维护自己的环境变量,而进程的cwd又是从bash中来的,而bash又是从系统中来的,所以,我们可以理解:文件名由用户提供,文件路径由进程提供!  

注意:
所以,我们知道了:访问文件必须要有目录+文件名=路径的原因
根目录固定无件名,inode号,无需查找,系统开机之后就必须知道

可是路径谁提供?

  • 访问文件,都是指令/工具访问,本质是进程访问,进程有CWD!进程提供路径。
  • open文件,提供了路径

上面所有行为:本质就是在磁盘文件系统中,新建目录文件。而你新建的任何文件,都在你或者系
统指定的目录下新建,这不就是天然就有路径了嘛!系统+用户共同构建Linux路径结构.

路径缓存
问题1:Linux磁盘中,存在真正的目录吗?
答案:不存在,只有文件。只保存文件属性+文件内容
问题2:访问任何文件,都要从/目录开始进行路径解析?
答案:原则上是,但是这样太慢,所以Linux会缓存历史路径结构
问题2: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_PROFILING
struct dcookie_struct *d_cookie; /* cookie, if any */
#endif
int d_mounted;
unsigned char d_iname[DNAME_INLINE_LEN_MIN];
/* small names */
};

 注意:

  • 每个文件其实都要有对应的dentry结构,包括普通文件。这样所有被打开的文件,就可以在内存中形成整个树形结构
  • 整个树形节点也同时会⾪属于LRU(Least Recently Used,最近最少使用)结构中,进行节点淘汰整个树形节点也同时会⾪属于Hash,方便快速查找
  • 更重要的是,这个树形结构,整体构成了Linux的路径缓存结构,打开访问任何⽂件,都在先在这棵树下根据路径进行查找,找到就返回属性inode和内容,没找到就从磁盘加载路径,添加dentry结构,缓存新路径

文件系统总结

 软硬连接

1.硬链接

我们看到,真正找到磁盘上文件的并不是文件名,而是inode。其实在linux中可以让多个文件名对应于同一个inode。

inode一样,硬链接不是一个独立的文件,相比软连接,权限后面的数字不再是1 ,后面数字代表映射数量,文件名指向链接文件,叫硬连接数。

2.软链接
硬链接是通过inode引用另外一个文件,软链接是通过名字引用另外一个文件,但实际上,新的文件和被引用的文件的inode不同,应用常见上可以想象成一个快捷方式。在shell中的做法

 创建了一个独立文件,类似于快捷方式,对code.c修改,code-soft运行也会变

 下面解释一下文件的三个时间:

  • Access 最后访问时间
  • Modify 文件内容最后修改时间
  • Change 属性最后修改时间

软硬连接对比


• 软连接是独立文件
• 硬链接只是文件名和目标文件inode的映射关系
软硬连接的用途:
硬链接
• .和.. 就是硬链接
• 文件备份
软连接
• 类似快捷方式

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com