Linux:文件系统

news2025/1/20 14:59:07

Linux:文件系统

    • 磁盘
      • 物理结构
      • 存储结构
      • 逻辑结构
    • 文件系统
      • inode
      • 分区 & 分组
      • 分区管理
        • inode Bitmap & inode Table
        • Block Bitmap & Data Blocks
        • GDT & Super Block & Boot Block
      • 重新理解目录
    • 软硬链接
      • 软链接
      • 硬链接
      • 软硬链接的使用场景


磁盘

计算机需要存储数据,主要有两种存储数据的硬件,内存和硬盘,其中内存需要通电,具有较高的数据交换效率,适合用于存储计算时产生的临时数据。对于长期保存的数据,一方面来说我们无法保证计算机永远通电,另一方面内存的价格太高了,因此计算机需要硬盘这种无需通电,价格低廉的存储介质来存储数据。

存储在硬盘中的数据,一般称为文件。本博客讲解在硬盘中,数据是如何被组织管理的,也就是文件系统

硬盘主要有磁盘SSD,而当代的个人计算机已经不使用磁盘了,而是使用SSD

在这里插入图片描述

上图中,左侧是磁盘,右侧是SSD。那么为什么我们还要讲磁盘,而不是SSD呢?

首先,磁盘的文件系统与SSD是十分相似的,磁盘文件系统的设计考虑了存储介质的通用性,因此可以很好地适用于SSD,不过可能会有针对SSD的特殊优化,但是不会影响文件系统的大框架。

其次,我们个人计算机使用的磁盘叫做消费级磁盘,虽然个人计算机已经不再使用磁盘了,但是由于低廉的价格,服务器主机使用的依然是磁盘,这种磁盘叫做企业级磁盘

Linux作为一个适用于服务器的操作系统,通过磁盘来理解文件系统,毫无疑问是合适的。

物理结构

先来看看磁盘的物理结构,了解磁盘底层是如何运作的。

在这里插入图片描述

对于企业级磁盘来说,一个磁盘会有多个盘面,也就是上图中的样子。

磁盘的盘面很像我们平常见到的光盘,光盘一般是一面图案,一面用于读取。而磁盘的盘面两面都是可以读写的。上图中,磁头就是用来对磁盘进行读写的工具,马达会带着盘面高速旋转,此时磁头再来回摆动,就可以通过磁头访问到整个盘面。由于盘的两面都可读写,因此一个盘的正反两面都是需要一个磁头的。

磁盘之所以叫做磁盘,就是因为其通过磁性来存储数据。计算机数据是由众多01二进制组成的,而磁铁分为NS两级,可以想象磁盘中有无数个小磁铁,通过改变这个小磁铁的NS极,来改变这个位置表达的01


存储结构

简单了解磁盘的物理结构后,再看看磁盘的存储结构:

在这里插入图片描述

磁盘的每个盘面,都会被为多个等宽的同心圆环,这样一个圆环叫做磁道/柱面。而一个磁道又会被划分为很多个小扇形,每个扇形叫做一个扇区

扇区是磁盘IO的基本单位,大小一般为固定的512 byte

有人可能就会有疑问:既然每个扇区的宽度都是相同的,那么内圈的扇区面积小,外圈扇区面积大,为什么扇区的大小都为512 byte

磁盘在生产的时候,厂家会调整不同区域的密度,内圈区域密度大,外圈区域密度小,最后可以保证每个扇区的大小都是相同的。

计算机通过磁盘访问数据时,通过CSH定位法:

  1. 决定访问哪一个磁道(Cylinder)
  2. 决定访问哪一个磁头(Head),也就是决定哪一个盘面
  3. 决定访问哪一个扇区(Sector)

只需要确定CHS这三者,就可以确定一个磁盘的扇区,进行写入或读取。


逻辑结构

在操作系统眼中,磁盘不是一个环形结构,而是一个逻辑上的结构来访问。

在播音机中,常会见到这样的磁带:

在这里插入图片描述

磁带有两个磁带盘,如右图,左侧的磁带被拉直后,经过读写头,再卷入右侧的磁带盘。

