Linux之文件系统前世今生(一)
Linux在线1
Linux在线2
一、 基本概念
1.1 块(Block)
在计算机存储之图解机械硬盘这篇文章中我们提到过,磁盘读写的最小单位是扇区,也就是 512 Byte;很明显,每次读写的效率非常低。
为了提高IO效率,我们要一次读写多个扇区。Linux 中一次性读写 8 个扇区, 也就是 4 KB,我们给这 4KB一个名字,记为块(Block);也就是说,块(Block)是 Linux 中每次读写磁盘的最小单位。
当然也可以一次性读取 1K(2个扇区),2K (4个扇区)。

- Block 的大小和数量在格式化后无法改变。
- 一个 Block 只能存放一个文件的数据。
- 如果文件大于 Block 的大小,则一个文件会占用多个 Block。
- 如果文件小于 Block 的大小,则 Block 中多余的容量将无法再被使用,即磁盘空间会浪费。
1.2 文件系统
1.2.1 Inode
我们给所有 Block 编号(从0开始)后,就可以在 Block 中写入数据了。

比如,现在有一个名为 today.log 的文件,文件内容大小为 10 K,我们可以把它存储在Block 40 、Block 41 、Block 42 中(Block大小为4K,所以需要3个Block);
文件存起来了,怎么找到这个文件呢?
- 得有个索引啊,不然,只有GOD知道这个文件存在了哪个Block了,我们将这个索引记为 Inode(Index node),前面提到的3个 Block 记为 数据区(Data Area 或者 Data Blocks);
- Inode中除了存储数据块号码(地址),还有其它文件元数据需要存储,比如文件类型、文件CRUD时间、文件权限等;
- Inode一般为
128 byte或256 byte。
- Inode 也要存储起来,以便我们日后使用,我们可以把所有的 Inode 统一存放在几个连续的 block 中,记为 Inode 区(Inode Table);
- Inode table 就是个Inode数组(
Inode[]),数组下标我们记为Inode号; - Inode数组很大时,要找到一个空闲的 Inode 就得线性扫描了,为提高效率,我们用1个位图(Bitmap)来标识 Inode 数组中元素被使用情况,记为 Inode位图(Inode Bitmap),Inode位图也要消耗 Block 来存储。
- Inode Bitmap 用于标识 Inode Table 的使用状态,其使用 1 bit 来表示:0 表示空闲,1 表示占用;

现在我们思考另外一个问题,我们把 today.log的内容放在了Block 40 、Block 41 、Block 42 中,万一这3个Block中有数据,即被别的文件写入内容了,那我们这么暴力的使用就会导致别的文件被损坏了,所以我们得记录下哪些Block使用了,哪些未被使用。同样,我们得把这部分信息使用 Bitmap 存储在 Block 中,记为数据位图 ( Block Bitmap )
- Block Bitmap 用于标识所有的 Block 的使用状态,其使用 1 bit 来表示:0 表示空闲,1 表示占用;
- 如果 Block 的大小为 4K,那么其总共有 32768( 4 x 1024 x 8 ) 个 bit ,即一个 Block 可用于描述的 Block为 32768 个;
- 注意,Block Bitmap 只在写数据时使用,因为只有写数据才需要找到空闲的 Block;
- 使用Bitmap 可以在大量数据块的情况下,快速找到哪些块是可用的,避免了线性扫描。
到目前为止,我们的 Block 划分成了下图所示:

