当前位置: 首页 > news >正文

PG在还没有pg_class的时候怎么访问基础系统表?

在没有pg_class的时候,数据库怎么访问系统表?这个问题可以分成两个阶段来看:

  1. 数据库簇初始化,此时一个database都没有,所以怎么构造和访问pg_class等系统表是一个问题
  2. 私有内存初始化系统表。PG的系统表信息是放在backend本地进程上的,backend在初始化的时候又怎么load pg_class?

初始化数据字典

在数据库还没有初始化的时候,明显是不能通过访问数据字典来初始化database、pg_class等等对象的,因为一个库都没有就不能create database,也没有pg_class去查元数据信息。
PG通过bki文件的特殊语言初始化一些数据结构,然后在bootstrap模式初始化一个原始database1

编译阶段:genbki.h & genbki.pl

src/include/catalog/genbki.h

 * genbki.h defines CATALOG(), BKI_BOOTSTRAP and related macros* so that the catalog header files can be read by the C compiler.* (These same words are recognized by genbki.pl to build the BKI* bootstrap file from these header files.)

genbki.h内容很少,主要是为了catalog相关操作的宏定义,以及给KBI bootstrap文件的宏定义。数据字典的头文件基本都包含genbki.h
genbki.pl会在编译过程读取/src/include/catalog目录下的.h表定义文件(不含pg_*_d.h),并创建postgres.bki文件和pg_*_d.h头文件。
以pg_class为例:

[postgres@catalog]$ ll |grep pg_class 
-rw-r----- 1 postgres postgres   3682 Aug  6  2019 pg_class.dat
lrwxrwxrwx 1 postgres postgres     86 Apr  8 20:31 pg_class_d.h -> /lzl/soft/postgresql-11.5/src/backend/catalog/pg_class_d.h
-rw-r----- 1 postgres postgres   5219 Aug  6  2019 pg_class.h

pg_*_d.h头文件就是genbki.pl生成的。pg_*_d.h文件中都包含下面的一段话:

It has been GENERATED by src/backend/catalog/genbki.pl

每个数据字典都有一个结构体typedef struct FormData_*catalogname*用以存储数据字典的行数据2,例如pg_class的FormData_pg_class

