【Linux】解锁磁盘文件奥秘,高效数据管理的实战技巧

news2024/12/25 16:48:57

磁盘文件

  • 1. 引言
  • 2. 磁盘的机械构成
  • 3. 磁盘的物理存储
    • 3.1. CHS定位寻址法
  • 4. 磁盘的逻辑存储
    • 4.1. LBA地址
    • 4.2. inode
    • 4.3. 分区、分组
    • 4.4. Boot Block
    • 4.5. 块组 — Block group
      • 4.5.1. inode Table
      • 4.5.2. Data Blocks
      • 4.5.3. inode Bitmap
      • 4.5.4. Block Bitmap
      • 4.5.5. GDT
      • 4.5.6. Super Block
  • 5. 目录文件
    • 5.1. 文件名和inode
    • 5.2. 重谈文件的增删查改
    • 5.3. 路径
  • 6. 如何知道文件在哪个分区下
    • 6.1. 格式化
    • 6.2. 分区进行"挂载"

1. 引言

  1. 系统中是不是所有的文件都被打开?大部分文件都是没有被打开的。

  2. 未打开的文件存放在哪里?磁盘或固态硬盘(SSD)上,这些存储设备为文件提供了永久的存储空间。

  3. OS需要管理磁盘上的文件吗?需要,目的是为了让OS快速的定位一个文件。

对于磁盘文件,我们要研究的是如何更好、更合理地把所有文件规划到磁盘上,便于让我们快速定位到一个文件。

故事理解:菜鸟驿站,老板的核心工作是把驿站内所有快递归置好,让用户能够快速定位到自己的快递,还需要对驿站内快递总数、还能容纳的快递数量等工作进行了解。即:菜鸟驿站的老板要对全部快递进行管理,把快递放到特定的位置,对外输出一种能力,让用户快速找到快递的能力。

菜鸟驿站相当于磁盘、存放在驿站的快递相当于磁盘文件、拿走的快递相当于被打开的文件、老板相当于OS中的一个管理模块,称为文件系统,其核心工作是对磁盘文件进行管理,把众多的文件分门别类的放好,给用户提供一种服务,让用户能够快速定位一个文件,具体是通过路径来定位文件。

2. 磁盘的机械构成

  1. 磁盘有多个盘面、磁头,一个磁头一个盘面(1:1)。

盘面是可读可写的,数据以磁信号的形式存储在盘面上。而光盘是可读的。

  1. 盘面、磁头、磁道(柱面)、扇区都有唯一的编号。

  2. 盘面高速旋转,磁头来回摆动,就是磁头在盘片上进行寻址,向磁盘对应位置进行读写。

  3. 磁盘是个机械设备,不允许在开机的状态下,对它进行搬迁或产生强烈的震动,可能会导致磁头和盘面发生碰撞,从而造成数据损坏、物理损坏。

  4. 磁盘内部需要保持相对的无尘环境,可能会对磁盘造成损失。

💡Tips:扇区是磁盘IO的基本单位,每个扇区的大小是固定的,一般为512字节,但不一定是系统和磁盘的IO的基本单位。

3. 磁盘的物理存储

3.1. CHS定位寻址法

问:我该如何访问磁盘中的一个扇区?

确定目标扇区的地址 -> 选择磁头 -> 移动磁臂到指定的柱面 -> 旋转磁盘以定位到目标磁道 ->定位目标扇区 -> 执行读写操作。

目标扇区的地址:由柱面号、盘面号、扇区号组成。这三个参数共同决定了磁盘上唯一的一个扇区。

选择磁头:根据目标扇区的盘面号,确定使用磁头。 每个磁头负责读取或写入对应盘面上的数据。