这个过程中,环形的磁带被拉直,形成一个线性结构,那么我们是否可以在逻辑上把环形的磁盘拉直为一个线性结构?

在这里插入图片描述

这样我们就可以把整个磁盘抽象为一个线性结构,此时操作系统对磁盘的管理,就变成了对数组的增删查改

但是由于扇区的大小为512 byte,如果操作系统只能每次按照512 byte为单位进行写入,效率太低了。所以操作系统一般以4 kb为单位进行写入,其中4 kb = 8 * 512 byte,即每次按照八个扇区为一个基本单位进行写入。哪怕用户只写入1 byte数据,操作系统也会在磁盘中开出4 kb大小的空间

在这里插入图片描述

操作系统会在系统层面把八个扇区合成一个数据块,并对每个数据块进行重新编址,比如上图中,1 - 8号扇区,就被合成了1号数据块。这个数据块的地址,叫做LBA(Logical Block Address)地址,当操作系统要对磁盘写入时,先把LBA地址转化为线性地址,也就是一个个扇区的地址,然后再把线性地址转化为CHS地址,之后磁盘就可以根据CHS地址来访问到指定扇区了。


文件系统

简单了解了磁盘的硬件结构后,再来看看操作系统是如何在全局上管理这个磁盘的。

inode

所有被存储在磁盘的数据,都是以文件的形式,那么每个文件是如何被管理的呢?

文件可以被分为两个部分:

文件 = 内容 + 属性 {\color{Red} \mathbf{文件 = 内容 + 属性 } } 文件=内容+属性

Linux中,文件的内容和属性是分开管理的,因为文件的内容大小是不确定的,而每个文件的具有属性都是相同的,只是属性值不同。Linux把文件的属性放在结构体struct inode中管理

Linux 2.6.10内核的struct inode部分源码如下:

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;
	gid_t			i_gid;
	dev_t			i_rdev;
	loff_t			i_size;
	struct timespec		i_atime;
	struct timespec		i_mtime;
	struct timespec		i_ctime;
	//......
};

由于inode的成员太多,我这里只截取了一小部分,大约是总量的四分之一。所有文件的属性都被这样的inode管理

以下是inode中一些重要的成员及其含义:

  1. i_inoinode 的编号,这个编号是文件系统中唯一标识一个 inode 的数字

  2. i_mode:文件的访问权限和文件类型(常规文件、目录、设备文件等)

  3. i_uidi_gid:文件所有者的用户ID和组ID

  4. i_size:文件大小(以字节为单位)

  5. i_atimei_mtimei_ctime:最后访问时间、最后修改时间和最后状态改变时间

  6. i_blocks:文件占用的磁盘块数

  7. i_links_count:文件的硬链接数

这些inode成员记录了文件的基本属性、访问权限、所有权、位置信息等,是文件系统管理文件的关键数据结构。不同的文件系统可能会有一些细微的差异,但基本结构和含义是相同的。

以上重要成员中,你也许对6 7有疑问,这三者会在博客后续讲解。

第一条i_ino用于在一个文件系统中标识一个唯一的inode,操作系统对文件写入时,就是通过i_ino来查找文件的,我们一般称其为inode编号

可以通过ls-i选项查看文件的inode编号:

在这里插入图片描述

其中左侧第一栏就是文件对应的inode编号了。


分区 & 分组

现在的计算机已经不怎么会缺少存储空间了,因为硬盘的价格普遍不贵,很多计算机的容量都是以TB为单位了,服务器中的存储空间就更大了。操作系统不可能一次性对以TB为单位的磁盘进行管理,于是就把磁盘分为很多个区域,然后分别管理每一个区域,这就是磁盘分区

提到分区,想必第一个想到的就是各自Windows主机中的C盘D盘了,以下为我的个人主机,大小约为1TB

在这里插入图片描述

C盘D盘并不是两个硬盘,而是一个硬盘的两个分区。也就是说是我的Windows中,把1TB分为了两个分区来管理,当然你也可以自己再划分更多的分区出来。

而对于一个分区,操作系统又会把它划分为很多个分组:

在这里插入图片描述

现在操作系统只需要按照相同的方式来管理一个个相同的分组,就可以管理好整个硬盘了。