我们
today.log文件的写入逻辑如下:
- 系统查询 Inode Bitmap 后分配 Inode号为
12,659,同时标识该bit 为 1;- 在 Inode Table 中 写入信息,即
Inode[12,659] = Inode信息;- 查询 Block Bitmap 后分配
block 40,同时更新 Block Bitmap 40这个bit 为 1;- 将文件内容写入;
- 写满一个Block,继续回到3. 直到写完数据才往6.走;
- 更新Inode Table ,即将数据块号(40、41、42),文件大小等其它信息更新到
Inode[12,659]中;
1.2.2 Inode记录大文件数据地址
前面我们限制了文件内容为 10KB,若文件很大,比如 400 MB,存储会有什么问题呢?
- 我们的数据块存储400M内容需要 100,000(400 M / 4 K)个Block,这当然没有什么问题,但是 Inode 是有大小的,100,000个 Block 地址(大小为 4 Byte)存储需要 400 KB(100,000 * 4)空间,已超过 Inode的大小(即使为256 Byte);
- 一个直观的方式是扩大Inode 大小,若文件内容为1G呢,扩大到什么范围?
- 软件领域里有一句经典的话是“计算机科学中的所有问题都可以通过增加一个间接层来解决”,所以
- 一个Block可以存储 1024 (4KB / 4Byte ) 个地址,1024个地址表示的数据范围可以达到 4MB(1024 * 4k),即加一层可以存储4MB数据;
- 加两层可以存储 4GB(1024 * 4M)数据;
- 加三层可以存储 4TB (1024 * 4G)数据;
- 我们可以加两层,把这100,000个Block地址存储在另外的几个 Block 内,然后让 Inode 中数据块地址指向第2层Block即可。
Inode结构示意图如下:Inode记录数据Block号码的Block数组大小为15,前12个为直接地址(可以记录 48 KB 数据,12 * 4KB = 48KB)、1个一级间接指针、1个二级间接指针,1个三级间接指针。
综上,文件大小理论上最大是 48K + 4M + 4G + 4T。

- 当文件小于 48KB 时,用直接指针即可记录;
- 超过48KB,但小于4MB + 48KB 时,增加一级间接指针记录;
- 超过4MB + 48KB,但小于4GB + 4MB + 48KB时,增加二级间接指针记录;
- 超过4GB + 4MB + 48KB 时,增加三次间接指针记录。
注意,这里采用 32 bit 寻址;所以 Block指针数组占用空间大小为 60 Byte (15 * 4 Byte)
1.2.3 目录
前面我们通过 Inode 信息和数据块(Data Blocks)解决了文件储存和读取问题,但是我们的文件都是位于某个目录下的,怎么样将目录信息也储存起来呢?
比如目录 /xiaolingting/month/january/下有2个文件:yesterday.log、today.log:

Linux中有句经典哲学: “一切皆文件 ” ,所以我们把目录也看成文件处理即可,即:
目录january看成是文件名,文件内容为目录下文件列表,假设其 Inode 号为10,000,我们来看下在目录/xiaolingting/month/january/下打开today.log的步骤:
- 根据
january的 Inode号:10,000 到Inode Table里找到对应的Inode信息,即Inode[10,000]; - 从上述Inode信息里的数据块地址 37 找到 目录下的内容;
- 在目录的数据块内容里找到了
today.log的 Inode号码:12,659; - 根据
today.log的 Inode号:12,659 到Inode Table里找到对应的Inode信息,即Inode[12,659]; - 从上述Inode信息里的数据块地址 40、41、42找到文件
today.log的内容; - 读取文件
today.log:“世人妙性本空……”