移动磁臂到指定的柱面:根据目标盘面的柱面号来确定的,磁臂连接着所有磁头,通过移动磁臂,可以使所有磁头同时移动到指定的柱面。

  1. CHS(Cylinder-Head-Sector,柱面-磁头-扇区):通过磁盘的物理结构(来定位数据的三维寻址方式,它通过磁盘的柱面、磁头和扇区三个参数,来定位磁盘上的一个扇区。

  2. CHS优点:在早期硬盘容量较小的情况下,CHS寻址方式能够有效地定位和访问数据。

  3. CHS缺点:CHS寻址的容量是有限的。

4. 磁盘的逻辑存储

4.1. LBA地址

  1. LBA地址(Logical Block Addressing,逻辑块寻址):是将扇区编号转化为一维线性编号的逻辑寻址方式,即:它将磁盘上所有扇区编号为一个连续的线性序列。

LBA地址是一个线性地址(单一的数字),用于唯一标识磁盘上的一个扇区,LBA地址从0开始,依次递增。

  1. 工作原理:LBA编址方式将CHS这种三维寻址方式转变为一维的线性寻址;在访问磁盘时,系统或者磁盘控制器直接指定从硬盘上的特定扇区读取或写入LBA地址,硬盘控制器负责将LBA值转化为实际的物理CHS值。

  2. 优点:简化了数据访问的过程,提高了系统的效率,支持更大的容量;因为它采用线性寻址的方式,因此不受物理结构的限制。

💡Tips:LBA地址是扇区数组的下标;在使用LBA地址进行磁盘访问时,LBA地址指向磁盘的一个逻辑扇区,即:LBA地址实际上是直接对扇区的索引,不是对数据块的索引。

在这里插入图片描述

  1. 当将磁盘拉直,并视为线性结构时,实际上是将所有扇区重新排列成一个线性数组。

  2. 线性地址(LBA地址)->CHS,由磁盘自动完成,访问磁盘的任意一个扇区,只要知道这个扇区的线性地址,即:这个扇区在线性数组中的扇区编号,也就是数组下标。

问:OS与磁盘进行IO操作时,为什么使用4KB作为基本单位?

  • 减少IO操作的次数,提供性能和效率。

磁盘基本参数获取:在操作系统(OS)启动时,确实会进行一系列硬件检测,包括磁盘设备。这些检测会获取磁盘的基本参数,如扇区数量、磁道数量、每磁道的扇区数等。这些参数对于操作系统管理磁盘存储是至关重要的。

4.2. inode

Linux磁盘文件的特性:文件 = 内容 + 属性,内容大小可变,属性的类别相同,但类别的内容不同(sizeof(结构体)相等);内容和属性分开存储,内容存放在数据块(Data Blocks)中,属性存放在indeo表(indeo Tables)中。

  1. inode的定义:是文件系统中用于存储文件属性的数据结构;每个文件或目录在文件系统中都有唯一的inode与之对应,而每个inode内部都包含inode编号,但不包含文件名或目录名本身。

inode编号:是每个文件或目录的唯一标识符,用于在文件系统中唯一标识文件目录;文件系统中的各种操作需要通过inode编号来访问文件的属性和内容的位置。

ll -i

  • 功能:显示文件的inode编号。
  1. inode的作用:快速定位文件数据、实现文件的索引和访问。

快速定位文件数据:inode包含了指向文件数据块的指针,使得OS能够高效地读取或写入文件内容。

实现文件的索引和访问:通过inode,OS可以有效管理文件系统中大量的文件或目录,提供高效的存储和检索功能。

  1. inode特点:唯一性、不变性(时间戳除外)、不包含文件名或目录名的字符串。

  2. inode包含的信息(有限个重点属性):文件类型、权限、大小,数据块指针、硬链接个数、ACM时间、所有者和所属组。

人认识世界上的任何事物,都是通过事物的属性,且只能通过属性来认识。一件事物自身的属性是无限个,无法穷举出来,因为语言是有限的。即:人认识事物,只能通过有限个重点事物属性来认识的。

💡Tips:inode编号在整个分区内唯一,不是在分组内唯一!inode大小通常为128字节。

struct inode {
    mode_t i_mode;        /* 文件类型和权限 */
    uid_t i_uid;          /* 文件所有者 */
    gid_t i_gid;          /* 文件所属组 */
    ino_t i_ino;          /* inode编号 */
    unsigned long *i_block; /* 指向数据块的指针数组 */
    unsigned short i_nlink;  /* 硬链接个数 */  
    blkcnt_t i_size;      /* 文件大小 */
    time_t i_atime;       /* 最后访问时间 */
}

4.3. 分区、分组

4.4. Boot Block

Boot Block:只存在0号盘面、0号磁道、1号扇区中,即:分组0前,其作用是辅助开机,如:引导OS启动、检测文件系统状态、加载其他引导程序等。

4.5. 块组 — Block group

块组:ext2文件系统,会根据分区的大小划分为数个Block group,每个Block group都有着相同的结构组成,每个块组都包含一个inode表、数据块、inode位图、块位图等。

4.5.1. inode Table

inode Table:是块组中的一个数据结构,用于存储文件系统中的文件或目录的属性,每个inode表包含一定数量的inode结构体。

4.5.2. Data Blocks

  1. Data Blocks:是磁盘上的连续空间,用于存储文件系统中的文件或目录的内容;它是由多个连续的数据块组成的集合,这些数据块在物理上可能并不连续,在逻辑上是连续的,因为它们被组成在一个块组上。

  2. 在ext系列的文件系统中,文件的数据通常用一系列数据块来存储,而这些数据块的组织方式可以通过一级索引、二级索引、三级索引等多种方式进行管理,以便可以存储更大内容的文件。

一级索引:下标为[0, 11],通过一个索引块来存储数据块的编号。存储了12个数据块编号。

二级索引:下标为[12,13],通过一个索引块来存储另一个索引块的编号,后者在存储数据块的编号。存储了2*(4*1024/4)=2048个数据块编号。

三级索引:下标为[14],通过一个索引块来存储另一个索引块的编号,后者再存储第三个索引块的编号,最终第三个索引块存储数据块的编号。存储了110241024=1,048,576个数据块编号。

思想总结:在ext系列的文件系统中,通过编号或者指针找到真实存储数据的数据块;在多级索引下,先找到索引块,然后通过最后一次的索引指针或编号找到实际的数据块,即:最后一次索引才是真正存储文件的内容。

struct inode
{
    //如果block数组直接存储数据块的编号(一级索引),则可存储的文件内容大小为4KB*15 = 60KB,而文件内容大小是可变的
    int block[15];  
}

4.5.3. inode Bitmap

inode位图:用来记录块组中的inode(inode Table)是否被分配。

位图的位置:第几个inode,每个比特位,对应一个inode; 位图的内容:对应的inode是否被分配给一个文件或目录;如果该位为1,则表示对应的inode已经分配、如果该位为0,则表示对应的inode当前空闲,可用于分配给新的文件或目录。

4.5.4. Block Bitmap

块位图:用来记录块组中的数据块(Data Blocks)是否被占用。

位图的位置:第几个数据块,每个比特位,对应一个数据块;

位图的内容:对应的数据块是否被占用了;如果该位为1,则表示对应的数据块已经被占用、如果该位为0,则表示对应的数据块未被占用。

inode Bitmap、Block Bitmap:不属于文件本身的直接内容,而是文件系统为了管理对应的文件,而设置的额外管理字段。

删除一个文件,不用把文件本身的内容和属性删除,而是把位图内容由1只为0,表明这个文件已失效,可以被覆盖。

4.5.5. GDT

块组描述符:是对文件系统中所有块组进行管理的数据结构,每个块组在GDT中都有一个对应的条目,这个条目包含了块组的关键信息,如:inode表、数据块、inode位图、块位图的位置。

GDT是一个全局的数据结构,每个块组中并不包含一个单独的GDT完整副本,通常只存储在文件系统中块组0,它描述了文件系统中所有块组的信息。

struct group_descriptor {
    blk_t bg_block_bitmap;     /* 块位图的位置 */
    blk_t bg_inode_bitmap;     /* inode位图的位置 */
    blk_t bg_inode_table;      /* inode表的位置 */
    blk_t bg_free_blocks_count; /* 未分配的块数 */
    blk_t bg_free_inodes_count; /* 未分配的inode数 */
    blk_t bg_used_dirs_count;  /* 使用的目录数 */
    /* 其他字段... */
};

4.5.6. Super Block

  1. 超级块:是文件系统中一个全局的数据结构,即:对整个文件系统进行管理的数据结构,存放整个文件系统的结构信息,如:block、inode的数量,未使用用的block、inode的数量,最近一次挂载的时间,最近写入数据的时间等其他与文件系统相关的信息。
struct super_block {
    blk_t s_block_count;       /* 文件系统的总块数 */
    blk_t s_inode_count;       /* 文件系统的总inode数 */
    blk_t s_block_size;        /* 块大小 */
    blk_t s_inode_size;        /* inode大小 */
    blk_t s_blocks_per_group;  /* 每个块组的块数 */
    blk_t s_inodes_per_group;  /* 每个块组的inode数 */
    blk_t s_first_data_block;  /* 第一个数据块的位置 */
    blk_t s_first_inode_block; /* 第一个inode块的位置 */
    /* 其他字段... */
};
  1. 超级块的位置:一个文件系统,对应一个Super Block,通常在块组0中内保存着,为了提高文件系统的可靠性和容错性,会在个别块组内且存储Super Block的副本。

问1:为什么不在所有组中包含超级块?

  • 节省空间、减少冗余。

问2:为什么个别组内包含超级块?

  • 可靠性、容错性、文件系统修复:尽管Super Block在全局范围内只需存一份,但为了防止单点故障导致的数据丢失或文件系统损坏,通常会在个别块组中存储Super Block的副本,这样,即使主超级快损坏,可以从个别组中的超级块副本来恢复文件系统的状态。

💡Tips:Super Block的信息被破坏,则整个文件系统的结构被破坏了。

  1. 当OS启动时,它会识别并挂载系统上的各个分区。在这个过程中,OS会读取每个分区最头部的Super Block信息,并将其加载到内存中,为了在内存中表示这些信息,OS通常会为每个挂载的文件系统创建一个struct Super Block结构体对象,并将从磁盘上读取Super Block信息填充到这个结构体对象中,再用特定的数据结构将所有对象进行链接,即:对文件系统的管理,就转化为了对特定数据结构的增删查改。

5. 目录文件

5.1. 文件名和inode

  1. 在文件系统中,普通文件或目录都是文件系统中的文件,每个文件都有自己的inode和数据块,普通文件的内容存储了实际的数据,而目录文件的内容存储了文件名和其inode的映射关系。

任何一个普通文件,一定存放在一个目录中。

当你打开一个目录时,你看到的是目录中包含的文件名列表,而每个文件名都关联(或映射)到一个inode编号,通过inode编号可以找到具体的文件或目录。

5.2. 重谈文件的增删查改

问1:找一个文件,是通过inode编号查找,前提是你得先知道你的文件在哪一个分组中,如何知道?

分区内的inode编号是唯一的,OS会给分区中的每个分组分配一个起始inode编号和起始数据块编号,且每个分组内的inode总数、数据块总数是已知的。通过将inode编号与每个分组的inode编号范围进行对比,如果inode编号落在某个分组的范围内,则说明该文件处于这个分组内。

  1. 在一个目录下,进行文件操作(增、删、改),本质都需要修改目录的内容,即·:对目录权限的约束,可以间接约束在该目录下进行文件操作(增、删、改)。

  2. 新建文件:遍历位图 -> 在inode表中添加新的inode -> 初始化inode -> 分配数据块 -> 建立文件名和inode编号的映射关系 -> 更新目录内容。

初始化inode:inode编号 = 分组的起始inode编号 + 其所在inode表中的数组下标。

  1. 修改文件:查找inode -> 找到具体的文件 -> 更新数据块 / inode属性 -> 更新inode表。

查找inode:查找目录的内容,根据文件名和inode的映射关系,从而获取inode编号;

通过inode编号,找到具体的文件:inode编号与每个分组的起始inode编号进行对比,从而确认其所在的分组,再让inode编号 - 分组起始inode编号 = 在位图中的位置 = 在inode表中的位置。

5.3. 路径

  1. 查找一个文件,在OS中,都要逆向的递归般得到/,然后再从根目录进行路径解析。

查找一个文件,就得找到这个文件的inode,就必须查找这个文件所在的目录内容,而目录也是文件;查找目录文件,就得找到这个目录文件的indoe,就必须查找这个目录文件所在的目录内容,直到遇到根目录,根目录inode编号是已知的(逆向递归)。再从根目录正向进行路径解析,知道inode编号,就知道这个文件的内容,就知道这个目录文件下所有文件的inode。

6. 如何知道文件在哪个分区下

6.1. 格式化

  1. 概念:向指定的分区写入新的文件系统的操作。

  2. 目的:快速清空分区内的所有数据,并创建一个新的文件系统,以便分区能够存储新的数据。

每个分区可以有相同或者不同的Ext系列的文件系统。

6.2. 分区进行"挂载"

  1. 前提:一个写入文件系统的分区,要能被Linux使用,必须要把这个具有文件系统的分区进行"挂载"。

  2. 挂载:将一个文件系统所对应的分区,挂载到指定的目录下。使得用户可以通过访问指定的目录,实现访问分区下的目录或文件。

df -h

  • 功能:查看已挂载文件系统的磁盘使用情况,并以易于阅读的格式显示。

  1. 通过解析文件路径(字符串前缀匹配),可以确定哪个目录是文件路径的一部分,从而推断出文件存储在哪个分区上。

  1. 挂载的本质:将存储设备上的文件系统,与文件系统(Super Block)中的某个目录(挂载点,dentry)建立关联关系,使得用户可以通过访问挂载点目录来间接访问文件系统上的所有数据。

在这个过程中,Super Block提供了文件系统的全局信息,dentry通过目录下缓存机制来加速文件名的查找,它提供了文件名到inode的快速映射,使得用户可以通过文件名快速访问文件数据。

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

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

相关文章

c++primer第十三章 类继承

本章内容:单个类就可以提供用于管理对话框的全部资源。通常,类库是以源代码的方式提供的,这意味着可以对其进行修改,以满足需求。但是,C-提供了比修改代码更好的方法来扩展和修改类。这种方法叫作类继承(class inheria…

【Android 源码分析】Activity生命周期之onDestroy

忽然有一天,我想要做一件事:去代码中去验证那些曾经被“灌输”的理论。                                                                                  – 服装…

命令行操作的基本指令【Linux】学完使用操作命令行就像喝汤一样快

致谢:Linux常用命令大全(手册) – 真正好用的Linux命令在线查询网站 提供的命令查询 一、认识操作系统 1.1计算机层级结构 操作系统是一款进行软硬件资源管理的软件 计算机从最接近我们的开始是软件->操作系统->设备驱动->硬件,我们学习软件要学习他的使用方法,而…

【光伏混合储能】VSG并网运行,构网型变流器,虚拟同步机仿真

摘要 本文提出了一种基于光伏发电与混合储能系统结合的虚拟同步发电机(VSG)控制策略,该策略能够在并网运行时稳定电网电压和频率。通过仿真分析,验证了该策略在各种运行工况下的有效性,展示了其在电力系统中的广泛应用…

RDI ADCP命令与ASCII输出结构

RDI ADCP命令与ASCII输出结构 一、RDI垂直式ADCP:1.1固定命令:1.2 向导命令 二、RDI水平式ADCP三、ADCP 公共目录四、常用BBTalk命令五、ADCP的ASCII输出数据文件、流量与数据结构5.1 ASCII类输出:5.2 ASCII 输出数据文件头5.3 ASCII 输出数据集5.4 导航…

PMP--三模--解题--91-100

文章目录 10.沟通管理--沟通管理计划--沟通管理计划是项目管理计划的组成部分,描述将如何规划,结构化、执行与监督项目沟通,以提高沟通的有效性。该计划包括如下信息:干系人的沟通需求。--与干系人沟通的文件,要看沟通…

Prometheus监控MySQL主从数据库

案例分析Prometheus监控MySQL主从数据库 1. 规划节点 节点规划,见表1。 表1 节点规划 IP主机名节点192.168.100.3masterPrometheus Grafana192.168.100.3mastermysql/master mysqld_exporter node_exporter192.168.100.4nodemysql/master mysqld_exporter …

毕业设计选题:基于ssm+vue+uniapp的家庭记账本小程序

开发语言:Java框架:ssmuniappJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:M…

开放式耳机的优缺点?哪个品牌专业?好用的开放式蓝牙耳机分享

我相信很多想入手的开放式耳机的家人都想知道开放式耳机是什么,开放式耳机有什么优缺点,开放式耳机是不是智商税、值不值得购买以及如果要购买的话,有什么专业的开放式耳机品牌推荐。因为我毕竟是测评过三十多款开放式耳机的数码博主&#xf…

67.【C语言】枚举类型

1.定义 对于有限的情况,一一列举 如一周有7天,从周一到周日;光学三原色(Red Green Blue) 2.格式 enum 枚举类型名 {//枚举常量 }; 备注:enum为enumeration缩写 3.枚举成员变量的值 #include <stdio.h> enum color {Red,Green,Blue };int main() {printf("%d…

健康信息管理:SpringBoot的创新应用

第2章相关技术 2.1 B/S架构 B/S结构的特点也非常多&#xff0c;例如在很多浏览器中都可以做出信号请求。并且可以适当的减轻用户的工作量&#xff0c;通过对客户端安装或者是配置少量的运行软件就能够逐步减少用户的工作量&#xff0c;这些功能的操作主要是由服务器来进行控制的…

C++平台跳跃游戏

目录 开头程序Game.cpp源文件Player.h头文件Player.cpp源文件 程序的流程图程序游玩的效果下一篇博客要说的东西 开头 大家好&#xff0c;我叫这是我58。 程序 Game.cpp源文件 #include <iostream> #include "Player.h" using namespace std; void printma…

【环保背景高管1009】2022顶刊论文数据,环保背景高管对投资的影响探究

今天给大家分享的是国内顶刊数量经济技术经济研究2022年发布的名为《高管环保背景与绿色投资者进入》论文使用到的数据——高管环保背景数据以及管理自主权的高管环保背景数据&#xff0c;该文章利用中国上市公司沪深A股2007-2017年的面板数据&#xff0c;采用双向固定效应模型…

YOLOv11改进 | 独家创新- 注意力篇 | YOLOv11结合全新多尺度线性注意力机制MLAttention(全网独家创新)

1. MLAttention介绍 (1). 多尺度卷积操作&#xff1a;MLAttention通过多尺度卷积操作来增强不同尺度的特征表达能力。采用了多种卷积核尺寸&#xff08;例如5x5、1x7、7x1、1x11、11x1、1x21、21x1&#xff09;的深度可分离卷积来捕捉不同感受野的特征。较小的卷积核擅长捕捉细…

四,MyBatis-Plus 当中的主键策略和分页插件的(详细实操使用)

四&#xff0c;MyBatis-Plus 当中的主键策略和分页插件的(详细实操使用) 文章目录 四&#xff0c;MyBatis-Plus 当中的主键策略和分页插件的(详细实操使用)1. 主键策略1.1 主键生成策略介绍 2. 准备工作&#xff1a;2.1 AUTO 策略2.2 INPUT 策略2.3 ASSIGN_ID 策略2.3.1 雪花算…

基础算法之双指针--Java实现(下)--LeetCode题解:有效三角形的个数-查找总价格为目标值的两个商品-三数之和-四数之和

这里是Themberfue 今天继续讲解经典算法 > 双指针算法 没看过上篇文章的小伙伴记得去看看哦&#x1f618; 有效三角形的个数 题目链接&#xff1a;有效三角形的个数 题目解析 题目要求在该数组中任意选取三个数&#xff0c;看这三个数是否可以构成可以一个有效三角形。最后…

2024上半年网络安全漏洞态势报告

2024年9月26日&#xff0c;“2024中国数字经济创新发展大会”在汕头成功召开&#xff0c;大会汇聚业界精英&#xff0c;旨在全面探讨在新形势新挑战下&#xff0c;如何“健全数据安全体系 构建可信流通环境”。在《数据安全与合规发展专题》分论坛上&#xff0c;工业和信息化部…

Windows远程Kylin系统-xrdp

Windows远程Kylin系统-xrdp 一. 查看开放端口 查看是否有3389端口二. 安装xrdp Kylin对应的是centos8 下载链接&#xff1a;https://rhel.pkgs.org/8/epel-x86_64/xrdp-0.10.1-1.el8.x86_64.rpm.html rpm -Uvh 包名 systemctl start xrdp 启动服务 systemctl enable xrdp …

只出现一次的数字|||(考察点为位操作符)

目录 一题目&#xff1a; 二思路汇总&#xff1a; 三代码解答&#xff1a; 一题目&#xff1a; leetcode原题链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 二思路汇总&#xff1a; 思路&#xff1a;如果直接对数组按位异或&#xff0c;那么最后得到的是a^b&a…

pnpm install的时候失败提示python问题

忘记是哪个依赖了&#xff0c;npm正常&#xff0c;pnpm的时候就异常&#xff0c;但是报错里python异常 解决方法&#xff1a;安装python就行 ennn免安装的python好麻烦 网上找教程安装python好麻烦&#xff0c;发现微软可以直接安装&#xff0c;就用微软的安装了 查看结果 p…