分区管理

现在开始,我们只讨论一个分区内部如何管理的了,因为每个分区的管理是相同的,只需要理解一个分区如何管理,就知道所有分区如何管理,最后就知道整个磁盘如何管理的了。

操作系统通过文件系统来管理一个分区,每个分区都会有一套独立的文件系统,现在主流文件系统是Ext3文件系统,本博客后续讲解的是Ext2文件系统,两者没有太大差别。

值得注意是,一个硬盘可以有多个分区,不同分区是可以搭载不同的文件系统的

基于Ext2文件系统,每个分区都有如下结构:

在这里插入图片描述

/*
 * Structure of a blocks group descriptor
 */
struct ext2_group_desc
{
	__le32	bg_block_bitmap;		/* Blocks bitmap block */
	__le32	bg_inode_bitmap;		/* Inodes bitmap block */
	__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];
};

inode Bitmap & inode Table

一个分组中,会有大量的文件,每个文件都要有自己的inode来存储自己的信息,一个分组的所有文件的inode结构体,都存储在该分组的inode Table

在这里插入图片描述

当新创建文件的时候,要给这个文件分配一个inode,那么一个分组要如何给一个文件分配inode呢?总不可能是生成一个随机数,然后直接分配这个inode编号对应的inode给文件吧?

因此每个分组还会维护一张位图inodeBitmap,其用inode编号对应的位来标记一个inode的状态。通过查找位图,从而快速判断一个inode是否已经被分配过了。

inode描述一个文件属性的结构体,包含了大量文件的属性。Ext2也有自己的inode,其基于inode增加了某些其它信息,用于帮助管理

Linux 2.6.10内核的struct ext2_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 */
	//...

	__le32	i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
	//...
};

我们可以从中看到非常多熟悉的成员,比如i_modei_uid等等,但是我特意在最后写出来了一个i_block成员,这是一个极为重要的成员,其与硬盘空间分配有关,接下来我们了解一下空间是如何分配的。


Block Bitmap & Data Blocks

刚才提到,文件 = 内容 + 属性,我们已经了解了文件的属性被inode管理,而inode被分组中的inode Table管理。那么文件系统如何管理内容的呢?这就是Block BitmapData Blocks的任务了。

在这里插入图片描述

分组是用来存储文件的,自然要存储文件的内容,而文件的内容要放到数据块中,而所有的数据块,都由Data Blocks管理。

inode Bitmap相似的,Block Bitmap也是一个位图,用于标识哪些数据块被使用了,哪些没被使用,从而快速给文件分配数据块

那么Data Blocks是如何分配数据的?

我们在上一个小节末尾留了一个成员i_block,其存在于inode中:

struct ext2_inode {
	//...
	__le32	i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
	//...
};

Linux源码对其的注释是/* Pointers to blocks */,也就是指向的数据块。inode中的i_block成员,用于存储该文件使用了哪些数据块

i_block是一个数组,元素的类型是__le32,本质上是一个32位的int类型,元素的个数是EXT2_N_BLOCKS,这个值等于15

在源码中,EXT2_N_BLOCKS定义如下:

/*
 * 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)

最后值就是12 + 1 + 1 + 1 = 15,为什么要周转这么久,一个一个加上去?

了解了i_block是如何指向数据块后,我们就可以解决这个问题了:

i_block的数组下标分为四个区域:[0, 11][12][13][14]

前十二个元素[0, 11],它们直接指向存储文件内容的数据块:

在这里插入图片描述

哪些数据块存储了文件内容,这些元素就存储对应数据块的编号。

下标为[12]的元素,指向一级间接块

在这里插入图片描述

当文件使用的数据块超过了12个,就会启用下标为[12]的元素,其指向一级间接块,一级间接块中存储了其他数据块的编号,被一级间接块指向的数据块,才是真正存放文件内容的数据块

上图中,绿色的数据块是存放文件内容的数据块,蓝色数据块是一级间接块。

下标为[13]的元素,指向二级间接块

在这里插入图片描述

当使用的数据块数量超过一级间接块的范围,就会启用下标为[13]的元素,其指向二级间接块,二级间接块指向一级间接块,被一级间接块指向的数据块,才是真正存放文件内容的数据块。上图中,灰色的为二级间接块。

下标为[14]的元素,指向三级间接块

在这里插入图片描述

当使用的数据块数量超过二级间接块的范围,就会启用下标为[14]的元素,其指向三级间接块,三级间接块指向二级间接块。上图中,紫色的为三级间接块。

文件系统利用这样一个间接块的设计,用长度为15的数组,保存了文件使用的所有数据块。

现在我们再看到当时EXT2_N_BLOCKS的定义过程:

/*
 * 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)
  1. #define EXT2_NDIR_BLOCKS 12

    • 这个宏定义了 Ext2 文件系统中 inode 中直接块的数量为 12
  2. #define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS

    • 其中 IND表示:singly indirect block 一级间接块
    • 这个宏定义了一级间接块的数组下标为 12
  3. #define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)

    • 其中 DIND表示:doubly indirect block 二级间接块
    • 这个宏定义了二级间接块的数组下标为 13
  4. #define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)

    • 其中 TIND表示:triple indirect block 三级间接块
    • 这个宏定义了三级间接块的数组下标为 14
  5. #define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)

    • 这个宏定义了 Ext2 文件系统中总共的数据块索引数为 15
    • 包括 12 个直接块、1 个一级间接块、1 个二级间接块和 1 个三级间接块。

GDT & Super Block & Boot Block

现在我们已经讲清楚了一个文件是如何存储的,文件 = 内容 + 属性,属性被inode Table管理,而内容被Data Blocks管理。那么这个文件系统整体又是如何被管理的呢?这就与Super BlockGroup Descriptor Table还有Boot Block有关了。

在这里插入图片描述

Group Descriptor Table叫做块组描述符表,简称GDT,用于宏观描述一个分组

Linux 2.6.10内核的struct ext2_group_desc源码如下:

struct ext2_group_desc
{
	__le32	bg_block_bitmap;		/* Blocks bitmap block */
	__le32	bg_inode_bitmap;		/* Inodes bitmap block */
	__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];
};

我简单翻译一下注释:

bg_block_bitmap:组中块位图所在的块号
bg_inode_bitmap:组中索引节点位图所在块的块号
bg_inode_table:组中索引节点表的首块号
bg_free_blocks_count:组中空闲块数
bg_free_inodes_count:组中空闲索引节点数
bg_used_dirs_count:组中分配给目录的节点数

可以看到,GDT描述了各个区域的起始位置,以及当前分组的总体状态,每个分组都有自己的GDT

Super Block用于存放文件系统本身的结构信息

Linux 2.6.10内核的struct ext2_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 */
	//...
};

从上图中可以看出这个Super Block存储了整个文件系统的inode的数量,数据块的数量等等。这种对文件系统宏观描述的结构,因该来说每个分区只需要一个即可,为什么会放在分组里面呢?

并不是所有的分组都有Super Block,只有非常小一部分分组有Super Block是代表一个文件系统的核心数据结构,一旦Super Block损毁,整个文件系统都会崩溃,因此文件系统不只把Super Block保留一份,而是保留多份放到不同分组中。

需要Super Block时到特定分组去访问,一旦某个分组的Super Block被损毁,用其它的Super Block进行拷贝,从而修复Super Block。这样可以极大提高文件系统的稳定性。

Boot Block用于计算机开机时告知磁盘的分区情况,帮助计算机加载操作系统等

操作系统本质也是一个软件,开机时计算机要加载操作系统,毫无疑问操作系统也要被存储在硬盘中,Boot Block就会存储操作系统的存储位置,从而帮助计算机启动操作系统。

Boot Block不仅仅是一个分区只有一个,而是整个硬盘中只有一个,放在整个硬盘的第一个分区头部


现在总结一下刚才讲解的结构:

在这里插入图片描述

  • inode Table:存储当前分组所有文件的inode
  • inode Bitmap:标识当前分组的inode的使用情况
  • Data Blocks:管理当前分组的数据块
  • Block Bitmap:标识当前分组的数据块的使用情况
  • GDT:宏观描述一个分组
  • Super Block:描述一个分区,文件系统的核心
  • Boot Block:描述整个硬盘的分区情况,帮助计算机加载操作系统