1.2.4 文件类型
在前面我们把目录也统一看成文件,从而方便的利用文件的存储规则对目录进行了存储;但数据块内存储到底是目录还是真实的文件内容,这个是需要标识出来的,我们把这个标识记为文件类型,同样存储在 Inode 里。
常见文件类型如下表所示:
| 编码 | 文件类型 |
|---|---|
| 0 | Unknown |
| 1 | Regular File |
| 2 | Director |
| 3 | Character Device |
| 4 | Block Device |
| 5 | Named Pipe |
| 6 | Socket |
| 7 | Symbolic Link |
1.2.5 超级块
思考以下问题:
- 前面我们成功找到了
/xiaolingting/month/january/下的today.log文件,但是有个前提,我们假设了目录january的Inode号为10,000,抛开这个假设,我们怎么知道这个Inode号呢?当然是从上一层目录month里的文件内容里去读喽,这不是死循环了吗?得有个终止条件啊,即根目录/的Inode号码是多少呢? - 我们约定的Block大小为4KB,Inode 的大小为128 Byte, 这些信息记录在哪里?
- 磁盘一共有多少空间可用,已经用了多少,还有多少可用呢?
我们可以使用存储空间开头的位置来存储上面的这些信息,在机器初始化时将这些内容加载到内存中使用即可;我们将这个特殊的块记为超级块(super_block);
- 使用
df命令读取的就是超级块(super_block),所以它的统计速度非常快。- 相对应的,用
du命令时,需要遍历整个目录的所有文件,所以查看一个较大目录的已用空间会非常慢。- 常见的df和du不一致情况就是文件删除的问题。当一个文件被删除后,在文件系统目录中已经不可见了,所以du就不会再统计它了。然而如果此时还有运行的进程持有这个已经被删除了的文件的句柄,那么这个文件就不会真正在磁盘中被删除, 分区超级块中的信息也就不会更改。这样df仍旧会统计这个被删除了的文件。
通过lsof | grep delete查看占用文件的进程,kill进程即可解决。
此外还有我们之前提到的Inode Bitmap、Block Bitmap、Inode Table、Data Blocks它们各自的起始位置和容量大小,也需要记录下来,我们把这些信息存储在超级块(super_block) 旁边的块上,记为描述块(Description Block)。
至此,逻辑块变成了下面图示的样子,我们的文件就可以愉快的读取和写入了。

看上面图示会发现图里多了个启动块即Boot Block,也称为boot sector。它位于分区上的第一个块,占用 1K Byte,并非所有分区都有这个boot sector,只有装了操作系统的主分区和装了操作系统的逻辑分区才有。
二、EXT文件系统
前面我们捣鼓出来一个简易的文件系统,麻雀虽小,但五脏俱全。接下来我们看看Linux中真实的文件系统 EXT。
EXT
全称Linux extended file system, extfs,即Linux扩展文件系统,Ext2就代表第二代文件扩展系统,Ext3/Ext4以此类推,它们都是Ext2的升级版,只不过为了快速恢复文件系统,减少一致性检查的时间,增加了日志功能,所以Ext2被称为索引式文件系统,而Ext3/Ext4被称为日志式文件系统。

常见的文件系统类型非常多,比如:
- Windows 默认使用 NTFS
- MacOS、iOS、watchOS 默认使用 APFS(曾经使用 HFS)
- 光盘类的文件系统ISO9660
- 网络文件系统NFS
- 内容寻址文件系统 Git
- 分布式文件存储系统 TFS(Taobao File System)
2.1 EXT2
以EXT2为例,系统结构如下图所示:

-
为了方便管理,Ext2将这些Block聚集在一起分为几个大的块组(Block Group),每个块组包含的等量的逻辑块,在块组的数据块中存储文件或目录;
为啥分组呢?
- 降低文件系统损坏风险;
- 以
Block Bitmap为例来说,因为如果所有的bitmap都存放在同一个块组(Block Group)中,当该group数据块被损坏时,整个文件系统的可用性都会受到影响。分散保存可以降低这种风险。
- 以
- 提高性能。
- 假设文件系统是 100GB 时,分为 25,000,000(100G / 4K)个Block,用Bitmap需要存储需要储存25,000,000 个bit,25MB的数据量啊,想在其中找一个空闲的 Bit 要扫描好长时间啊。将这 25MB数据分散到不同块组中,扫描一个块组可以节约不少时间。
块组容量
根据图示,一个块组里 Block Bitmap 占用1 个block ,即 4KB,即 215 ( 4 * 1024 * 8 ) 个 bit,则可以表示128 MB (4 * 1024 * 8 * 4KB) - 降低文件系统损坏风险;
-
注意:块组(Block Group),并没有限制 Inode 中记录的数据块(data block)属于其它group的情况!ext2文件系统甚至鼓励这种跨group存储文件。
-
块组描述信息为
Inode Bitmap、Block Bitmap、Inode Table、Data Blocks,其大小固定为32Byte, 每个块组都占用一个Block,有点浪费空间,把所有块组描述信息统一放在一起,组成了块组描述符表(Group Description Table, GDT),保留GDT 用于以后扩容文件系统使用,防止扩容后块组太多,使得块组描述符超出当前存储GDT的blocks。 -
超级块不仅存储在第一个块组,后续还有特定的块组内部存储超级块(Super Block),这些超级块均存储一样的信息,起到备份的作用,提高了文件系统的健壮性。
超级块(Super Block)、块组描述符表( GDT) 和 保留GDT 对于文件系统而言是至关重要的,三者形影不离,超级块丢失或损坏必将导致文件系统的损坏。
正常情况下文件系统只使用第一个块组即Block Group 0中超级块信息来获取文件系统属性,只有当Group0上的Super Block损坏或丢失才会将下一个备份Super Block复制到Group0中来恢复文件系统。
2.1.1 EXT2 文件实际大小
在 “1.2.2 Inode记录大文件数据地址” 这一小节中,我们提到了 “文件大小理论上最大是 48K + 4M + 4G + 4T”,注意,这里说的是理论,实际有内核等各种限制(2.4 内核对单个块设备的限制是 2TB),最大为 2 TB;
2.2 Ext文件系统预留 Inode
Ext 文件系统预留了一部分 Inode 作为特殊用途,如下所示。
| Inode | 用途 |
|---|---|
0 | 不存在,可用于标识目录的 Data Block 中已删除的文件 |
| 1 | 虚拟文件系统,如:/proc、/sys |
2 | 根目录 |
| 3 | ACL 索引 |
| 4 | ACL 数据 |
| 5 | Boot Loader |
| 6 | 未删除的目录 |
| 7 | 预留的区块组描述符 Inode |
| 8 | 日志 Inode |
| 11 | 第一个非预留的 Inode,通常是 lost+fount 目录 |
注意:Inode有效编号从 1 开始
2.3 如何删除文件
- 从前面章节可以了解到,删除一个文件时,
- 先把目录文件里的文件名和Inode映射删除;
实际是把文件名对应的 Inode 修改为
0(2.2 小节中 预留 Inode 为 0 时用于标记删除) - 然后把
Block Bitmap和Inode Bitmap均置为0即可,这就表示该空间空闲了;这里有个前提:即Inode 里的链接数为
0,详见Linux之文件系统前世今生(二)
- 先把目录文件里的文件名和Inode映射删除;
- 至于文件占用
Data Blocks和Inode信息,后面使用时直接覆盖即可。 - 如果在Linux中误删除一个文件,还是能恢复的,但是前提必须是
Inode和Data Block没有被占用。
2.4 EXT3
Ext2写一个文件要多个步骤,如更新Inode Bitmap、更新Block Bitmap、刷新Inode数据块指针……
当系统突发故障,刚写完Inode Bitmap,系统断电了,我们怎么保证数据的持久化和一致性呢?
聪明的你一定想到了数据库事务是怎么保证事务ACID的,当然是预写式日志(Write-ahead logging,WAL)。
Ext3 正是采用了 WAL 来解决上述问题的。
2.5 EXT4
2.5.1 Ext2/3 面临的问题:
- Ext2/3 的 Inode 中 数据块指针数组容量为15,文件最大为 4TB + 4GB + 4MB + 48KB ;即无法存储超过此大小的文件;
- 文件很大时,使用三级间接指针,性能较低;
- block很多,导致消耗
Block Bitmap也多,对于一个巨大的文件,扫描整个Block Bitmap耗时显著增加。
2.5.2 Ext4 优化
Ext2/3 上述问题的一个重要原因是面向 Block 进行分配,对于N个连续的 Block ,需要记录N个指针信息。所以我们可以将这连续的N个Block的指针信息记录1份,我们把这一份信息记为 区(Extent) ,即 Extent 可以尽可能的包含物理上连续的 N 个 Block,N为任意正整数( 1 <= N <= 215 ,一个块组最多215个 Block) ,如下图所示:

-
Extent 分为 head 和 body,一个head 可以搭配多个body,如下图所示:

-
Ext4 通过 B+树 将 Extent 组织起来:
- Extent 这个结构的根节点(Root)存在了 Inode 里原来的的数据指针区域;
- 中间节点和叶子节点存在 1个 Block 上,即Extent 最大为 4KB;

-
Extent 组成的B+ 树,添加了中间节点,如下图所示:

我们来算下Ext4 这样存储后,可以存储的文件大小:
- 1 个块组为 128 M,一个 extent_body最多可以表示一个块组,Inode 里有4个 extent_body,可以表示 512 MB (4 * 128 MB);
- 加一个中间节点Extent,可以表示大约 340 (4 KB / 12 Byte ) 个块组,可以表示大约40 GB ( 340 * 128 MB);
- 第二层可以放4个中间节点,可以表示大约160 GB (4 * 40GB);
- ……
Ext4 实际实现时比较复杂,大概原理如上所述。
三、虚拟文件系统(Virtual File System, VFS)
Linux中允许众多不同的文件系统共存并且对文件的操作可以跨文件系统而执行,这依赖于VFS(Virtual File System)虚拟文件系统。通俗点,就是 VFS 类比接口,不同的文件系统如Ext2、Ext3、Ext4、NFS 都是这个接口的具体实现,这个和面向对象里的多态一样。
VFS 支持的文件系统:
- 基于磁盘(disk-based)的文件系统
- 管理本地磁盘和模拟磁盘的设备。
- 网络文件系统
- 它允许方便访问网络上其它计算机的文件系统。
- 特殊文件系统
- 也是一种虚拟文件系统,它不管理磁盘空间。
| 文件系统分类 | 具体文件系统 | 备注 |
|---|---|---|
| 基于磁盘 | Ext2/3/4 | Linux |
| NFTS(New Technology File System) | windows | |
| HFS(Hierarchical File System)、AFFS(Apple File System)、ADFS | 苹果 | |
| ZFS(Zettabyte File System) | Zettabyte 相当于1万亿兆字节。它能存储1800亿亿(18.4×1018)倍于当前64位文件系统的数据。ZFS 的设计如此超前以至于这个极限就当前现实实际可能永远无法遇到。 | |
| btrfs( B-Tree Filesystem) | ||
| 网络文件系统 | NFS、CIFS(Common Internet Filesystem) | |
| Coda、AFS(Andrew filesystem) | ||
| NCP(Novell’s NetWare Core Protocol) | ||
| 特殊文件系统(虚拟文件系统) | proc | 挂载于/proc目录下,由内核在内存中创建,用于跟踪正在执行的进程 |
| devfs | linux 2.6内核以前使用devfs来管理位于/dev目录下的所有设备。devfs缺点:一个设备映射的设备文件可能不同。例如,U盘可能对应sda,也可能对应sdb,没有足够的主/辅设备号,当设备过多的时候,此问题突显 | |
| sysfs | 为了解决devfs的缺点,linux 2.6内核引入了sysfs,挂载于/sys目录下 | |
| tmpfs(temporary filesystem) | tmpfs是构建在内存中的,所以存放在tmpfs中的所有数据在卸载或断电后都会丢失 |
借助VFS可以直接使用open()、read()、write()这样的系统调用操作文件,而无须考虑具体的文件系统和实际的存储介质。