CATALOG(pg_class,1259,RelationRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(83,RelationRelation_Rowtype_Id) BKI_SCHEMA_MACRO
{/* oid */Oid			oid;/* class name */NameData	relname;/* OID of namespace containing this class */Oid			relnamespace BKI_DEFAULT(pg_catalog) BKI_LOOKUP(pg_namespace);/* OID of entry in pg_type for relation's implicit row type, if any */Oid			reltype BKI_LOOKUP_OPT(pg_type);/* OID of entry in pg_type for underlying composite type, if any */Oid			reloftype BKI_DEFAULT(0) BKI_LOOKUP_OPT(pg_type);/* class owner */Oid			relowner BKI_DEFAULT(POSTGRES) BKI_LOOKUP(pg_authid);.../* access-method-specific options */text		reloptions[1] BKI_DEFAULT(_null_);/* partition bound node tree */pg_node_tree relpartbound BKI_DEFAULT(_null_);
#endif
} FormData_pg_class;

pg_class的OID写死了1259,所有字段都在FormData_pg_class结构体中。
用户存储数据的结构体初始化后,会使用对应的.dat文件插入基础数据。pg_class中会插入4条数据,可以理解为bootstrap item(pg15中的数据字典表有49个):

{ oid => '1247',relname => 'pg_type', reltype => 'pg_type' },
{ oid => '1249',relname => 'pg_attribute', reltype => 'pg_attribute' },
{ oid => '1255',relname => 'pg_proc', reltype => 'pg_proc' },
{ oid => '1259',relname => 'pg_class', reltype => 'pg_class' },
postgres=#  select oid,relname from  pg_class where oid::int >=1247 and oid::int<=1259;oid  |   relname    
------+--------------1247 | pg_type1249 | pg_attribute1255 | pg_proc1259 | pg_class

把基础数据字典写入后,其他的都可以依赖这些数据生成。

初始化database阶段:initdb&postgres.bki

initdb.c中的注释:

 * To create template1, we run the postgres (backend) program in bootstrap* mode and feed it data from the postgres.bki library file.  After this* initial bootstrap phase, some additional stuff is created by normal* SQL commands fed to a standalone backend. 

以bootstrap模式启动backend并运行postgres.bki脚本,postgres.bki可以在没有任何系统表的情况下,执行相关函数。此后才可以使用正常的SQL文件和启动标准的backend进程。
template1可以称之为bootstrap database了,postgres、template0两个库是在template1建立以后才创建:

void
initialize_data_directory(void)
{
.../* Bootstrap template1 */bootstrap_template1();
...make_template0(cmdfd);make_postgres(cmdfd);PG_CMD_CLOSE;check_ok();
}

有了template1后,make_template0make_postgres创建对应的template0 database和postgres database,直接用一般的SQL语句CREATE DATABASE命令创建:

/** copy template1 to postgres*/
static void
make_postgres(FILE *cmdfd)
{const char *const *line;/** Just as we did for template0, and for the same reasons, assign a fixed* OID to postgres and select the file_copy strategy.*/static const char *const postgres_setup[] = {"CREATE DATABASE postgres OID = " CppAsString2(PostgresDbOid)" STRATEGY = file_copy;\n\n","COMMENT ON DATABASE postgres IS 'default administrative connection database';\n\n",NULL};for (line = postgres_setup; *line; line++)PG_CMD_PUTS(*line);
}

backend本地缓存数据字典

PG私有内存的基础知识可参考PostgreSQL内存浅析3

PG的数据字典信息存放在本地backend进程中,非共享。数据字典缓存主要关注的是syscache/catcache和relcache,他们分别缓存系统表和表模式信息。
其中syscache/catcache是用于缓存系统表的,syscache相当于catcache的上层结构。syscache是一个数组,数字中的每个元素对应一个catcache,每个catcache对应一个系统表1

//PG15.3 SysCacheSize=35
static CatCache *SysCache[SysCacheSize];

pg在fork backend的时候调用的是InitPostgres,其中会调用syscache/catcache和relcache的初始化函数。下面来看看backend的初始化。

syscache/catcache初始化

struct cachedesc
{Oid			reloid;			/* OID of the relation being cached */Oid			indoid;			/* OID of index relation for this cache */int			nkeys;			/* # of keys needed for cache lookup */int			key[4];			/* attribute numbers of key attrs */int			nbuckets;		/* number of hash buckets for this cache */
};static const struct cachedesc cacheinfo[] = {{
...	{RelationRelationId,		/* RELNAMENSP */ClassNameNspIndexId,2,{Anum_pg_class_relname,Anum_pg_class_relnamespace,0,0},128},{RelationRelationId,		/* RELOID */ClassOidIndexId,1,{Anum_pg_class_oid,0,0,0},128
...
};

例如pg_class,由genbki.pl生成的pg_class_d.h中定义Anum_pg_class_oid

#define Anum_pg_class_oid 1

reloid就是oid

  select oid,relname from  pg_class where oid::int >=1247 and oid::int<=1259;oid  |   relname    
------+--------------1259 | pg_class

InitCatalogCache其实是初始化syscache数组,也就是初始化所有的catcache。InitCatalogCache最终通过InitCatCache全量初始化CatCache(这里其中一个就有pg_class的):

void
InitCatalogCache(void)
{
...for (cacheId = 0; cacheId < SysCacheSize; cacheId++){SysCache[cacheId] = InitCatCache(cacheId,cacheinfo[cacheId].reloid,cacheinfo[cacheId].indoid,cacheinfo[cacheId].nkeys,cacheinfo[cacheId].key,cacheinfo[cacheId].nbuckets);if (!PointerIsValid(SysCache[cacheId]))elog(ERROR, "could not initialize cache %u (%d)",cacheinfo[cacheId].reloid, cacheId);/* Accumulate data for OID lists, too */SysCacheRelationOid[SysCacheRelationOidSize++] =cacheinfo[cacheId].reloid;SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =cacheinfo[cacheId].reloid;SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =cacheinfo[cacheId].indoid;/* see comments for RelationInvalidatesSnapshotsOnly */Assert(!RelationInvalidatesSnapshotsOnly(cacheinfo[cacheId].reloid));}
...CacheInitialized = true;
}

然后来到catcache.c
InitCatCache会开辟内存,并且放到CacheMemoryContext中管理。它也只是把宏定义的一些oid赋值给对应的catcache,此时还没有open表:

/**		InitCatCache**	This allocates and initializes a cache for a system catalog relation.*	Actually, the cache is only partially initialized to avoid opening the*	relation.  The relation will be opened and the rest of the cache*	structure initialized on the first access.*/
CatCache *
InitCatCache(int id,Oid reloid,Oid indexoid,int nkeys,const int *key,int nbuckets)
{
...oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
...sz = sizeof(CatCache) + PG_CACHE_LINE_SIZE;cp = (CatCache *) CACHELINEALIGN(palloc0(sz));cp->cc_bucket = palloc0(nbuckets * sizeof(dlist_head));/** initialize the cache's relation information for the relation* corresponding to this cache, and initialize some of the new cache's* other internal fields.  But don't open the relation yet.*/cp->id = id;cp->cc_relname = "(not known yet)";cp->cc_reloid = reloid;cp->cc_indexoid = indexoid;cp->cc_relisshared = false; /* temporary */cp->cc_tupdesc = (TupleDesc) NULL;cp->cc_ntup = 0;cp->cc_nbuckets = nbuckets;cp->cc_nkeys = nkeys;for (i = 0; i < nkeys; ++i)cp->cc_keyno[i] = key[i];
...MemoryContextSwitchTo(oldcxt);return cp;
}

id是catcache数组元素的编号,赋值的reloid是已知的cacheinfo中的oid,也赋值了cacheinfo中的key[4],其他信息基本都还不知道,例如relname、tupdesc,因为到这里系统表还没有open。
catcache只有在search的时候才有open的操作,虽然函数名字类似*init*,不过已经不在初始化的过程中了,相关函数不再这里展示。
syscache/catcache初始化完成后,实际上是没有任何元组信息的。

relcache初始化

relcache初始化这篇PostgreSQL内存浅析已经讲的比较好了。
relcache初始化由5个阶段:

  • RelationCacheInitialize - 初始化relcache,初始化为空的
  • RelationCacheInitializePhase2 - 初始化共享的catalog,并加载5个global系统表
  • RelationCacheInitializePhase3 - 完成初始化relcache,并加载4个基础系统表
  • RelationIdGetRelation - 通过relation id获得rel描述
  • RelationClose - 关闭一个relation

其中RelationCacheInitializePhase2 RelationCacheInitializePhase3 都有load系统表,他们有先后顺序的必要。
RelationCacheInitializePhase2有兴趣的可以自行查看函数,也load几个系统表;RelationCacheInitializePhase3 是与我们的问题相关的,我们看这个:

/**		RelationCacheInitializePhase3**		This is called as soon as the catcache and transaction system*		are functional and we have determined MyDatabaseId.  At this point*		we can actually read data from the database's system catalogs.*		We first try to read pre-computed relcache entries from the local*		relcache init file.  If that's missing or broken, make phony entries*		for the minimum set of nailed-in-cache relations.  Then (unless*		bootstrapping) make sure we have entries for the critical system*		indexes.  Once we've done all this, we have enough infrastructure to*		open any system catalog or use any catcache.  The last step is to*		rewrite the cache files if needed.*/
void
RelationCacheInitializePhase3(void)
{
...if (IsBootstrapProcessingMode() ||!load_relcache_init_file(false)){needNewCacheFile = true;formrdesc("pg_class", RelationRelation_Rowtype_Id, false,Natts_pg_class, Desc_pg_class);formrdesc("pg_attribute", AttributeRelation_Rowtype_Id, false,Natts_pg_attribute, Desc_pg_attribute);formrdesc("pg_proc", ProcedureRelation_Rowtype_Id, false,Natts_pg_proc, Desc_pg_proc);formrdesc("pg_type", TypeRelation_Rowtype_Id, false,Natts_pg_type, Desc_pg_type);#define NUM_CRITICAL_LOCAL_RELS 4	/* fix if you change list above */}MemoryContextSwitchTo(oldcxt);/* In bootstrap mode, the faked-up formrdesc info is all we'll have */if (IsBootstrapProcessingMode())return;.../* now write the files */write_relcache_init_file(true);write_relcache_init_file(false);}
}

IsBootstrapProcessingMode其实是专门为bootstrap模式定制的判断,一般的backend是不满足这个条件的。
load_relcache_init_file(false)尝试从initfile中加载系统表信息,load_relcache_init_file(false)传入的是false表示是私有initfile,不是共享initfile:

[postgres@16384]$ pwd
/pgdata/lzl/data15_6879/base/16384
--粗糙一点看。strings会忽略一部分信息,但是表和列名可以看到
[postgres@16384]$ strings pg_internal.init |grep pg_class
pg_class_oid_index
pg_class
pg_class_relname_nsp_index
[postgres@16384]$ strings pg_internal.init |grep -E "pg_class|relname"
pg_class_oid_index
pg_class
relname
relnamespace
pg_class_relname_nsp_index
relname
relnamespace

如果initfile损坏或者没有,那么加载initfile失败进入判断,去load 4个基础系统表:

	//跟2阶段差不多,加载更多的系统表描述if (IsBootstrapProcessingMode() ||!load_relcache_init_file(false)){needNewCacheFile = true;formrdesc("pg_class", RelationRelation_Rowtype_Id, false,Natts_pg_class, Desc_pg_class);formrdesc("pg_attribute", AttributeRelation_Rowtype_Id, false,Natts_pg_attribute, Desc_pg_attribute);formrdesc("pg_proc", ProcedureRelation_Rowtype_Id, false,Natts_pg_proc, Desc_pg_proc);formrdesc("pg_type", TypeRelation_Rowtype_Id, false,Natts_pg_type, Desc_pg_type);

有了pg_class 4个基础表,后面加载系统表信息一切都很简单了

References


  1. 《PostgreSQL内核分析》第2,3章 ↩︎ ↩︎

  2. https://www.postgresql.org/docs/current/system-catalog-declarations.html ↩︎

  3. PostgreSQL内存浅析 ↩︎

相关文章:

PG在还没有pg_class的时候怎么访问基础系统表?

在没有pg_class的时候&#xff0c;数据库怎么访问系统表&#xff1f;这个问题可以分成两个阶段来看&#xff1a; 数据库簇初始化&#xff0c;此时一个database都没有&#xff0c;所以怎么构造和访问pg_class等系统表是一个问题私有内存初始化系统表。PG的系统表信息是放在back…...

UnityHub 无法添加模块问题

文章目录 1.问题描述2.问题解决 1.问题描述 在Hub中无法添加模块 2.问题解决 1、点击设置 2、设置版本安装位置 可以发现installs的安装位置路径设置不是unity安装位置&#xff0c;这里我们更改成自己电脑unity安装位置的上一级路径 添加模块正常&#xff1a;...

python04——类(基础new)

类其实也是一种封装的思想&#xff0c;类就是把变量、方法等封装在一起&#xff0c;然后可以通过不同的实例化对其进行调用操作。 1.类的定义 class 类名&#xff1a; 变量a def __init__ (self,参数2&#xff0c;参数2...)&#xff1a;初始化函数&#xff01;&#xff01;&…...

【Python百日进阶-Web开发-Peewee】Day296 - 查询示例(五)聚合2、递归

文章目录 14.6.13 列出每个指定设施的预订总小时数 List the total hours booked per named facility14.6.14 列出每位会员在 2012 年 9 月 1 日之后的首次预订 List each member’s first booking after September 1st 201214.6.15 生成成员名称列表,每行包含成员总数 Produc…...

闲话银行家舍入法,以及在程序中如何实现

前言 相信对于四舍五入的舍入法&#xff0c;大家都耳熟能详&#xff0c;但对于银行家舍入法&#xff0c;可能就会比较少接触了&#xff01; 可是在金融界&#xff0c;银行家舍入法可是大名鼎鼎的主角之一&#xff0c;主要应用于金融领域和涉及货币计算的场合。 那么&#xf…...

最短路径算法(算法篇)

算法之最短路径算法 最短路径算法 概念&#xff1a; 考查最短路径问题&#xff0c;可能会输入一个赋权图(也就是边带有权的图)&#xff0c;则一条路径的v1v2…vN的值就是对路径的边的权求和&#xff0c;这叫做赋权路径长&#xff0c;如果是无权路径长就是单纯的路径上的边数。…...

昇思25天学习打卡营第11天 | LLM原理和实践:基于MindSpore实现BERT对话情绪识别

1. 基于MindSpore实现BERT对话情绪识别 1.1 环境配置 # 实验环境已经预装了mindspore2.2.14&#xff0c;如需更换mindspore版本&#xff0c;可更改下面mindspore的版本号 !pip uninstall mindspore -y !pip install -i https://pypi.mirrors.ustc.edu.cn/simple mindspore2.2…...

反向散射技术(backscatter communication)

智能反射表面辅助的反向散射通信系统研究综述&#xff08;知网&#xff09; 1 反向散射通信技术优势和应用场景 反向散射通信技术通过被动射频技术发送信号,不需要一定配有主动射频单元,被认为是构建绿色节能、低成本、可灵活部署的未来物联网规模化应用关键技术之一,是实现“…...

致远CopyFile文件复制漏洞

复现版本 V8.0SP2 漏洞范围 V5&G6_V6.1至V8.0SP2全系列版本、V5&G6&N_V8.1至V8.1SP2全系列版本。 漏洞复现 上传文件 POST /seeyon/ajax.do?methodajaxAction&managerNameportalCssManager&rnd57507 HTTP/1.1 Accept: */* Content-Type: applicatio…...

MySQL 创建数据库

MySQL 创建数据库 在当今的数据驱动世界中,数据库是任何应用程序的核心组成部分。MySQL,作为一个流行的开源关系数据库管理系统,因其可靠性、易用性和强大的功能而广受欢迎。本文将详细介绍如何在MySQL中创建数据库,包括基础知识和最佳实践。 什么是MySQL数据库? MySQL…...

AbyssFish单连通周期边界多孔结构2D软件

软件介绍 AbyssFish单连通周期边界多孔结构2D软件&#xff08;以下简称软件&#xff09;可用于生成具备周期性边界条件的单连通域多孔结构PNG图片&#xff0c;软件可设置生成模型的尺寸、孔隙率、孔隙尺寸、孔喉尺寸等参数&#xff0c;并且具备孔隙形态控制功能。 软件生成的…...

Linux驱动开发-03字符设备驱动框架搭建

一、字符设备驱动开发步骤 驱动模块的加载和卸载&#xff08;将驱动编译模块&#xff0c;insmod加载驱动运行&#xff09;字符设备注册与注销&#xff08;我们的驱动实际上是去操作底层的硬件&#xff0c;所以需要向系统注册一个设备&#xff0c;告诉Linux系统&#xff0c;我有…...

Zynq系列FPGA实现SDI视频编解码+图像缩放+多路视频拼接,基于GTX高速接口,提供8套工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐本博已有的 SDI 编解码方案本博已有的FPGA图像缩放方案本方案的无缩放应用本方案在Xilinx--Kintex系列FPGA上的应用 3、详细设计方案设计原理框图SDI 输入设备Gv8601a 均衡器GTX 解串与串化SMPTE SD/HD/3G SDI IP核BT1120转RGB自研…...

VS2019使用C#写窗体程序技巧(1)

1、打开串口 private void button1_Click(object sender, EventArgs e){myPort cmb1.Text;mybaud Convert.ToInt32(cmb2.Text, 10);databit 8;parity Parity.None;stopBit StopBits.One;textBox9.Text "2";try{sp new SerialPort(myPort, mybaud, parity, dat…...

Python爬虫-requests模块

前戏: 1.你是否在夜深人静的时候&#xff0c;想看一些会让你更睡不着的图片却苦于没有资源... 2.你是否在节假日出行高峰的时候&#xff0c;想快速抢购火车票成功..。 3.你是否在网上购物的时候&#xff0c;想快速且精准的定位到口碑质量最好的商品. …...

适用于PyTorch 2.0.0的Ubuntu 22.04上CUDA v11.8和cuDNN 8.7安装指南

将下面内容保存为install.bash&#xff0c;直接用bash执行一把梭解决 #!/bin/bash### steps #### # verify the system has a cuda-capable gpu # download and install the nvidia cuda toolkit and cudnn # setup environmental variables # verify the installation ######…...

使用conda安装openturns

目录 1. 有效方法2. 整体分析使用pip安装使用conda安装验证安装安装过程中可能遇到的问题 1. 有效方法 conda install -c conda-forge openturns2. 整体分析 OpenTURNS是一个用于概率和统计分析的软件库&#xff0c;主要用于不确定性量化。你可以通过以下步骤在Python环境中安…...

Chameleon:动态UI框架使用详解

文章目录 引言Chameleon框架原理核心概念工作流程 基础使用安装与配置创建基础界面 高级使用自定义组件响应式布局数据流与状态管理 结论 引言 Chameleon&#xff0c;作为一种动态UI框架&#xff0c;旨在通过灵活、高效的方式帮助开发者构建跨平台、响应用户交互的图形用户界面…...

7.10飞书一面面经

问题描述 Redis为什么快&#xff1f; 这个问题我遇到过&#xff0c;但是没有好好总结&#xff0c;导致答得很乱。 答&#xff1a;Redis基于内存操作&#xff1a; 传统的磁盘文件操作相比减少了IO&#xff0c;提高了操作的速度。 Redis高效的数据结构&#xff1a;Redis专门设计…...

[数据结构] 归并排序快速排序 及非递归实现

&#xff08;&#xff09;标题&#xff1a;[数据结构] 归并排序&&快速排序 及非递归实现 水墨不写bug &#xff08;图片来源于网络&#xff09; 目录 (一)快速排序 类比递归谋划非递归 快速排序的非递归实现&#xff1a; &#xff08;二&#xff09;归并排序 归…...

Python办公自动化:用PyMuPDF+pdfplumber一键提取PDF文字/图片/表格(附完整代码)

Python办公自动化实战&#xff1a;PyMuPDF与pdfplumber高效提取PDF三要素 每天面对堆积如山的PDF文档&#xff0c;行政和财务人员最头疼的莫过于手动复制粘贴文字、截图保存图片、重新绘制表格。我曾见过一位财务同事为了处理200份供应商报价单&#xff0c;连续加班一周手工录入…...

别再死记硬背了!动态规划解回文问题的填表顺序与状态定义保姆级图解

动态规划解回文问题&#xff1a;从填表顺序到状态定义的思维重塑 第一次接触回文串的动态规划解法时&#xff0c;我盯着那个双重循环的填表顺序发呆了半小时——为什么i要从n-1开始倒着遍历&#xff1f;为什么j又要从i开始正着遍历&#xff1f;更让我困惑的是&#xff0c;dp[i…...

【愚公系列】《剪映+DeepSeek+即梦:短视频制作》026-字幕:用文字来美化画面(美化字幕)

&#x1f48e;【行业认证权威头衔】 ✔ 华为云天团核心成员&#xff1a;特约编辑/云享专家/开发者专家/产品云测专家 ✔ 开发者社区全满贯&#xff1a;CSDN博客&商业化双料专家/阿里云签约作者/腾讯云内容共创官/掘金&亚马逊&51CTO顶级博主 ✔ 技术生态共建先锋&am…...

如何突破极域电子教室限制?3个高效学习工具推荐

如何突破极域电子教室限制&#xff1f;3个高效学习工具推荐 【免费下载链接】JiYuTrainer 极域电子教室防控制软件, StudenMain.exe 破解 项目地址: https://gitcode.com/gh_mirrors/ji/JiYuTrainer 在数字化教学环境中&#xff0c;极域电子教室作为常见的教学管理软件&…...

【AI平台】n8n进阶指南:Docker环境下无缝更新与配置保留实战

1. 为什么需要无缝更新n8n&#xff1f; 如果你正在使用n8n这个强大的工作流自动化工具&#xff0c;肯定会遇到版本更新的问题。作为一个长期使用n8n的开发者&#xff0c;我深刻理解那种"既想用新功能又怕配置丢失"的矛盾心理。每次看到n8n后台的更新提示&#xff0c;…...

LeRobot终极指南:用开源框架零门槛构建智能协作机械臂

LeRobot终极指南&#xff1a;用开源框架零门槛构建智能协作机械臂 【免费下载链接】lerobot &#x1f917; LeRobot: State-of-the-art Machine Learning for Real-World Robotics in Pytorch 项目地址: https://gitcode.com/GitHub_Trending/le/lerobot 副标题&#xf…...

实战剖析:利用EFDD与VeraCrypt破解加密磁盘文件

1. 加密磁盘破解的核心原理 当你面对一个加密的VeraCrypt容器时&#xff0c;第一反应可能是"这数据还能救吗&#xff1f;"。我处理过几十起类似案例&#xff0c;可以明确告诉你&#xff1a;只要获取到内存转储文件&#xff0c;就有很大概率能还原出加密密钥。这里的关…...

免费降AI率和付费降AI率差距有多大?降论文ai率效果实测对比

免费降AI率和付费降AI率差距有多大&#xff1f;降论文ai率效果实测对比 “有没有免费的降AI率工具&#xff1f;” 这是毕业季被问得最多的问题之一。毕竟论文查重已经花了一笔钱&#xff0c;再加上降AI率的费用&#xff0c;对学生来说确实是一笔不小的开支。 但免费降AI率方案真…...

TranslucentTB:打造高效个性化Windows任务栏的3大核心价值与实践指南

TranslucentTB&#xff1a;打造高效个性化Windows任务栏的3大核心价值与实践指南 【免费下载链接】TranslucentTB A lightweight utility that makes the Windows taskbar translucent/transparent. 项目地址: https://gitcode.com/gh_mirrors/tr/TranslucentTB Windows…...

从零开始构建高精度原子间势:LLZO材料训练集避坑指南

从零开始构建高精度原子间势&#xff1a;LLZO材料训练集避坑指南 在材料科学的前沿领域&#xff0c;机器学习势函数正掀起一场静默的革命。想象一下&#xff0c;你能够以前所未有的精度模拟材料的原子级行为&#xff0c;同时避免传统量子力学计算的高昂成本——这正是高精度原子…...