重新理解目录

有了以上知识后,我们再来重新理解一下目录这个结构。目录的本质也是文件,那么目录是如何存储其内部的文件的呢?

目录内部存储的是 文件名inode编号的映射关系

这里有一个很重要的知识:文件名不属于文件的属性,也不存在于inode中

文件名存在于目录中,而不存在于文件本身。我们通过目录来访问文件名,本质是去目录文件中,通过文件名找到对应的inode编号,然后再访问到文件

比如说现在通过路径/usr/bin/ls来访问一个文件,其过程为:

  1. 先在根目录中找到文件名usr对应的inode编号
  2. 访问文件usr,在文件usr中找到文件名bin对应的inode编号
  3. 访问文件bin,在文件bin中找到文件名ls对应的inode编号
  4. 访问文件ls

软硬链接

在Linux中,文件和目录有两种特殊的链接方式,分别称为软链接(Soft Link)和硬链接(Hard Link)。这两种链接方式都是用于创建文件或目录的快捷方式,但它们在实现原理和使用场景上存在一些差异。

软链接

软链接也称为符号链接,它是一种特殊的文件,其中包含了另一个文件或目录的路径信息

创建软链接的命令如下:

ln -s 源文件/目录 软链接名称

此处的-s表示soft

示例:

当前目录下有一个soft.txt

在这里插入图片描述

现在为其建立一个软链接,名为link-soft.txt

在这里插入图片描述

可以看到我们成功创建了一个软链接,使用ls时也指明了link-soft.txt -> soft.txt,即文件link-soft.txtsoft.txt的链接。

通过最左侧第一栏可知,软链接和原文件的inode不同,说明是不同的两个文件,只是软链接的文件内部存储的是目标文件的路径

软链接的主要特点如下:

  1. 文件类型:软链接是一种特殊的文件类型,在文件列表中以 l 开头表示
  2. 链接目标:软链接中存储的是链接目标的路径信息,而不是实际的文件内容
  3. 独立性:软链接是独立于链接目标的,即使链接目标被删除或移动,软链接仍然存在,只是无法访问实际的文件或目录
  4. 跨文件系统:软链接可以跨越不同的文件系统,链接到不同分区或网络共享中的文件或目录

硬链接

硬链接是另一种创建文件快捷方式的方法,它与软链接有一些不同之处。

创建硬链接的命令如下:

ln 源文件/目录 软链接名称

示例:

当前目录下有一个hard.txt

在这里插入图片描述

现在为其建立一个硬链接,名为link-hard.txt

在这里插入图片描述

可以看到我们成功创建了一个硬链接,值得注意的是:硬链接的inode与原文件的inode相同!

硬链接本质上,只是在目录内部,多增加了一个文件名与inode的映射关系

从左往右数第三栏,你会发现soft.txt的值为1,而hard.txt的值为2,这个值叫做硬连接数,即有多少个相同的文件名指向这个inode

硬链接的主要特点如下:

  1. 文件类型:硬链接在文件列表中看起来与普通文件没有区别
  2. 链接目标:硬链接指向实际文件的数据块,而不是文件路径
  3. 独立性:硬链接依赖于链接目标,如果链接目标被删除,硬链接也将失效
  4. 跨文件系统:硬链接只能在同一个文件系统内创建,不能跨越不同的文件系统

如果想要删除一个软连接或者硬连接,使用指令unlink即可

还要注意的是:不能给目录创建硬连接,只能给目录创建软链接


软硬链接的使用场景

软链接和硬链接各有适用的场景:

软链接

  • 在不同文件系统或分区之间创建快捷方式
  • 链接到可能会被移动或删除的文件或目录
  • 创建指向目录的快捷方式

硬链接

  • 为同一个文件创建多个名称
  • 提高文件访问效率,因为硬链接直接指向文件数据块
  • 备份或归档文件时保留文件的硬链接关系

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

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

相关文章

C++中vector的简单实现