VFS是一种软件机制,只存在于物理内存当中,屏蔽了下层具体文件系统操作的差异,为上层的操作提供一个统一的接口。VFS同样也有 超级块(Super Block)和 Inode,此外新增了目录项(Directory Entry, Dentry)和文件对象(File)。
-
超级块:超级块对象表示一个文件系统。它存储一个已安装的文件系统的控制信息,包括文件系统名称(比如Ext2)、文件系统的大小和状态、块设备的引用和元数据信息(比如空闲列表等等)。VFS超级块存在于内存中,它在文件系统安装时建立,并且在文件系统卸载时自动删除。
-
Inode:将磁盘中的Inode加载到内存中,同时添加VFS内的额外信息如进程引用计数器。详见Linux之文件系统前世今生(二)
-
目录项(Dentry):由于VFS会经常的执行目录相关的操作,比如切换到某个目录、路径名的查找等等,为了提高这个过程的效率,VFS引入了目录项的概念。目录项对象没有对应的磁盘数据结构,只存在于内存中。一个路径的各个组成部分,不管是目录还是普通的文件,都是一个目录项对象。如在路径
/xiaolingting/month/january/today.log中,VFS在遍历/,xiaolingting、month、january、today.log的过程中,将它们逐个解析成目录项对象。解析一个路径是一个耗时的、常规的字符串比较过程。 -
文件对象(File):文件对象描述的是进程已经打开的文件。一个文件可以被多个进程打开,所以一个文件可以存在多个文件对象。
相关文章:
Linux之文件系统前世今生(一)
Linux在线1 Linux在线2 一、 基本概念 1.1 块(Block) 在计算机存储之图解机械硬盘这篇文章中我们提到过,磁盘读写的最小单位是扇区,也就是 512 Byte;很明显,每次读写的效率非常低。 为了提高IO效率&…...
当设置dialog中有el-table时,并设置el-table区域的滚动,看到el-table中多了一条横线
问题:当设置dialog中有el-table时,并设置el-table区域的滚动,看到el-table中多了一条横线; 原因:el-table有一个before的伪元素作为表格的下边框下,初始的时候已设置,在滚动的时候并没有重新设置…...
Windows远程桌面网关出现重大漏洞
微软披露了其Windows远程桌面网关(RD Gateway)中的一个重大漏洞,该漏洞可能允许攻击者利用竞争条件,导致拒绝服务(DoS)攻击。该漏洞被标识为CVE-2025-21225,已在2025年1月的补丁星期二更新中得到…...
vue 前端优化性能优化方法
1.列表使用唯一 key v-for"item in activeList" :key"item.id"原因是不使用 key 或者列表的 index 作为 key 的时候,每个元素对应的位置关系都是 index,直接导致我们插入的元素到后面的全部元素,对应的位置关系都发生了变…...
docker-compose部署kafka 3.3.1 kraft
一、服务器: 节点1:10.1.1.165 节点2:10.1.1.164 节点3:10.1.1.169二、添加环境地址解析 vim /etc/hosts kafka1 10.1.1.165 kafka2 10.1.1.164 kafka3 10.1.1.169三、节点配置 节点1 version: "3" services:kafka1:image: bitnami/kafka:3.3.1contain…...
【Python】第二弹---深入理解编程基础:从常量、变量到注释的全面解析
✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】【MySQL】【Python】 目录 1、常量和表达式 2、变量和类型 2.1、变量是什么 2.2、变量的语法 2.3、变量的类型 2.4、动态类型特…...
[BrainShadow-V1] VR头戴设备统计报告
Brain-Shadow-V1 EventVR headsetsReported byXiao enDate2025/01/15Version1.0 HTC Vive Pro 2 Pro HTC Vive Pro 2 是一款高端虚拟现实头显,配备双 2.5K 显示屏,组合分辨率达到 48962448,提供 120 的视场角和 120Hz 的刷新率。该设备支持…...
跨境电商使用云手机用来做什么呢?
随着跨境电商的发展,越来越多的卖家开始尝试使用云手机来协助他们的业务,这是因为云手机具有许多优势。那么,具体来说,跨境电商使用云手机可以做哪些事情呢? (一)实现多账号登录和管理 跨境电商…...
DAY23 使用具有通用性的队列
1.初始化数组 //Initialize arrays.int tempLength getNumNodes();valuesArray new char[tempLength];indicesArray new int[tempLength];int i 0;2.初始化队列 创建了一个名为tempQueue的CircleObjectQueue对象,即一个循环对象队列。 将当前对象(即…...
汽车网络信息安全-ISO/SAE 21434解析(上)
目录 概述 第四章-概述 1. 研究对象和范围 2. 风险管理 第五章-组织级网络安全管理 1. 网络安全治理(cybersecurity governance) 2. 网络安全文化(cybersecurity culture) 3. 信息共享(Information Sharing) 4. 管理体系…...
通用查询类接口开发的另类思路
文章目录 一、需求概述二、开发方式1、传统开发方式2、将接口视为资源文件1.)springmvc工程2.)springboot工程3.)nginx代理 三、接口数据如何更新1、原始数据文件生成接口数据1.)定义启动类2.)启动监听3.)文…...
uc/os-II 原理及应用(八) 系统裁减以及移植到51单片机-下
现在说明几个重要的点, OSStartHighRdy 的作用就是把任务栈复制到系统栈上面,再利用RET的时候会从系统栈上到一个地址放到PC寄存器上来实现任务运行。OSCtxSw是任务切换,把系统栈全部备份到当前任务栈映射上,然后改OSTCBCur,调用…...
职场沟通与行为
职场沟通与行为 引言 在职场上,你是否曾遇到过困惑的沟通?是否对同事的行为有过疑虑?这不仅是个别现象,而是我们这个时代工作文化中的普遍问题。许多职场的摩擦,来自沟通不畅或是行为不当。那么,如何才能…...
【tailscale 和 ssh】当服务器建立好节点,但通过客户端无法通过 ssh 连接
背景 当服务器建立好节点,一切显示正常但通过客户端无法通过 vs code 中的 ssh 连接到服务器 问题解决 因为服务器是重装过的,所以忘记在服务器上下载 ssh 了。。。安装完成并启动 SSH 服务后便可正常连接! sudo apt update sudo apt in…...
Spark 之 Aggregate
Aggregate 参考链接: https://github.com/PZXWHU/SparkSQL-Kernel-Profiling完整的聚合查询的关键字包括 group by、 cube、 grouping sets 和 rollup 4 种 。 分组语句 group by 后面可以是一个或多个分组表达式( groupingExpressions )。 聚合查询还支持 OLAP 场景下的多…...
【JSqlParser】Java使用JSqlParser解析SQL语句总结
简述 Java解析SQL语句有很多工具都可以做到,比如Mybatis、Druid、目前用来用去最全面的仍然是Jsqlparser,它是一个Github上的开源项目,JSqlParser是一个用于解析SQL语句的Java库,它可以帮助开发者分析和操作SQL语句的结构。无论是…...
Linux下的dev,sys和proc(TODO)
(TODO) 还有一个sysfs 在 Linux 系统中,/dev、/sys 和 /proc 是三个特殊的虚拟文件系统目录,它们各自有特定的用途,主要用于与设备和内核交互。以下是它们的详细区别和功能说明: 1. /dev(Devi…...
【Unity3D】利用Hinge Joint 2D组件制作绳索效果
目录 一、动态绳索 (可移动根节点) 二、静态绳索 三、利用Skinning Editor(Unity2022.3.15f1正常使用) 四、注意事项 一、动态绳索 (可移动根节点) 动态绳索 DynamicRope空物体 Anchor和whitecircle是相同位置的物体ÿ…...
Springer Nature——Applied Intelligence 投稿指南
投稿系统:Editorial Manager (Manuscript and Peer Review) : 使用Editorial Manager 投稿系统的期刊列表:期刊列表 期刊主页:Spring Nature 主页 投稿主页:Spring Nature Submit SystemSubmission Guidelines: Official Submissi…...
数据结构、数据类型、数字编码、字符编码:保姆级图文详解
文章目录 前言1、数据结构分类1.1、逻辑结构:线性与非线性1.2、物理结构:连续与分散1.3、数据结构的实现方式1.4、数据结构的选择依据 2、基本数据类型2.1、定义与分类2.2、存储形式 3、数字编码3.1、原码、反码与补码3.2、浮点数编码3.3、整数与浮点数区…...
Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...
【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...
使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度
文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...
基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
