Linux——文件与磁盘
1. 磁盘结构
磁盘在我们的计算机中有着重要的地位,当文件没有被打开时其数据就存储在磁盘上,要了解磁盘的工作原理先要了解磁盘的结构。
1.1 磁盘的物理结构
以传统的存储设备机械硬盘为例,它通过磁性盘片和磁头来读写数据。磁盘内部有多个旋转的磁盘(盘片),磁头通过移动到不同的位置来读写数据。
机械硬盘的结构主要有:
盘片(Platters):硬盘的存储介质,通常由铝或玻璃制成,表面覆盖有磁性涂层。数据以磁化的形式存储在盘片的表面。每个盘片都有两个面可以用来存储数据。
磁头(Read/Write Heads):磁头用于读取和写入数据。每个盘片面上都有一个磁头,通过磁头的电磁作用来改变磁化状态,进而写入数据;或者通过读取磁化状态来获取数据。
主轴电机(Spindle Motor):驱动盘片旋转的电机,通常有几千转每分钟(RPM)的速度。常见的转速有5400 RPM和7200 RPM,较高的转速意味着数据读取和写入速度更快。
磁头臂(Actuator Arm):连接磁头和驱动电机的部分,负责移动磁头,使其能够定位到盘片的不同区域。
控制器(Controller):硬盘的“脑袋”,负责控制硬盘的读写操作、定位磁头、管理数据的存取等。
机械硬盘的成本相对较低,存储容量大。但是速度较慢,尤其是随机访问速度,因为磁头需要移动到正确的位置读取数据。
1.2 磁盘的存储结构
机械硬盘(HDD)采用的是一种基于磁性存储的结构,数据被存储在盘片上,并按照一定的方式进行组织,以便磁头能够快速且高效地读取或写入数据。
磁道(Tracks):磁道是硬盘上盘片表面上一个圆形的存储区域。每个盘片上都有多个磁道,磁道的排列是同心圆形状,磁道的数量通常取决于盘片的密度和大小。硬盘上的每个磁道可以看作是一个线性存储区域,数据按照顺序存储在这些磁道上。
扇区(Sectors):扇区是硬盘上磁道的最小存储单元,硬盘通过扇区来管理数据的存储和读取。每个扇区通常存储512字节的数据。磁盘将数据按照扇区来组织和存储,因此每个扇区都有一个编号。当硬盘控制器发出读写请求时,它会指定具体的扇区编号,以确定需要访问的物理位置。当磁头在磁道上移动时,它会按照一定的顺序访问磁道上的每个扇区。读取或写入操作的最小单位通常是扇区。扇区的编号是从1开始的。
磁道相对于磁盘面是同心圆环的分布方式,扇区则是同心圆环上的一段扇环。对于老式磁盘而言,采取的是非分区记录方式,即不同磁道的扇区数目相同。此时所有的扇环圆心角大小相等,又因为扇区存储的都是512字节的数据,所以由内向外存储密度逐渐减小。新式的磁盘采取的则是分区记录方式,不同磁道扇区数不相同。
柱面(Cylinders):柱面是硬盘上由多个盘片的相同磁道所组成的一个三维概念。硬盘有多个盘片,每个盘片上都有若干个磁道。在硬盘工作时,磁头会在同一时间访问多个盘片上的相同磁道,这些磁道在物理上是垂直对齐的。
1.2.1 扇区的定位——CHS寻址
磁盘读写就是依靠这些结构完成的。
磁盘的盘片是始终处于高速旋转(固定速率)中的,磁盘有多个盘片,而盘片的两个面都是可以读写的。读写工作由磁头来完成,每一个磁盘面都有一个自己的磁头,所有的磁头被机械臂连接在一起,他们是同时做同样的运动的。
当需要对某一个位置(扇区)进行读写操作时,硬盘控制器会控制磁头移动到对应的磁道,然后等待盘片旋转到指定扇区位置后,对应盘面的磁头就开始读写数据。
定位扇区实质就是定位圆柱体内一个点,类比柱坐标系需要三维数据:半径、高、角度,通过上面的磁盘结构与读写过程,定位一个扇区就需要柱面号(半径)、磁头号(高)、扇区号(角度)。
于是我们可以计算出磁盘容量=磁头数×柱面数×每道扇区数×扇区字节大小。
1.3 磁盘的逻辑结构
1.3.1 逻辑地址块(LBA)
对于一个磁盘,我们使用的CHS寻址方法实际上是一种三维寻址方法,三个维度分别是面号、磁头号、扇区号,于是这实际上就是一个三维数组。而我们知道在C语言中,几维数组都好,它们实质上在物理空间中是连续存储的,相当于是一个一维数组一样。
对于磁盘而言也是一样,扇区是基本的单位,多个扇区在一起就组合成了磁道,所有盘面的同位置磁道共同组合成为一个柱面,多个柱面就构成了整个磁盘。
于是对于这样的一个逻辑结构的磁盘,我们抽象成为了一个数组结构,就可以通过线性地址的方法来定位任何一个扇区了。
1.3.2 CHS与LBA的转换
需要注意的是,在CHS下柱面号、磁头号是从0开始的,扇区号从1开始。
CHS→LBA:
LBA=柱面号×单个柱面扇区数+磁头号×单个磁道扇区数+扇区号-1
LBA→CHS:
柱面号=LBA/单个柱面扇区数
磁头号=(LBA%单个柱面扇区数)/单个磁道扇区数
扇区号=LBA%单个磁道扇区数+1
2. 文件系统
2.1 磁盘分区
2.1.1 物理块
磁盘以扇区作为基本的存储单位,当操作系统和磁盘IO交互时,由于磁盘扇区大小为512字节,单次交互数据量少,所以会一次性交互1KB、2KB、4KB、8KB等大小的数据,而其中以4KB最为普遍,因此抽象出物理块的概念,将4KB大小作为一个物理块的大小。于是一个块中就包含了8个扇区,也就是8个LBA地址。在与操作系统交互时,基本存储单位就是块,此时磁盘也可以看作是以块为单位的一维数组。
因为我们知道一个块对应着8个LBA地址,于是就二者之间的转换就非常容易了。
2.1.2 分区
磁盘分区在我们使用电脑的过程中会有很多使用经验。磁盘分区是对硬盘物理存储空间进行逻辑划分的过程,通过分区,硬盘可以被划分为多个独立的区域,每个区域可以被操作系统视为一个独立的存储设备,即不同分区允许使用不同的文件系统。
可以看到我的机器具有三个分区。
对于一个磁盘而言,我们在将其看作一个以块为单位的一维数组后,对其分区相当于就是对这个一维数组进行分割,划分成为几个区间。于是要指明分区的具体大小与位置,只需要给出各个分区的起始和终止块号即可。
2.2 Ext2文件系统
2.2.1 分组
硬盘(Disk)被分为了多个分区(Partition),对于任意一个磁盘分区,它的开头会存在一个启动块(Boot Sector),这个启动块的⼤⼩是确定的1KB,⽤来存储磁盘分区信息和启动信息,任何⽂件系统都不能修改启动块。在其之后才是真正的分区的文件系统。
为了更好地管理分区的内容,Ext2文件系统对一个分区的空间继续进行划分,这样就划分出了很多的块组(Block Group)。
得到的分组都具有同样的结构,包括 Super Block、Group Descriptor Table、Block Bitmap、inode Bitmap、inode Table、Data Blocks。
2.2.1.1 inode
文件是由属性和内容两部分组成的,因此属性也需要存储在磁盘中。为了将文件属性组织起来,Ext2文件系统使用inode的结构体对其属性进行描述,记录了文件的权限、属主、时间、大小等信息以及文件的i结点编号。通过ls的-i选项我们就可以看到文件的inode值,他们的值是不重复的。
每一个文件都有着自己的inode,inode结构体的大小是固定的,一般而言大小为128字节或256字节。
2.2.1.1 超级块(Super Block)
超级块中存放的是文件系统的结构信息,描述了所在分区的文件系统结构,包括分区的inode和block的总量,inode和block的剩余数量,分区最近读写时间等等。
作为存储分区信息的块而言,本来应该是属于分区结构一层的,为什么会将其下放到块组结构中呢。这是因为超级块因为记录着分区信息,所以十分重要,一旦出现错误就会使得整个分区文件系统崩溃。将其放在组的层级之中,就可以创建多个备份来保证文件系统的健壮性。
每一个分区都有多个组,其中第一个组一定会有超级块的备份,其余的个别组会具有超级块的备份,以此来保证当Super Block的信息被破坏后还有备用的信息。
2.2.1.2 块组描述符表(GDT/Group Descriptor Table)
GDT中存放的是块组的属性信息,在每一个块组中都有一个,描述了当前组的结构信息。包括inode Table开始的块号、Data Blocks开始的块号、inode和Data Block剩余的数量等。
在此做一下小结和区别,我们当前的层次一共有三层。
①第一层是磁盘被分为多个分区。每个分区从何处开始,到何处结束的信息由分区表记录,而这个分区表位于磁盘的主引导记录(MBR,Master Boot Record),通常在磁盘第一个扇区。——磁盘内的分区信息→主引导记录
②第二层是分区被分为多个块组。每个块组的大小、起始结束块号等块组信息由超级块(Super Block)记录。超级表位于分区下第一个组块中和其他某几个组块中。——分区内的块组信息→超级块
③第三层是组块被划分为不同的区域。由块组描述符表(GDT)来记录块组内Block Bitmap、inode Bitmap、inode Table、Data Blocks的起始结束块号与块总量和剩余量等信息。——块组内的块结构信息→GDT
2.2.1.3 块位图(Block Bitmap)
块位图以位图的形式管理数据块的占用情况,每个块对应一个bit位。
2.2.1.4 inode位图(inode Bitmap)
inode位图以位图的形式管理i节点表的占用情况,每个inode值对应一个bit位。
2.2.1.5 i节点表(inode Table)
i节点表中存储的就是当前组内所有的文件属性信息,值得注意的是文件名并是inode的字段。inode的结点编号分区之间相互隔离,即同一分区内inode编号是唯一的,不同分区下inode编号可以相同。
在inode结构体内存在着一个数组,用于指向文件对应的文件内容存储的块。出于inode结构体大小的128字节限制,这个数组一般有15个元素。
前12个属于直接块指针,即直接指向文件对应的数据块。这种方式很快,但是因为一个元素只能指向数据块,所以12个指针一共可以容纳12*4KB=48KB大小的文件。
第13个指针是一级间接块索引表指针,即先指向一个块,这个块中存储着文件的数据块的直接块指针。于是可容纳文件的大小就增加了4KB(索引表大小--一个块)/4B(一个块号占的字节数)*4KB(一个数据块的大小)=4MB。
第14个指针是二级间接块索引表指针,即指向的一个块是索引,这个块再指向的4KB/4B=1K个块也是索引,所以最后可容纳文件的大小增加了1K*4MB=4GB。
第15个指针是三级间接块索引表指针,即指向的一个块是索引,这个块再指向的4KB/4B=1K个块也是索引,这个二级索引指向的块也是索引,所以最后可容纳文件的大小增加了1K*1K*4MB=4TB。
通过这样间接块索引的方法即可让仅仅只有128KB的文件能够管理GB级别的文件。当文件较小时,只需要使用前12个指针,速度最快,随着文件的大小增加,再启用后续的索引块。
3.3.1.6 数据块(Data Block)
在数据块中存放的就是各个文件的文件内容了,可以通过文件i结点表映射找到数据块中需要的内容。实际在分组中占据空间最大空间的是Data Blocks。
2.2.2 格式化
文件系统格式化是在磁盘分区之后对分区进行初始化的一系列操作,目的是在一个已分区的存储介质上建立一个结构化的方式来存储和管理数据,方便操作系统进行读写和管理,通俗来说格式化相当于将搭建整个文件系统的框架好。
格式化一个分区,对于每一个块组,首先会创建超级块,记录了分区内的块组信息;然后创建GDT,管理块组结构;然后将两个位图初始化为全0;然后创建inode表与数据块区域。于是格式化后,分区有几个块组、每个块组大小、分配的inode数量等结构信息都已经被决定。
由于一个块组内inode的数量和数据块的数量已经在格式化时被决定,所以会出现inode和数据块数量不匹配的情况。当文件系统中有大量小文件,每个文件都需要一个 inode,但它们使用的数据块很少时,inode 耗尽而数据块未耗尽;当文件系统中有少量大文件,每个文件占用大量数据块,但只需要一个 inode时,就会出现inode 未耗尽而数据块耗尽。
2.2.3 文件操作(增删查改)
基于这样的这样的文件系统,我们通过文件操作来系统地理解其工作流程。
已知创建了一个log.txt文件,其i结点值为114514。在创建时,首先操作系统会在确定新创建的文件属于哪一个组,然后查询inode位图和块位图找到一个空闲inode与数据块分配给文件,然后写入属性和内容。最后这个申请到的inode就是i结点位图空闲的下标+分组起始inode值。
对于同一个log.txt文件进行查找,实际上是通过i结点值来查询的。通过inode对比组inode区间找到对应的组,然后减去start inode即可找到文件的inode结点,通过结构体即可访问到内容。
删除则是在查找的基础上将位图对应的位置置为空闲。修改则是在查找的基础上对文件的i结点内容或数据块进行读入内存,然后修改再写回磁盘。
2.2.4 目录文件
对于目录文件,在文件系统看来也和普通文件一样,有着自己的inode结点,也有着自己的数据块。只是目录文件的数据块(内容)是目录内的文件名和inode值的映射关系。
于是我们理解为什么说访问文件使用的是inode值而非文件名,因为在使用文件名访问文件时,首先打开文件所在目录的,从其中获取文件名对应的inode值,从而才能查找到文件并打开。于是目录的r权限会限制能否获取目录内容——目录下文件的文件名与inode值映射,从而限制能否访问目录下的文件;w权限会限制能否修改目录内容,从而限制能否创建、修改、删除目录下的文件。
2.2.4.1 路径解析
目录也是文件,访问当前目录也需要他的inode值,因此需要打开它所在的目录内容来进行映射,而访问上级目录又需要上上级目录的帮助。于是不论打开什么文件,最后一定会递归到要打开根目录来进行文件名与inode映射,于是操作系统将根目录的固定加载到了内存中,以便从根目录开始解析。
于是我们知道,打开路径为 "/home/xlz/tmp/log.txt" 这样的一个文件,首先会从根目录开始,打开根目录,将根目录内容中的home文件名映射得到一个inode,找到这个inode的inode结点从而找到数据块,取得其内容后就可继续拿出其中xlz文件名映射的inode。同样打开了xlz的内容后,映射得到tmp的inode,再由tmp的内容映射得到log.txt的inode,从而找到了这个文件。
因此打开文件需要拿到其路径,而进程打开文件,绝对路径不必多说。相对路径由于进程CWD的存在,取得文件的路径也很容易。接着层层解析自然就可以打开对应的文件。
2.2.4.2 路径缓存
如果对于所有文件的访问都要从根目录解析一遍,那效率未免也太低了,于是解决这种问题最经典的方案就是缓存技术。而路径文件这种结构是一种天生的树形结构,所以缓存结构采用树状结构自然是最优选择。
在Linux中,存在名为dentry的结构体,它就是文件作为树状缓存结构的结点,其中包含了文件的inode、父子结点、LRU队列等信息。
所有的文件都会存在自己的dentry结构体,树的结点从根目录开始,当需要打开某个文件时,就会根据路径提供的顺序查找这棵树,查找到了就可以返回文件inode从而得到文件内容。如果没有找到,则会逐步进行路径解析,并在树上增加dentry结点,缓存新的路径。
需要注意的是这棵缓存树是内核数据结构,仅仅存在于内存当中,来方便内存进行文件访问。整棵树形节点也被LRU结构管理,淘汰last recently used的结点。
2.3 分区挂载
①制作磁盘块
dd if=/dev/zero of=./disk.img bs=1M count=5
dd——dd是一个 Unix/Linux 系统上的工具,用于低级数据拷贝和转换,能够在设备之间或文件之间以块为单位复制数据,并支持数据的格式化、转换等操作。它常用于创建磁盘镜像、写入磁盘、备份等任务。
if=/dev/zero——if 表示输入文件(Input File)。/dev/zero 是一个特殊的设备文件,表示无限的空数据流(每个字节为 0)。这里使用 /dev/zero 作为数据源,也就是生成连续的空字节。
of=./disk.img——of 表示输出文件(Output File)。./disk.img 是输出文件的路径,即在当前目录下创建一个名为 disk.img 的文件。
bs=1M——bs 表示块大小(Block Size)。1M 表示每个块的大小为 1 MB(1,048,576 字节)。这是拷贝的基本单位。
count=5——count 指定拷贝多少个块。5 表示拷贝 5 个块。
dd是在按块进行数据拷贝。在这条指令后dd 会从 /dev/zero 中读取 5 个块的数据(每块大小为 1 MB),然后将这些数据写入 disk.img 文件,最终在当前目录下生成一个大小为 5 MB 的文件 disk.img。
②格式化文件系统
mkfs.ext4 disk.img
mkfs.ext4——mkfs 是 "make filesystem" 的缩写,用来创建文件系统。ext4 是常用的 Linux 文件系统类型。
disk.img——disk.img 是创建 ext4 文件系统的目标文件。它可以是一个文件,表示一个虚拟磁盘映像。
mkfs将文件格式化为文件系统。在这步之后,该文件将会被格式化为 ext4 文件系统的结构,并可以像一个实际的磁盘分区一样使用。
③查看分区
df -h
df—— "disk free"(磁盘空间)的缩写。它用于显示文件系统的磁盘空间使用情况。
-h选项——表示 human-readable(易读的格式)。它会以适合人类阅读的格式显示磁盘空间,通常以 KB、MB、GB 等单位而不是字节(B)显示。
④分区挂载
sudo mount -t ext4 ./disk.img /mnt/test/
将磁盘映像文件 disk.img 挂载到 Linux 系统中的一个目录 /mnt/test/,并指定该磁盘映像使用 ext4 文件系统。
在类 Unix 操作系统(如 Linux)中,挂载(mount)是将一个存储设备或文件系统(如磁盘、分区、CD-ROM、USB 设备等)与系统的目录结构连接起来的过程。挂载之后,操作系统就能把存储设备上的文件和目录呈现给用户,并允许用户像操作本地文件一样操作它们。挂载的目的是让操作系统能够访问存储设备上的数据,把它“挂”到文件系统的树状结构中,使用户可以通过目录路径访问这些数据。
对于真正的存储设备而言,挂载就是将其接入系统,使得操作系统可以访问存储设备的数据从而让用户也可以进行访问。
而对于我们这里的磁盘映像文件,也就是虚拟磁盘,有一些容易混淆的地方。可以类比,磁盘映像文件和u盘一样,一旦生成大小就是固定的,其中的空间只有使用和未使用两种情况。通过dd if=/dev/zero of=./disk.img bs=1M count=5 生成的磁盘映像文件实际上是将实际的磁盘中拿出5M的空间分给了磁盘映像文件,而磁盘映像文件作为一个磁盘其大小就是5M,这时把它挂载后进行文件创建等操作,在真实磁盘视角是对这个5M映像文件的内容做修改,而在虚拟磁盘的视角是在自己5M大小的磁盘空间内创建文件。简言之就是拿出了5M的空间给虚拟磁盘,而这个虚拟磁盘在实际磁盘中的表现就是映像文件。
挂载点则是一个特定的目录,操作系统通过该目录将文件系统中的文件和目录呈现给用户和应用程序。例如,/(根目录)是文件系统的起始挂载点,其他磁盘分区、文件系统或设备可以挂载到 /data、/mnt、/home 等目录上。
其中/dev/loop0 是 Linux 系统中的一个环回设备(loop device)。环回设备允许你将一个普通的文件(如磁盘映像文件)映射到一个虚拟的块设备,从而使操作系统能够像处理物理磁盘一样处理这个文件。
因为磁盘映像文件被看作了环回设备loop0,所以一个文件构成的虚拟磁盘也可以对文件进行挂载、读取、写入、分区等操作,就好像它是一个物理设备。通常情况下,环回设备用于挂载磁盘映像文件,或者以类似磁盘的方式访问存储在普通文件中的数据。
⑤分区卸载
sudo umount /mnt/test
用于卸载已挂载的文件系统,将之前挂载到 /mnt/test 目录的文件系统卸载掉。
3. 软硬链接
在Linux中,**软链接**(Symbolic Link)和**硬链接**(Hard Link)都是用来为文件创建别名的方式,但它们在实现和使用上有所不同。
3.1 软链接(Symbolic Link 或 Symlink)
软链接,也叫符号链接,是一个指向目标文件路径的特殊文件,可以类比为Windows中的快捷方式。软链接文件中保存的是目标文件的路径,而不是目标文件的内容,因此它是一个独立的文件,拥有自己独立的inode。
创建方法【后者链接前者】
ln -s <原文件或目录> <软链接>
注意点
①通过软链接查找来打开目标文件的过程包括:通过软链接文件的inode找到其物理块,其中存储着目标文件的路径信息;内存得到这个路径信息后,进行路径解析,一步步找到目标文件并打开。因此软链接不局限于当前文件系统,而可以跨文件系统。
②软链接不仅可以指向文件,还可以指向目录。
③软连接文件文件在Linux中是独立的,有一个自己唯一的inode,包含文件的元数据(如文件大小、权限等)。
④删除软链接不会影响原文件。如果目标文件被删除,软链接就会变成悬挂链接(即无法访问的链接)。
3.2 硬链接(Hard Link)
硬链接是文件系统中对文件的直接引用。硬链接创建后,多个文件名指向相同的磁盘块(即相同的数据)。每个硬链接都有相同的inode编号,它们指向相同的数据块,因此删除其中一个硬链接并不会影响其他硬链接,只有当所有硬链接都被删除时,磁盘上的数据才会被回收。
创建方法
ln <原文件> <硬链接>
因为通过文件名来打开文件,实际上是读取了所在目录的文件内容,将文件名映射为了inode值,所以硬链接的本质就是创建了一个映射到同一个inode的新文件名,此时一个inode有多个文件名映射了。
通过观察发现软链接的文件间inode不同,而硬链接的文件具有相同的inode。
另外可以发现在我们熟知的文件信息中有一个数字(红色标出),这个实际上是硬链接数(inode的引用计数),表示当前文件有多少个硬链接(inode有多少个映射关系)。如我们刚才创建的text.txt的硬链接,二者的引用计数都是2。
又可以发现dir1的引用计数也是2,这是因为目录文件中默认包含.和..两个目录,这个其中.就是指向dir1自身的一个硬链接。
我们发现当在dir1中再创建一个目录dir2,会发现引用计数又变为了3,这是因为dir2中的..是dir1目录的硬链接。所以目录文件固有的.和..实际上就是硬链接。
可以看到根目录有17个硬链接,所以我们知道根目录下有16个文件(17-1个根目录下的.目录文件),其余的目录都会贡献一个..硬链接。值得一提的是根目录的..也是根目录自身,但是操作系统为了使所有文件保持一致就没有将..加入引用计数。
注意点
①通过硬链接查找来打开目标文件和正常文件一致,只需要根据自己的文件名映射到inode访问数据块即可。所以硬链接不能跨文件系统,因为硬链接文件inode一致,不同文件系统下的inode各自为一套。
②无法创建目录的硬链接,这是出于避免循环结构的考虑。但是.和..就是目录的硬链接,这是操作系统做的例外操作,用户是不可以创建目录的硬链接的。
③删除一个硬链接不会影响文件内容,只有所有链接删除时,文件才会被删除。于是我们可以在剪切大型文件的时候,直接使用硬链接的方式,避免拷贝开销。同时也可以采取硬链接的方式来备份文件。
相关文章:
Linux——文件与磁盘
1. 磁盘结构 磁盘在我们的计算机中有着重要的地位,当文件没有被打开时其数据就存储在磁盘上,要了解磁盘的工作原理先要了解磁盘的结构。 1.1 磁盘的物理结构 以传统的存储设备机械硬盘为例,它通过磁性盘片和磁头来读写数据。磁盘内部有多个旋…...
Maven jar 包下载失败问题处理
Maven jar 包下载失败问题处理 1.配置好国内的Maven源2.重新下载3. 其他问题 1.配置好国内的Maven源 打开⾃⼰的 Idea 检测 Maven 的配置是否正确,正确的配置如下图所示: 检查项⼀共有两个: 确认右边的两个勾已经选中,如果没有请…...
Qt中的UIC、MOC、RCC宏定义说明
在Qt6新建工程的时候,CMakeLists.txt中会默认带有UIC,MOC,RCC的3个宏定义。 set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) uic(User Interface Compiler),用户界面编译器,将根据.ui文件生成相…...
SQLite Update 语句详解
SQLite Update 语句详解 SQLite 是一款轻量级的数据库管理系统,以其简单、易用和高效的特点在全球范围内得到了广泛的应用。在 SQLite 中,UPDATE 语句是用于修改数据库表中记录的常用命令。本文将详细解析 SQLite 的 UPDATE 语句,包括其语法…...
理解PLT表和GOT表
1 简介 现代操作系统都是通过库来进行代码复用,降低开发成本提升系统整体效率。而库主要分为两种,一种是静态库,比如windows的.lib文件,macos的.a,linux的.a,另一种是动态库,比如windows的dll文…...
InfluxDB 2.0 到 3.0 技术架构演进与性能分析
架构演进 关键技术变化:InfluxDB 3.0 相比 2.0 在架构上进行了重大的技术升级。首先,核心代码由 Go 语言重写为 Rust,以利用 Rust 更高的性能和内存安全特性,从而显著提升数据库的性能、可靠性和安全性。其次,引入列式…...
介绍一下Mybatis的底层原理(包括一二级缓存)
表面上我们的就是Sql语句和我们的java对象进行映射,然后Mapper代理然后调用方法来操作数据库 底层的话我们就涉及到Sqlsession和Configuration 首先说一下SqlSession, 它可以被视为与数据库交互的一个会话,用于执行 SQL 语句(Ex…...
docker gitlab arm64 版本安装部署
前言: 使用RK3588 部署gitlab 平台作为个人或小型团队办公代码版本使用 1. docker 安装 sudo apt install docker* 2. 获取arm版本的gitlab GitHub - zengxs/gitlab-arm64: GitLab docker image (CE & EE) for arm64 git clone https://github.com/zengxs…...
7、怎么定义一个简单的自动化测试框架?
定义一个简单的自动化测试框架可以从需求理解、框架设计、核心模块实现、测试用例编写和集成执行等方面入手,以下为你详细介绍: 1. 明确框架需求和范围 确定测试类型:明确框架要支持的测试类型,如单元测试、接口测试、UI 测试等…...
linux组管理
创建组:groupadd (创建组命令的详细使用:如何创建组-CSDN博客) 修改组:groupmod (修改组命令的详细使用:如何修改组-CSDN博客) 组配置文件: /etc/group...
【MySQL】常用语句
目录 1. 数据库操作2. 表操作3. 数据操作(CRUD)4. 高级查询5. 索引管理6. 用户与权限7. 数据导入导出8. 事务控制9. 其他实用语句注意事项 如果这篇文章对你有所帮助,渴望获得你的一个点赞! 1. 数据库操作 创建数据库 CREATE DATA…...
二维数组 C++ 蓝桥杯
1.稀疏矩阵 #include<iostream> using namespace std;const int N 1e4 10; int a[N][N];int main() {int n, m; cin >> n >> m;for (int i 1; i < n; i) {for (int j 1; j < m; j) {cin >> a[i][j];}}for (int j m; j > 1; j--) {for (i…...
SAP HCM 回溯分析
最近总有人问回溯问题,今天把12年总结的笔记在这共享下: 12年开这个图的时候总是不明白是什么原理,教程看N次,网上资料找一大堆,就是不明白原理,后来为搞明白逻辑,按照教材的数据一样做…...
MySQl的日期时间加
MySQL日期相关_mysql 日期加减-CSDN博客MySQL日期相关_mysql 日期加减-CSDN博客 raise notice 查询目标 site:% model:% date:% target:%,t_shipment_date.site,t_shipment_date.model,t_shipment_date.plant_date,v_date_shipment_qty_target;...
前部分知识复习03
一、光照模型 经验型: 1.Lambert光照模型 2.Phong光照模型 3.Blinn-Phong光照模型 物理型: 4.PBR光照模型 二、渲染路径 渲染路径:是为进行光照计算而设置的渲染方式 前向渲染路径顶点照明渲染路径延迟渲染路径 顶点照明渲染路径中的灯光…...
Windows图形界面(GUI)-QT-C/C++ - QT MDI Area
公开视频 -> 链接点击跳转公开课程博客首页 -> 链接点击跳转博客主页 目录 一、概述 二、使用场景 1. 多文档编辑器 2. 多窗口应用程序 3. 多视图应用程序 三、常见样式 1. 子窗口管理 2. 布局管理 四、属性设置 1. 添加子窗口 2. 移除子窗口 3. 设置…...
基于微信小程序的私家车位共享系统设计与实现(LW+源码+讲解)
专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…...
用deepseek制作我的第一个长视频---使用AI解决尝试新领域没有经验拖延的问题!
(由于技术原因,联网搜索暂不可用) 制作一个高质量的Vlog或生活记录长视频,即使零基础也能通过系统规划实现!以下是为你定制的「从零到成品」全流程指南,结合叙事逻辑、剪辑技巧和效率工具,帮你…...
零基础学习电磁兼容(EMC)06--时域和频域
大部分工程师很熟悉示波器,并使用它读取信号的频率和电压值,然而,在EMC领域,绝大多数的数据都是从频谱分析仪、测量接收机等基于频率测量的设备中读取的,因此,了解这些频率参数的含义以及与时域信号的关系,是非常重要的。 时域和频域的本质:傅里叶变换及其逆过程 如下…...
解决在使用自己的数据集在 Ultralytics 上运行 RT - DETR 模型时显存爆满的问题
在使用自己的数据集在 Ultralytics 上运行 RT - DETR 模型时,显存爆满是一个常见问题。以下是一系列可以采取的步骤和方法,帮助你解决这个问题,同时使用 Ultralytics 的官方源码。 1. 环境准备 确保你已经安装了 Ultralytics 库,…...
Android学习19 -- 手搓App
1 前言 之前工作中,很多时候要搞一个简单的app去验证底层功能,Android studio又过于重型,之前用gradle,被版本匹配和下载外网包折腾的堪称噩梦。所以搞app都只有找应用的同事帮忙。一直想知道一些简单的app怎么能手搓一下&#x…...
鼠标拖尾特效
文章目录 鼠标拖尾特效一、引言二、实现原理1、监听鼠标移动事件2、生成拖尾元素3、控制元素生命周期 三、代码实现四、使用示例五、总结 鼠标拖尾特效 一、引言 鼠标拖尾特效是一种非常酷炫的前端交互效果,能够为网页增添独特的视觉体验。它通常通过JavaScript和C…...
【CSS】什么是响应式设计?响应式设计的基本原理,怎么做
在当今多设备、多屏幕尺寸的时代,网页设计面临着前所未有的挑战。传统的固定布局已无法满足用户在不同设备上浏览网页的需求,响应式设计(Responsive Web Design)应运而生,成为网页设计的趋势和标准。本文将深入探讨响应…...
单机性能调优中的程序优化
目录 一、系统框架的选择 二、程序优化 表单压缩 局部刷新 仅取所需 逻辑清晰 谨慎继承 程序算法优化 批处理 延迟加载 防止内存泄漏 减少大对象引用 防止争用死锁 存储过程 内存分配 并行 异步 缓存 单机优化顾名思义就是我们要在单机上对系统的性能进行调优…...
2.4学习总结
洛谷1305代码 #include<stdio.h> #include<stdlib.h> struct treenode {char val;struct treenode* left;struct treenode* right; }; struct treenode* createnode(char val) {struct treenode* node (struct treenode*)malloc(sizeof(struct treenode));node-&…...
小程序-视图与逻辑
前言 1. 声明式导航 open-type"switchTab"如果没有写这个,因为是tabBar所以写这个,就无法跳转。路径开始也必须为斜线 open-type"navigate"这个可以不写 现在开始实现后退的效果 现在我们就在list页面里面实现后退 2.编程式导航…...
突破封闭集限制:OvSGTR引领开放词汇场景图生成新纪元
场景图生成(Scene Graph Generation, SGG),这个领域,旨在通过解析图像来构建描述性的结构化图表,不仅能够识别图片中的物体,还能捕捉它们之间的相互关系。 这种能力对于诸如图像字幕、视觉问答以及图像生成…...
C语言基础之【程序流程结构】
C语言基础之【程序流程结构】 概述选择结构if语句if…else语句小练习:“三只小猪体重比较” if…else if…else语句小练习:“三只小猪体重比较” 三目运算符小练习:“三只小猪体重比较” switch语句小练习:**“成绩等级判断器”**…...
代码随想录35 动态规划
目录 leetcode 746.使用最小花费爬楼梯 leetcode 62.不同路径 思路: leetcode 63.不同路径|| leetcode 746.使用最小花费爬楼梯 给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选…...
【游戏设计原理】98 - 时间膨胀
从上文中,我们可以得到以下几个启示: 游戏设计的核心目标是让玩家感到“时间飞逝” 游戏的成功与否,往往取决于玩家的沉浸感。如果玩家能够完全投入游戏并感受到时间飞逝,说明游戏设计在玩法、挑战、叙事等方面达到了吸引人的平衡…...
51单片机 06 定时器
51 单片机的定时器属于单片机的内部资源,其电路的连接和运转均在单片机内部完成。 作用:1、用于计时;2、替代长时间的Delay,提高CPU 运行效率和处理速度。 定时器个数:3个(T0、T1、T2)…...
4 前端前置技术(中):node.js环境
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 前言...
【Leetcode刷题记录】1456. 定长子串中元音的最大数目---定长滑动窗口即解题思路总结
1456. 定长子串中元音的最大数目 给你字符串 s 和整数 k 。请返回字符串 s 中长度为 k 的单个子字符串中可能包含的最大元音字母数。 英文中的 元音字母 为(a, e, i, o, u)。 这道题的暴力求解的思路是通过遍历字符串 s 的每一个长度为 k 的子串…...
C++效率掌握之STL库:string函数全解
文章目录 1.为什么要学习string?什么是string?2.string类对象的常见构造3.string类对象的容量操作4.string类对象的迭代器5.string类对象的元素访问6.string类对象的元素修改7.string类对象的查找、提取、对比8.string类的非成员函数及npos希望读者们多多…...
Linux命令运行原理及权限管理
目录 1.引言 2.shell命令以及运行原理 3.Linux权限 3.1Linux下的用户类型 3.2Linux权限管理 3.2.1文件访问者的分类(人) 3.2.2文件类型和访问权限(事物属性) 3.2.3文件权限值的表示方法 3.2.4文件访问权限的相关设置方法…...
linux内核源代码中__init的作用?
在 Linux 内核源代码中,__init是一个特殊的宏,用于标记在内核初始化阶段使用的变量或函数。这个宏的作用是告诉内核编译器和链接器,被标记的变量或函数只在内核的初始化阶段使用,在系统启动完成后就不再需要了。因此,这…...
系统学习算法:专题九 穷举vs暴搜vs深搜vs回溯vs剪枝
其中标题的深搜,回溯,剪枝我们之前专题都已经有过学习和了解,这里多了两个穷举和暴搜,其实意思都差不多,穷举就是穷尽力气将所有情况都列举出来,暴搜就是暴力地去一个一个情况搜索,所以就是全部…...
《深度洞察ICA:人工智能信号处理降维的独特利器》
在人工智能技术飞速发展的今天,信号处理作为关键环节,面临着数据维度不断攀升的挑战。高维信号数据虽蕴含丰富信息,但也给处理和分析带来诸多难题,如计算资源消耗大、分析复杂度高、模型易过拟合等。独立成分分析(ICA&…...
FASTA 和 FASTQ 格式详解|SRA转fastq
FASTA 格式 FASTA 格式是一种用于存储序列信息的简单格式,广泛应用于核酸(DNA/RNA)和蛋白质序列的存储。它主要由两个部分组成: 描述行:以“>”符号开头,包含序列的描述信息,如名称、来源等…...
Docker使用指南(一)——镜像相关操作详解(实战案例教学,适合小白跟学)
目录 1.镜像名的组成 2.镜像操作相关命令 镜像常用命令总结: 1. docker images 2. docker rmi 3. docker pull 4. docker push 5. docker save 6. docker load 7. docker tag 8. docker build 9. docker history 10. docker inspect 11. docker prune…...
为何在Kubernetes容器中以root身份运行存在风险?
作者:马辛瓦西奥内克(Marcin Wasiucionek) 引言 在Kubernetes安全领域,一个常见的建议是让容器以非root用户身份运行。但是,在容器中以root身份运行,实际会带来哪些安全隐患呢?在Docker镜像和…...
【人工智能】多模态学习在Python中的应用:结合图像与文本数据的深度探索
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 多模态学习是人工智能领域的一个重要研究方向,旨在通过结合多种类型的数据(如图像、文本、音频等)来提高模型的性能。本文将深入探讨多模…...
以AI为翼:技术能力进阶的新路径
一、引言 1.1 研究背景与意义 在当今数字化时代,人工智能(AI)已成为推动各领域发展的核心驱动力。从最初简单的算法模型到如今复杂的深度学习架构,AI 技术取得了令人瞩目的进步。自 20 世纪 50 年代人工智能概念提出以来&#x…...
使用 HTTP::Server::Simple 实现轻量级 HTTP 服务器
在Perl中,HTTP::Server::Simple 模块提供了一种轻量级的方式来实现HTTP服务器。该模块简单易用,适合快速开发和测试HTTP服务。本文将详细介绍如何使用 HTTP::Server::Simple 模块创建和配置一个轻量级HTTP服务器。 安装 HTTP::Server::Simple 首先&…...
Jenkins 触发构建的几种常见方式
为了实现自动化构建,Jenkins 提供了多种触发构建的方式。这些触发方式可以根据开发团队的需求来选择,使得构建过程更加灵活和高效。 1. 手动触发构建 手动触发构建是最简单的一种方式,通常用于开发人员或管理员手动启动构建任务。 步骤: 登录 Jenkins 后,进入某个项目(…...
算法基础--二分查找
模板 #include <iostream> #include <cstring> #include <algorithm> #include <unordered_map> /** 二分查找(Binary Search)是一种高效的查找算法,其时间复杂度为 o(logn) */ using namespace std;const int N …...
Vue 3 30天精进之旅:Day 14 - 项目实践
在前面的学习中,我们已经掌握了Vue 3的基础知识,包括其核心概念、Vue Router、Vuex,以及异步操作等。今天是一个重要的里程碑:我们将把这些知识整合到一个实际的项目中。通过项目实践,你将能够深入理解所学知识&#x…...
【Java基础-42.4】Java中的包装类对象默认值:深入解析与注意事项
在Java编程中,包装类(Wrapper Classes)是将基本数据类型(如int、char等)封装为对象的类。它们提供了更多的功能和灵活性,例如允许基本数据类型参与面向对象的操作(如存储在集合中)。…...
Linux进程概念
目录 一.进程 二.进程状态 三.环境变量 四.程序地址空间 五.Linux2.6内核进程调度队列 一.进程 基本概念 课本概念:程序的一个执行实例,正在执行的程序等内核观点:担当分配系统资源(CPU时间,内存)的…...
Linux的简单使用和部署4asszaaa0
一.部署 1 环境搭建方式主要有四种: 1. 直接安装在物理机上.但是Linux桌面使用起来非常不友好.所以不建议.[不推荐]. 2. 使用虚拟机软件,将Linux搭建在虚拟机上.但是由于当前的虚拟机软件(如VMWare之类的)存在⼀些bug,会导致环境上出现各种莫名其妙的问题比较折腾.[非常不推荐…...