文章目录 一、主要任务1. 查看文档的网站的链接2.内部模拟的函数 二、本人的模拟实现过程1. 所需模拟实现的函数a.构造、拷贝构造b. reverse()扩容c.insert()、push_back()插入数据d. erase()、pop_back()删除数据e. swap()交换f. begin()、end()非const与const迭代器g. 完善构…

什么是$t?$t的介绍及使用

目录 $t介绍&#xff1a; 作用&#xff1a; 安装国际化插件&#xff1a; 创建国际化资源文件 配置 vue-i18n &#xff1a; 切换语言&#xff1a; 下面为中文和英文状态下的效果&#xff1a; 如下面所示&#xff0c;这是一段前端代码&#xff1a; <el-form-item :label…

如何在 Linux / Ubuntu 上下载和安装 JMeter?

Apache JMeter 是一个开源的负载测试工具&#xff0c;可以用于测试静态和动态资源&#xff0c;确定服务器的性能和稳定性。在本文中&#xff0c;我们将讨论如何下载和安装 JMeter。 安装 Java&#xff08;已安装 Java 的此步骤可跳过&#xff09; 安装 Java 要下载 Java&…

序列到序列模型在语言识别Speech Applications中的应用 Transformer应用于TTS Transformer应用于ASR 端到端RNN

序列到序列模型在语言识别Speech Applications中的应用 A Comparative Study on Transformer vs RNN in Speech Applications 序列到序列(Seq2Seq)模型在语音识别(Speech Applications)中有重要的应用。虽然Seq2Seq模型最初是为了解决自然语言处理中的序列生成问题而设计的…

访客管理系统对于校园安全的重要性

校园访客办理计划是针对校园安全需求规划的安全办理体系&#xff0c;主要用于对校园外来人员的科学办理。要做好校园安全作业&#xff0c;把风险分子拒之门外尤为要害。校园访客办理计划实现访客实名制&#xff0c;并结合公安网、黑名单功用&#xff0c;对风险人员进行提前预警…

指针的奥秘(四):回调函数+qsort使用+qsort模拟实现冒泡排序

指针 一.回调函数是什么&#xff1f;二.qsort函数使用1.qsort介绍2.qsort排序整型数据3.qsort排序结构体数据1.通过结构体中的整形成员排序2.通过结构体中的字符串成员排序 三.qsort模拟实现冒泡排序 一.回调函数是什么&#xff1f; 回调函数就是一个通过函数指针调用的函数。 …

机器人系统ros2-开发实践07-将机器人的状态广播到 tf2(Python)

上个教程将静态坐标系广播到 tf2&#xff0c;基于这个基础原理这个教程将演示机器人的点位状态发布到tf2 1. 写入广播节点 我们首先创建源文件。转到learning_tf2_py我们在上一教程中创建的包。在src/learning_tf2_py/learning_tf2_py目录中输入以下命令来下载示例广播示例代码…

显卡、显卡驱动、CUDA、cuDNN、CUDA Toolkit、NVCC、nvidia-smi等概念的区别与联系

在科技日新月异的今天&#xff0c;显卡、显卡驱动、CUDA、cuDNN、CUDA Toolkit、NVCC、nvidia-smi等术语已经成为了科技领域的重要组成部分。本文旨在阐述这些术语之间的区别与联系&#xff0c;帮助您更好地理解它们在技术生态系统中的作用。 一、显卡 显卡&#xff0c;也称为…

利用PS在不伤背景的前提下根据颜色去除图像上不想要的内容

下面为一个例子&#xff0c;去除图像上红色的虚线 Step1.用套索工具框选带有颜色的部分 Step2.切换到魔术棒工具&#xff0c;上端选项中&#xff0c;点击与选区交叉&#xff0c;连续这一项不要勾选 Step3.在需要去除的部分点击一下即可在框选范围内选中所有同颜色的区域&#x…

“二代”接班进行时:达利食品许阳阳揭秘“零食大王”成长密钥

“二代接班”早已不是一个新鲜话题。近年来&#xff0c;随着时间的推移&#xff0c;那些伴随改革开放和中国制造崛起的民营企业&#xff0c;更多的正在经历或已完成“二代接班”。 “毛巾王子”家的洁丽雅&#xff0c;最近因大手笔签约多位代言人而引起讨论的九牧王&#xff0…

