ext4 - mballoc块分配机制
概述
ext4为了尽量避免block管理的碎片化有如此措施:
1.mballoc多块分配器。
- buddy算法管理每个block group
- 采用prellocation机制,氛围per-cpu local preallocation和per inode preallocation
- 小文件和大文件采用不同的策略
- 小文件(具体怎么算小文件可配置)尽量保持在一起,默认应该是512 blocks的一块区域, 采用的是per_cpu locality group,为每个cpu都配置这么一块存放小文件的区域。
- 大文件采用per-inode preallocation方式。
- block分配时,会比请求的分配数量更多,多余的空间会放入preallocation space,这样给write多留些空间,避免concurrent write时候碎片化。
- 计算目标goal phsycial block,尽量保持块分配的连续性。
2.delay allocation。
- delay allocation可以尽可能将连续的申请组织成extent,配置mballoc一次分配连续的多个phsycial block,降低cpu使用率/碎片化。
3.data block优先和其inode在同一个block group中
4.磁盘分成128M的block group
5.同一个目录下的inode优先保存期该目录所在的block group(具体源码在哪里尚未找到,不太确认ext4是否实现)
6.defrag反碎片化工具。
ext4_mb_new_blocks
ext4 mballoc执行phsycial block分配的入口点是ext4_mb_new_blocks:
/** Main entry point into mballoc to allocate blocks* it tries to use preallocation first, then falls back* to usual allocation*/
ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,struct ext4_allocation_request *ar, int *errp)
{struct ext4_allocation_context *ac = NULL;struct ext4_sb_info *sbi;struct super_block *sb;ext4_fsblk_t block = 0;unsigned int inquota = 0;unsigned int reserv_clstrs = 0;u64 seq;might_sleep();sb = ar->inode->i_sb;sbi = EXT4_SB(sb);trace_ext4_request_blocks(ar);.../*主要是检查是否有足够的空间满足分配*///创建一个allocation contextac = kmem_cache_zalloc(ext4_ac_cachep, GFP_NOFS);if (!ac) {ar->len = 0;*errp = -ENOMEM;goto out;}//初始化context*errp = ext4_mb_initialize_context(ac, ar);if (*errp) {ar->len = 0;goto out;}ac->ac_op = EXT4_MB_HISTORY_PREALLOC;seq = this_cpu_read(discard_pa_seq);//优先使用prellcation space分配if (!ext4_mb_use_preallocated(ac)) {ac->ac_op = EXT4_MB_HISTORY_ALLOC;//所谓规范化本质是分配比请求量更大的空间ext4_mb_normalize_request(ac, ar);//初始化ac->pa*errp = ext4_mb_pa_alloc(ac);if (*errp)goto errout;
repeat:/* allocate space in core *///预分配失败,进入常规的分配逻辑*errp = ext4_mb_regular_allocator(ac);/** pa allocated above is added to grp->bb_prealloc_list only* when we were able to allocate some block i.e. when* ac->ac_status == AC_STATUS_FOUND.* And error from above mean ac->ac_status != AC_STATUS_FOUND* So we have to free this pa here itself.*/if (*errp) {ext4_mb_pa_free(ac);ext4_discard_allocated_blocks(ac);goto errout;}if (ac->ac_status == AC_STATUS_FOUND &&ac->ac_o_ex.fe_len >= ac->ac_f_ex.fe_len)ext4_mb_pa_free(ac);}if (likely(ac->ac_status == AC_STATUS_FOUND)) {*errp = ext4_mb_mark_diskspace_used(ac, handle, reserv_clstrs);if (*errp) {ext4_discard_allocated_blocks(ac);goto errout;} else {block = ext4_grp_offs_to_block(sb, &ac->ac_b_ex);ar->len = ac->ac_b_ex.fe_len;}} else {if (ext4_mb_discard_preallocations_should_retry(sb, ac, &seq))goto repeat;/** If block allocation fails then the pa allocated above* needs to be freed here itself.*/ext4_mb_pa_free(ac);*errp = -ENOSPC;}...return block;
}
ext4_allocation_context结构体
struct ext4_allocation_context {struct inode *ac_inode;struct super_block *ac_sb;/* original request */struct ext4_free_extent ac_o_ex;/* goal request (normalized ac_o_ex) */struct ext4_free_extent ac_g_ex;/* the best found extent */struct ext4_free_extent ac_b_ex;/* copy of the best found extent taken before preallocation efforts */struct ext4_free_extent ac_f_ex;__u16 ac_groups_scanned;__u16 ac_found;__u16 ac_tail;__u16 ac_buddy;__u16 ac_flags; /* allocation hints */__u8 ac_status;__u8 ac_criteria;__u8 ac_2order; /* if request is to allocate 2^N blocks and* N > 0, the field stores N, otherwise 0 */__u8 ac_op; /* operation, for history only */struct page *ac_bitmap_page;struct page *ac_buddy_page;struct ext4_prealloc_space *ac_pa;struct ext4_locality_group *ac_lg;
};
上面注释写的非常清晰:
ac_o_ex: 原始请求
ac_g_ex:目标请求,可以跟ac_o_ex不同,比如如注释中说明,ac_g_ex是ac_o_ex经过normalized(对应mballoc::ext4_mb_normalize_request函数处理之后即为ac_g_ex)的结果,ac_b_ex:最终的分配结果,因为ac_g_ex未必能被100%满足
ac_f_ex: ac_b_ex的一份拷贝。
ac_2order: 申请物理block数量如果正好是2的N次方,那么ac_2order = N,否则为0
ac_bitmap_page/ac_buddy_page: 跟mballoc相关的bit位信息,参考ext4 mballoc之buddy算法_nginux的博客-CSDN博客
ac_pa: per-inode预分配
ac_lg: per-cpu预分配,给小文件准备的。
ext4_mb_initialize_context函数
static noinline_for_stack int
ext4_mb_initialize_context(struct ext4_allocation_context *ac,struct ext4_allocation_request *ar)
{struct super_block *sb = ar->inode->i_sb;struct ext4_sb_info *sbi = EXT4_SB(sb);struct ext4_super_block *es = sbi->s_es;ext4_group_t group;unsigned int len;ext4_fsblk_t goal;ext4_grpblk_t block;/* we can't allocate > group size */len = ar->len;/* just a dirty hack to filter too big requests */if (len >= EXT4_CLUSTERS_PER_GROUP(sb))len = EXT4_CLUSTERS_PER_GROUP(sb);/* start searching from the goal */goal = ar->goal;if (goal < le32_to_cpu(es->s_first_data_block) ||goal >= ext4_blocks_count(es))goal = le32_to_cpu(es->s_first_data_block);ext4_get_group_no_and_offset(sb, goal, &group, &block);/* set up allocation goals */ac->ac_b_ex.fe_logical = EXT4_LBLK_CMASK(sbi, ar->logical);ac->ac_status = AC_STATUS_CONTINUE;ac->ac_sb = sb;ac->ac_inode = ar->inode;ac->ac_o_ex.fe_logical = ac->ac_b_ex.fe_logical;ac->ac_o_ex.fe_group = group;ac->ac_o_ex.fe_start = block;ac->ac_o_ex.fe_len = len;//可以看到normalized前ac_g_ex跟ac_o_ex相同ac->ac_g_ex = ac->ac_o_ex;ac->ac_flags = ar->flags;/* we have to define context: we'll work with a file or* locality group. this is a policy, actually */ext4_mb_group_or_file(ac);...return 0;}
首先完成ac_o_ex和 ac_g_ex的赋值工作;然后,ext4_mb_group_or_file函数决定是一个文件到底是小文件和大文件,如概述中描述,ext4针对这两种文件策略不同。
ext4_mb_group_or_file函数
/** We use locality group preallocation for small size file. The size of the* file is determined by the current size or the resulting size after* allocation which ever is larger** One can tune this size via /sys/fs/ext4/<partition>/mb_stream_req*/
static void ext4_mb_group_or_file(struct ext4_allocation_context *ac)
{struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);int bsbits = ac->ac_sb->s_blocksize_bits;loff_t size, isize;if (!(ac->ac_flags & EXT4_MB_HINT_DATA))return;if (unlikely(ac->ac_flags & EXT4_MB_HINT_GOAL_ONLY))return;size = ac->ac_o_ex.fe_logical + EXT4_C2B(sbi, ac->ac_o_ex.fe_len);isize = (i_size_read(ac->ac_inode) + ac->ac_sb->s_blocksize - 1)>> bsbits;if ((size == isize) && !ext4_fs_is_busy(sbi) &&!inode_is_open_for_write(ac->ac_inode)) {ac->ac_flags |= EXT4_MB_HINT_NOPREALLOC;return;}//s_mb_group_prealloc是给小文分配的per-cpu local group空间大小,如果<=0//就设置EXT4_MB_STREAM_ALLOC,不适用小文件分配策略if (sbi->s_mb_group_prealloc <= 0) {ac->ac_flags |= EXT4_MB_STREAM_ALLOC;return;}/* don't use group allocation for large files *///s_mb_stream_request值来自于/sys/fs/ext4/xxx/mb_stream_req,文件大小大于了该值//为大文件,否则为小文件size = max(size, isize);if (size > sbi->s_mb_stream_request) {ac->ac_flags |= EXT4_MB_STREAM_ALLOC;return;}BUG_ON(ac->ac_lg != NULL);/** locality group prealloc space are per cpu. The reason for having* per cpu locality group is to reduce the contention between block* request from multiple CPUs.*/ac->ac_lg = raw_cpu_ptr(sbi->s_locality_groups);/* we're going to use group allocation *///如果进行到这里,说明是小文件ac->ac_flags |= EXT4_MB_HINT_GROUP_ALLOC;/* serialize all allocations in the group */mutex_lock(&ac->ac_lg->lg_mutex);
}
ext4_prealloc_space结构体
struct ext4_prealloc_space {//如果是per-inode preallocation挂在ext4_inode_info的i_prealloc_list//如果是per_cpu locality group预分配空间挂在ext4_locality_group的lg_prealloc_list链表上struct list_head pa_inode_list;//预分配空间同时也会挂在ext4_group_info的bb_prealloc_list链表上,//用于初始化buddy bitmap的之 前给block bitmap置上对应的已使用标记struct list_head pa_group_list;union {struct list_head pa_tmp_list;struct rcu_head pa_rcu;} u;spinlock_t pa_lock;atomic_t pa_count;//预分配空间是否已删除unsigned pa_deleted;//起始物理块号ext4_fsblk_t pa_pstart; /* phys. block *///起始逻辑块号(相对于文件)ext4_lblk_t pa_lstart; /* log. block *///预分配空间长度(单位是block)ext4_grpblk_t pa_len; /* len of preallocated chunk *///空间的可用长度ext4_grpblk_t pa_free; /* how many blocks are free *///类型,indode or groupunsigned short pa_type; /* pa type. inode or group */spinlock_t *pa_obj_lock;struct inode *pa_inode; /* hack, for history only */
};
ext4_locality_group结构体
/** Locality group:* we try to group all related changes together* so that writeback can flush/allocate them together as well* Size of lg_prealloc_list hash is determined by MB_DEFAULT_GROUP_PREALLOC* (512). We store prealloc space into the hash based on the pa_free blocks* order value.ie, fls(pa_free)-1;*/
#define PREALLOC_TB_SIZE 10
struct ext4_locality_group {/* for allocator *//* to serialize allocates */struct mutex lg_mutex;/* list of preallocations */// 挂ext4_prealloc_space的链表,按照预分配空间的可用长度进行分组struct list_head lg_prealloc_list[PREALLOC_TB_SIZE];spinlock_t lg_prealloc_lock;
};
ext4_mb_use_preallocated函数
函数判定能否使用preallocation space分配block,优先使用per-inode preallocation预分配空间;如果失败,再判断是否是小文件能使用per-cpu local group preallocation预分配空间;如果任何一个预分配空间分配成功,return true;否者return false代表无法使用预分配空间。
/** search goal blocks in preallocated space*/
static noinline_for_stack bool
ext4_mb_use_preallocated(struct ext4_allocation_context *ac)
{struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);int order, i;struct ext4_inode_info *ei = EXT4_I(ac->ac_inode);struct ext4_locality_group *lg;struct ext4_prealloc_space *pa, *cpa = NULL;ext4_fsblk_t goal_block;/* only data can be preallocated *///linux一切皆文件,只要普通文件才使用预分配,EXT4_MB_HINT_DATA是ext4_ext_map_blocks//中根据如下条件设置 if (S_ISREG(inode->i_mode)) ar.flags = EXT4_MB_HINT_DATA; if (!(ac->ac_flags & EXT4_MB_HINT_DATA))return false;/* first, try per-file preallocation */rcu_read_lock();list_for_each_entry_rcu(pa, &ei->i_prealloc_list, pa_inode_list) {/* all fields in this condition don't change,* so we can skip locking for them *///不在这个预分配空间范围内,跳到下一个预分配空间if (ac->ac_o_ex.fe_logical < pa->pa_lstart ||ac->ac_o_ex.fe_logical >= (pa->pa_lstart +EXT4_C2B(sbi, pa->pa_len)))continue;/* non-extent files can't have physical blocks past 2^32 */if (!(ext4_test_inode_flag(ac->ac_inode, EXT4_INODE_EXTENTS)) &&(pa->pa_pstart + EXT4_C2B(sbi, pa->pa_len) >EXT4_MAX_BLOCK_FILE_PHYS))continue;/* found preallocated blocks, use them *///找到了合适的预分配空间spin_lock(&pa->pa_lock);if (pa->pa_deleted == 0 && pa->pa_free) {atomic_inc(&pa->pa_count);ext4_mb_use_inode_pa(ac, pa);spin_unlock(&pa->pa_lock);ac->ac_criteria = 10;rcu_read_unlock();return true;}spin_unlock(&pa->pa_lock);}rcu_read_unlock();//走到这里说明per-inode没有分配成功,需要判定能否是小文件走per-cpu local group分配/* can we use group allocation? */if (!(ac->ac_flags & EXT4_MB_HINT_GROUP_ALLOC))return false;/* inode may have no locality group for some reason */lg = ac->ac_lg;if (lg == NULL)return false;order = fls(ac->ac_o_ex.fe_len) - 1;if (order > PREALLOC_TB_SIZE - 1)/* The max size of hash table is PREALLOC_TB_SIZE */order = PREALLOC_TB_SIZE - 1;goal_block = ext4_grp_offs_to_block(ac->ac_sb, &ac->ac_g_ex);/** search for the prealloc space that is having* minimal distance from the goal block.*/for (i = order; i < PREALLOC_TB_SIZE; i++) {rcu_read_lock();list_for_each_entry_rcu(pa, &lg->lg_prealloc_list[i],pa_inode_list) {spin_lock(&pa->pa_lock);if (pa->pa_deleted == 0 &&pa->pa_free >= ac->ac_o_ex.fe_len) {cpa = ext4_mb_check_group_pa(goal_block,pa, cpa);}spin_unlock(&pa->pa_lock);}rcu_read_unlock();}if (cpa) {//小文件预分配空间分配成功ext4_mb_use_group_pa(ac, cpa);ac->ac_criteria = 20;return true;}return false;
}
ext4_mb_normalize_request
预分配空间分配失败就会进入ext4_mb_normalize_request,如代码注释所谓的normalize是考虑申请更合适的大小,一般会大于等于request size.
ext4_mb_regular_allocator
这个函数是mballoc buddy分配算法的核心函数,涉及的内容非常多,后面专门放到一篇文章分析
参考文章:
https://www.cnblogs.com/kanie/p/15359346.html
相关文章:

ext4 - mballoc块分配机制
概述 ext4为了尽量避免block管理的碎片化有如此措施: 1.mballoc多块分配器。 buddy算法管理每个block group采用prellocation机制,氛围per-cpu local preallocation和per inode preallocation 小文件和大文件采用不同的策略小文件(具体怎么…...

Spring整合junit
1、导入pom坐标 <dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><dependency><groupId>org.springframework</gro…...

Swift 让ScrollView滚动到具体某个位置
1. 使用scrollToItem方法滚动集合视图 DispatchQueue.main.asyncAfter(deadline: .now() 0.1) {let firstIndexPath IndexPath(item: 0, section: 0)let lastIndexPath IndexPath(item: self.recordArray.count - 1, section: 0)// Scroll to first itemself.collectionVie…...

【C语言day08】
int n5; int a[n][n2] 数组定义下角标不能为变量 注:C99标准中支持了使用变量本题考查的是二维数组的元素访问,A选项是 正确的,X[i]就是第i行的数组名,数组名表示首元素的地址,X[i]表示第i行的第一个元素的地址&#…...

【并发编程】ThreadLocal
从名字我们就可以看到 ThreadLocal 叫做线程变量,意思是 ThreadLocal 中填充的变量属于当前线程,该变量对其他线程而言是隔离的。 ThreadLocal 为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。 static ThreadL…...

如何提高自己的软件测试水平之bug定位
同学们在面试投简历的时候会经常看到人家公司JD上写的要求之一,如下: 这句话大家不要以为随便写写的,在我工作的十几年过程中起码见过10个以上试用期没过的公司新人,公司在衡量一个测试工程师是否专业的标准之一就是:…...

发点实用的快捷键(mac
切换输入法:ctrlspace /ctrloptionspace(更快捷 切换网页: shifttab 切换应用界面:alttab 关闭页面:altw 搜索:altspace 展示mac隐藏文件: Commangshift . (点) 以下是一些浏览器快捷键&am…...

Android播放多媒体文件——播放音频
以下内容摘自郭霖《第一行代码》第三版 播放音频 MediaPlayer类中常用的控制方法 方法名功能描述setDataSource()设置要播放的音频文件的位置prepare()在开始播放之前调用,以完成准备工作start()开始或继续播放音频pause()暂停播放音频reset()将MediaPlayer对象重…...

存储重启后,ceph挂载信息没了,手动定位osd序号并挂载到对应磁盘操作流程、ceph查看不到osd信息处理方法
文章目录 故障说明处理流程定位硬盘中的osd序号挂载osd到ceph上验证并拉起osd重复上面操作故障说明 我们的一个存储节点莫名其妙的重启了,不知道咋回事 但这样的问题就是,所有osd都down了 因为挂载信息没有写到fstab里面,所以不会自动up,并且没有挂载信息,并且也看不到o…...

Linux学习之循环处理位置参数
for处理位置参数 loopPositionFor.sh里边的内容如下: #!/bin/bash# show learningfor inputString in $* doif [ "${inputString}" "good" ];thenecho "learning"fi donechmod urx loopPositionFor.sh给当前用户把loopPositionFor…...

NLP实战8:图解 Transformer笔记
目录 1.Transformer宏观结构 2.Transformer结构细节 2.1输入 2.2编码部分 2.3解码部分 2.4多头注意力机制 2.5线性层和softmax 2.6 损失函数 3.参考代码 🍨 本文为[🔗365天深度学习训练营]内部限免文章(版权归 *K同学啊* 所有&#…...

Pytorch个人学习记录总结 玩俄罗斯方块の深度学习小项目
目录 前言 模型成果演示 训练过程演示 代码实现 deep_network tetris test train 前言 当今,深度学习在各个领域展现出了惊人的应用潜力,而游戏开发领域也不例外。俄罗斯方块作为经典的益智游戏,一直以来深受玩家喜爱。在这个项目中&…...

PuTTY连接服务器报错Connection refused
天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…...

11-3_Qt 5.9 C++开发指南_QSqlQuery的使用(QSqlQuery 是能执行任意 SQL 语句的类)
文章目录 1. QSqlQuery基本用法2. QSqlQueryModel和QSqlQuery联合使用2.1 可视化UI设计框架2.1.1主窗口的可视化UI设计框架2.1.2 对话框的可视化UI设计框架 2.2 数据表显示2.3 编辑记录对话框2.4 编辑记录2.5 插入记录2.6 删除记录2.7 记录遍历2.8 程序框架及源码2.8.1 程序整体…...

神码ai火车头伪原创插件怎么用【php源码】
大家好,本文将围绕python绘制烟花特定爆炸效果展开说明,如何用python画一朵花是一个很多人都想弄明白的事情,想搞清楚用python画烟花的代码需要先了解以下几个事情。 1、表白烟花代码 天天敲代码的朋友,有没有想过代码也可以变得…...

13.Netty源码之Netty中的类与API
highlight: arduino-light ServerBootstrap Bootstrap 意思是引导,一个 Netty 应用通常由一个 Bootstrap 开始,主要作用是配置整个 Netty 程序,串联各个组件,Netty 中ServerBootstrap 是服务端启动引导类。 java //泛型 AbstractB…...

C# 如何检查数组列表中是否存在数组
原文:https://www.coder.work/article/2958674 列表: 一个数组列表,想检查一个确切的数组是否在列表中 List<int[]> Output new List<int[]>(); 有一个数组 int[] coordinates 想检查coordinates 数组是否在Output 列表中&…...

AI课堂教学质量评估系统算法 yolov7
AI课堂教学质量评估系统通过yolov7网络模型框架利用摄像头和人脸识别技术,AI课堂教学质量评估系统实时监测学生的上课表情和课堂行为。同时,还结合语音识别技术和听课专注度分析算法,对学生的听课专注度进行评估,生成教学质量报告…...

eventBus使用遇到的坑
**问题:**通过eventBus传递的参数,在子组件的methods中无法通过this.使用。 **思路:**考虑组件方法的执行顺序(vue生命周期执行顺序) **解决办法:**在传递参数的组件外 this.$nextTick this.$nextTick(() …...

ChatGPT应用|科大讯飞星火杯认知大模型场景创新赛开始报名了!
ChatGPT发布带来的 AI 浪潮在全球疯狂蔓延,国内掀起的大模型混战已经持续半年之久,国产大模型数量正以惊人的速度增长,据不完全统计,截止7月14号已经达到了111个,所谓的“神仙打架”不过如此了吧。 ( 包括但…...

DM8 DSC备份还原
1、检查磁盘空间 检查服务器磁盘空间使用情况,确认磁盘有充足的空间存放物理备份。 查看磁盘空间使用情况(备份在端点0,此处检查端点0) su - dmdba [dmdbacentos-04 ~]$ df -h 文件系统 容量 已用 可用 已用% …...

【Docker--harbor私有仓库部署与管理】
目录 一、Harbor 部署1. 部署 Docker-Compose 服务2. 部署 Harbor 服务(1)下载或上传 Harbor 安装程序(2)修改harbor安装的配置文件 3. 启动 Harbor4. 查看 Harbor 启动镜像5. 创建一个新项目1、在虚拟上进行登录 Harbor2、下载镜…...

基于量子同态加密的安全多方凸包协议
摘要安全多方计算几何(SMCG)是安全多方计算的一个分支。该协议是为SMCG中安全的多方凸包计算而设计的。首先,提出了一种基于量子同态加密的安全双方值比较协议。由于量子同态加密的性质,该协议可以很好地保护量子电路执行过程中数据的安全性和各方之间的…...

MySQL案例——多表查询以及嵌套查询
系列文章目录 MySQL笔记——表的修改查询相关的命令操作 MySQL笔记——MySQL数据库介绍以及在Linux里面安装MySQL数据库,对MySQL数据库的简单操作,MySQL的外接应用程序使用说明 文章目录 系列文章目录 前言 一 创建数据库 1.1 创建一个部门表 1.…...

AI 视频清晰化CodeFormer-Deepfacelab
CodeFormer 概述 (a) 我们首先学习一个离散码本和一个解码器,通过自重建学习来存储人脸图像的高质量视觉部分。(b) 使用固定的码本和解码器,我们引入了一个用于代码序列预测的 Transformer 模块,对低质量输入的全局人脸组成进行建模。此外&a…...

TCP协议如何实现可靠传输
TCP最主要的特点 TCP是面向连接的运输层协议,在无连接的、不可靠的IP网络服务基础之上提供可靠交付的服务。为此,在IP的数据报服务基础之上,增加了保证可靠性的一系列措施。 TCP最主要的特点: TCP是面向连接的输出层协议 每一条…...

万恶的Eclipse的使用
恨啊!公司用eclipse,这种千年老古董又被翻出来了,我的idea,我的宝,我想你! 下面是总结的各种eclipse的使用技巧: 让eclipse像idea一样使用 .sout eclipse设置自动保存代码(图文&…...

文件上传--题目
之前有在技能树中学过文件上传,正好借这次进行一个整合: 技能树中所包含的题目类型有 无限制绕过 1.上传一句话木马 2.链接中国蚁剑 前端验证 1.会发现这个网站不让提交php,改后缀为jpg格式,再用burp抓包 2.在用中国蚁剑连接 .…...

小程序创建
1,下载HBuilder X ;(3.8.7) HBuilderX-高效极客技巧 2,下载模板(不选云服务的); 3,运行-运行到小程序模拟器; 4,安装小程序开发工具; 5,选择稳定版-windows64版&…...

stable diffusion如何确保每张图的面部一致?
可以使用roop插件,确定好脸部图片后,使用roop固定,然后生成的所有图片都使用同一张脸。 这款插件的功能简单粗暴:一键换脸。 如图所示: 任意上传一张脸部清晰的图片,点击启用。 在其他提示词不变的情况下…...