用python写算法——队列笔记

1.队列定义 队列是一种特殊的线性表&#xff0c;它只允许在表的前端进行删除操作&#xff0c;在表的后端进行插入操作&#xff0c;和栈一样&#xff0c;队列是一种操作受限制的线性表。进行插入操作的端称为队尾&#xff0c;进行删除操作的端称为队头。队列中没有元素时&#…

MATLAB的Bar3函数调节渐变色(内附渐变色库.mat及.m文件免费下载链接)

一. colormap函数 可以使用colormap函数&#xff1a; t1[281.1,584.6, 884.3,1182.9,1485.2; 291.6,592.6,896,1197.75,1497.33; 293.8,596.4,898.6,1204.4,1506.4; 295.8,598,904.4,1209.0,1514.6];bar3(t1,1) set(gca,XTickLabel,{300,600,900,1200,1500},FontSize,10) set…

机器学习周记(第三十八周:语义分割)2024.5.6~2024.5.12

目录 摘要 ABSTRACT 1 DeeplabV3实现思路 预测部分 ①主干网络介绍​编辑 ② 加强特征提取结构 ③ 利用特征获得预测结果 摘要 本周继续了语义分割的学习&#xff0c;主要学习了DeepLabV3的部分实现思路&#xff0c;即DeepLabV3的整个模型的预测过程&#xff0c;并通过代…

HCIP(BGP综合实验)--8

一&#xff1a;实验要求 二&#xff1a;实现过程 &#xff08;一&#xff09;配置IP地址&#xff1a; AR1: [AR1]int g0/0/0 [AR1-GigabitEthernet0/0/0]ip add 12.1.1.1 24 [AR1-GigabitEthernet0/0/0]int l0 [AR1-LoopBack0]ip add 172.16.0.1 32 [AR1-LoopBack0]int l1 […

vscode怎么设置背景图片?

vscode背景图片是可以自己设置的&#xff0c;软件安装后默认背景的颜色是黑色的&#xff0c;这是默认的设计&#xff0c;如果要修改背景为指定的图片&#xff0c;那么我们需要安装插件&#xff0c;然后再通过代码来设置背景图片的样式&#xff0c;下面我们就来看看详细的教程。…

【一步一步了解Java系列】:了解Java与C语言的运算符的“大同小异”

看到这句话的时候证明&#xff1a;此刻你我都在努力~ 加油陌生人~ 个人主页&#xff1a; Gu Gu Study ​​ 专栏&#xff1a;一步一步了解Java 喜欢的一句话&#xff1a; 常常会回顾努力的自己&#xff0c;所以要为自己的努…

VScode 修改 Markdown Preview Enhanced 主题与字体

VScode 修改 Markdown Preview Enhanced 主题与字体 1. 修改前后效果对比2. 修改主题2.1 更改默认主题2.2 修改背景色 3. 修改字体 VS Code基础入门使用可查看&#xff1a; VS Code 基础入门使用&#xff08;配置&#xff09;教程 其他Vs Code 配置可关注查看&#xff1a; Vs C…

使用train.py----yolov7

准备工作 在训练之前&#xff0c;数据集的工作和配置环境的工作要做好 数据集&#xff1a;看这里划分数据集&#xff0c;训练自己的数据集。_划分数据集后如何训练-CSDN博客 划分数据集2&#xff0c;详细说明-CSDN博客 配置环境看这里 从0开始配置环境-yolov7_gpu0是inter g…

使用python撰写计算书

使用python撰写电路计算书 1、效果预览 下图是效果预览&#xff0c;可以写公式&#xff0c;画图&#xff0c;带单位计算 我们通常写计算书&#xff0c;使用mathcad或者maple等商业软件&#xff0c;但是个人使用可能还行&#xff0c;在很多公司是不允许使用破解版的。这时…

Spring Boot 自动装配

本篇主要介绍Spring Boot 自动装配的相关内容。 目录 一、什么是自动装配 二、Bean的扫描方式 ComponentScan Import ImportSelector接口 三、Spring Boot自动装配原理 一、什么是自动装配 在我们在创建Spring Boot项目时往往会根据项目需求&#xff0c;引入很多第三方…