Slab,不连续页,buddy分配器与内存映射

Slab分配器分析

一、Slab分配器概述

1.1 Slab分配器的作用

Slab分配器是Linux内核中用于管理小对象内存分配的高效机制。它主要解决以下问题:

  • 频繁分配/释放小对象的性能问题:内核中大量使用固定大小的对象(如task_struct、inode、dentry等),频繁的分配和释放会导致性能下降
  • 内存碎片问题:直接使用Buddy分配器分配小对象会造成严重的内部碎片
  • 对象初始化开销:通过缓存已构造的对象,避免重复的初始化操作
  • 缓存行对齐:提高CPU缓存利用率,减少伪共享

1.2 Slab分配器的设计理念

  1. 对象缓存(Object Cache):为经常使用的数据结构类型创建专用缓存
  2. 构造/析构函数:对象可以预先构造,使用后不立即销毁而是放回缓存
  3. Per-CPU缓存:减少多处理器系统中的锁竞争
  4. 着色(Coloring):通过偏移量优化CPU缓存利用

1.3 Slab分配器的实现变体

Linux内核中有三种Slab分配器实现:

  • SLAB:原始实现,功能完整但较复杂
  • SLUB:简化版本,是当前主流实现(默认)
  • SLOB:面向小型嵌入式系统的轻量级实现

二、Slab分配器的核心数据结构

2.1 kmem_cache结构

structkmem_cache{structkmem_cache_cpu__percpu*cpu_slab;/* Per-CPU缓存 */unsignedlongflags;/* 分配标志 */unsignedlongmin_partial;/* 部分空闲slab的最小数量 */intsize;/* 对象大小 */intobject_size;/* 实际对象大小(不含元数据) */intoffset;/* 空闲指针的偏移量 */intcpu_partial;/* Per-CPU部分空闲slab数量限制 */structkmem_cache_order_objectsoo;/* 对象和阶数 */structkmem_cache_order_objectsmax;/* 最大对象和阶数 */structkmem_cache_order_objectsmin;/* 最小对象和阶数 */gfp_tallocflags;/* 传递给Buddy系统的分配标志 */intrefcount;/* 引用计数 */void(*ctor)(void*);/* 对象构造函数 */constchar*name;/* 缓存名称 */structlist_headlist;/* 缓存链表 */structkmem_cache_node*node[MAX_NUMNODES];/* NUMA节点 */};

2.2 Slab页结构

structpage{unsignedlongflags;/* 页标志 */union{struct{structlist_headlru;/* 用于链接到各种链表 */structkmem_cache*slab_cache;/* 指向所属的kmem_cache */void*freelist;/* 空闲对象链表 */union{struct{unsignedinuse:16;/* 已使用对象数 */unsignedobjects:15;/* 总对象数 */unsignedfrozen:1;/* 是否冻结(Per-CPU使用) */};atomic_t_refcount;};};};};

2.3 Per-CPU缓存结构

structkmem_cache_cpu{void**freelist;/* 指向下一个可用对象 */unsignedlongtid;/* 事务ID,用于无锁操作 */structpage*page;/* 当前正在使用的slab */structpage*partial;/* 部分空闲的slab链表 */};

三、Slab分配器的工作原理

3.1 三级缓存结构

Slab分配器采用三级缓存架构:

┌─────────────────────────────────────────┐ │ 1. Per-CPU快速路径 │ │ ┌─────────────┐ ┌─────────────┐ │ │ │ CPU 0 Slab │ │ CPU 1 Slab │ │ │ │ freelist │ │ freelist │ │ │ └─────────────┘ └─────────────┘ │ └─────────────────────────────────────────┘ ↓ 缓存未命中 ┌─────────────────────────────────────────┐ │ 2. Per-CPU部分空闲Slab链表 │ │ (cpu_slab->partial) │ └─────────────────────────────────────────┘ ↓ 仍未命中 ┌─────────────────────────────────────────┐ │ 3. Per-Node部分空闲Slab链表 │ │ (kmem_cache_node->partial) │ └─────────────────────────────────────────┘ ↓ 仍未命中 ┌─────────────────────────────────────────┐ │ 4. 从Buddy系统分配新Slab │ └─────────────────────────────────────────┘

3.2 对象分配流程

快速路径(Fast Path)
static__always_inlinevoid*slab_alloc(structkmem_cache*s,gfp_tgfpflags){void**object;structkmem_cache_cpu*c;unsignedlongtid;/* 1. 禁用抢占,获取Per-CPU缓存 */c=this_cpu_ptr(s->cpu_slab);tid=c->tid;barrier();/* 2. 快速路径:直接从freelist获取对象 */object=c->freelist;if(unlikely(!object||!node_match(c,node)))gotoslow_path;/* 3. 更新freelist指针 */c->freelist=get_freepointer(s,object);c->tid=next_tid(tid);/* 4. 返回对象 */returnobject;slow_path:return__slab_alloc(s,gfpflags,node,addr,c);}
慢速路径(Slow Path)
staticvoid*__slab_alloc(structkmem_cache*s,gfp_tgfpflags,intnode){void*freelist;structpage*page;/* 1. 尝试从Per-CPU部分空闲链表获取 */page=c->page;if(!page)gotonew_slab;/* 2. 重新加载freelist */freelist=c->freelist;if(freelist)returnfreelist;/* 3. 从Per-CPU partial链表获取 */page=c->partial;if(page){c->page=page;c->freelist=get_freepointer(s,page->freelist);returnpage->freelist;}new_slab:/* 4. 从Per-Node partial链表获取或分配新slab */page=get_partial(s,node);if(!page){/* 5. 从Buddy系统分配新页面 */page=new_slab(s,gfpflags,node);if(!page)returnNULL;}c->page=page;returnpage->freelist;}

3.3 对象释放流程

static__always_inlinevoidslab_free(structkmem_cache*s,structpage*page,void*object){void**object_ptr=object;structkmem_cache_cpu*c;unsignedlongtid;/* 1. 获取Per-CPU缓存 */c=this_cpu_ptr(s->cpu_slab);tid=c->tid;/* 2. 快速路径:将对象插入freelist */if(likely(page==c->page)){set_freepointer(s,object,c->freelist);c->freelist=object;c->tid=next_tid(tid);return;}/* 3. 慢速路径:处理其他情况 */__slab_free(s,page,object);}

3.4 Slab着色技术

着色技术通过在slab中添加偏移量,使不同slab中的对象映射到不同的CPU缓存行:

Slab 1: [偏移0] [对象1][对象2][对象3]... Slab 2: [偏移32][对象1][对象2][对象3]... Slab 3: [偏移64][对象1][对象2][对象3]...

这样可以减少多个slab对象竞争同一缓存行的情况。

四、Slab分配器与Buddy分配器的关系

4.1 层次关系

┌─────────────────────────────────────────────┐ │ 用户空间内存分配请求 │ └─────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────┐ │ 内核内存分配接口 (kmalloc/kfree) │ └─────────────────────────────────────────────┘ ↓ ┌───────────────────────┐ │ 小对象 (<2页) │ └───────────────────────┘ ↓ ┌─────────────────────────────────────────────┐ │ Slab分配器 (kmem_cache) │ │ - 对象缓存管理 │ │ - Per-CPU快速分配 │ │ - 减少碎片 │ └─────────────────────────────────────────────┘ ↓ 需要分配新slab时 ↓ ┌─────────────────────────────────────────────┐ │ Buddy分配器 (alloc_pages) │ │ - 以页为单位分配 │ │ - 2的幂次方大小 │ │ - 管理物理内存页 │ └─────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────┐ │ 物理内存页框 │ └─────────────────────────────────────────────┘

4.2 依赖关系

Slab分配器是建立在Buddy分配器之上的:

  1. 页面来源:Slab分配器通过调用alloc_pages()从Buddy系统获取页面
  2. 分配单位:通常分配1-2个连续页面作为一个slab
  3. 回收机制:当slab完全空闲时,通过__free_pages()归还页面给Buddy系统
/* Slab分配器向Buddy系统请求页面 */staticstructpage*allocate_slab(structkmem_cache*s,gfp_tflags,intnode){structpage*page;intorder;/* 计算需要的页面阶数 */order=oo_order(s->oo);/* 从Buddy系统分配连续页面 */page=alloc_pages_node(node,flags|__GFP_COMP,order);if(!page)returnNULL;/* 初始化slab页面 */__SetPageSlab(page);page->slab_cache=s;returnpage;}

4.3 性能优势对比

特性Buddy分配器Slab分配器
分配粒度页(4KB倍数)字节级
分配速度相对较慢(需要遍历链表)非常快(Per-CPU无锁)
内存碎片外部碎片内部碎片小
缓存效应对象预构造、缓存行优化
适用场景大块内存分配小对象频繁分配
并发性能需要自旋锁保护Per-CPU无锁快速路径

4.4 协作机制

/* 示例:kmalloc的实现 */void*kmalloc(size_tsize,gfp_tflags){/* 1. 小于2页的分配走Slab */if(size<=KMALLOC_MAX_CACHE_SIZE){structkmem_cache*s=kmalloc_slab(size,flags);returnkmem_cache_alloc(s,flags);// 使用Slab}/* 2. 大于2页的分配直接走Buddy */returnkmalloc_large(size,flags);// 使用Buddy}/* 大对象直接使用Buddy分配器 */void*kmalloc_large(size_tsize,gfp_tflags){unsignedintorder=get_order(size);structpage*page=alloc_pages(flags,order);// 直接调用Buddyreturnpage?page_address(page):NULL;}

五、Slab分配器与不连续页分配器(vmalloc)的关系

5.1 内存区域划分

内核地址空间布局(x86-64): ┌────────────────────────────────────┐ 0xFFFFFFFF FFFFFFFF │ 内核代码段 & 数据段 │ ├────────────────────────────────────┤ │ 直接映射区(线性映射) │ <- Slab和Buddy在此区域 │ - 物理内存连续映射 │ │ - 虚拟地址连续 = 物理地址连续 │ ├────────────────────────────────────┤ VMALLOC_START │ vmalloc区域(非连续映射) │ <- vmalloc在此区域 │ - 物理内存不连续 │ │ - 虚拟地址连续 ≠ 物理地址连续 │ ├────────────────────────────────────┤ VMALLOC_END │ 其他内核区域 │ └────────────────────────────────────┘

5.2 核心区别

特性Slab分配器vmalloc分配器
物理内存必须连续可以不连续
虚拟内存连续连续
内存区域直接映射区vmalloc区域
页表操作不需要(已映射)需要建立页表映射
TLB影响小(使用大页)大(使用小页)
分配速度慢(需要页表操作)
适用大小小对象大块内存
DMA支持支持不支持(物理不连续)

5.3 vmalloc的实现原理

void*vmalloc(unsignedlongsize){/* 1. 在vmalloc区域分配虚拟地址空间 */structvm_struct*area=get_vm_area(size,VM_ALLOC);if(!area)returnNULL;/* 2. 逐页从Buddy系统分配物理页面(不要求连续) */for(i=0;i<nr_pages;i++){page=alloc_page(GFP_KERNEL);// 从Buddy分配单页if(!page)gotofail;pages[i]=page;}/* 3. 建立虚拟地址到物理页面的映射(修改页表) */if(map_vm_area(area,PAGE_KERNEL,pages))gotofail;returnarea->addr;}

5.4 三者的协作关系

┌──────────────────────────────────────────────┐ │ 内核内存分配需求 │ └──────────────────────────────────────────────┘ ↓ ┌───────────┴───────────┬──────────────┐ ↓ ↓ ↓ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ 小对象 │ │ 中等对象 │ │ 大对象 │ │ <2KB │ │ 2KB-128KB │ │ >128KB │ └──────────────┘ └──────────────┘ └──────────────┘ ↓ ↓ ↓ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ Slab分配器 │ │ Slab/Buddy │ │ vmalloc │ │ - 对象缓存 │ │ - 直接分配 │ │ - 不连续页 │ │ - Per-CPU │ │ │ │ - 页表映射 │ └──────────────┘ └──────────────┘ └──────────────┘ ↓ ↓ ↓ └───────────┬───────┴──────────────────┘ ↓ ┌───────────────────────┐ │ Buddy分配器 │ │ - 提供物理页面 │ └───────────────────────┘ ↓ ┌───────────────────────┐ │ 物理内存 │ └───────────────────────┘

5.5 使用场景对比

Slab分配器适用于:

  • 频繁分配/释放的小对象(如task_struct、inode)
  • 需要高性能的场景
  • 需要DMA的场景
  • 对象大小固定或变化不大

vmalloc分配器适用于:

  • 大块内存分配(>128KB)
  • 不需要物理连续的场景
  • 模块加载(内核模块代码段)
  • 不关心性能的临时缓冲区
  • 物理内存碎片严重时

5.6 性能影响分析

/* 测试示例:分配1MB内存的性能对比 *//* 方式1:使用kmalloc(通过Buddy,要求物理连续) */void*buf1=kmalloc(1024*1024,GFP_KERNEL);// 优点:访问快(TLB友好,可能使用大页)// 缺点:可能因内存碎片而失败/* 方式2:使用vmalloc(物理不连续) */void*buf2=vmalloc(1024*1024);// 优点:不易失败(物理内存不需要连续)// 缺点:访问慢(TLB miss多,页表遍历)

六、通用缓存(kmalloc)的实现

6.1 kmalloc缓存层次

内核预先创建了一系列大小递增的Slab缓存:

staticstructkmem_cache*kmalloc_caches[KMALLOC_SHIFT_HIGH+1];/* 缓存大小: */// kmalloc-8, kmalloc-16, kmalloc-32, kmalloc-64,// kmalloc-96, kmalloc-128, kmalloc-192, kmalloc-256,// kmalloc-512, kmalloc-1024, kmalloc-2048, kmalloc-4096, kmalloc-8192

6.2 大小选择算法

static__always_inlinestructkmem_cache*kmalloc_slab(size_tsize,gfp_tflags){unsignedintindex;if(size<=192)index=size_index[size_index_elem(size)];elseindex=fls(size-1);// 找到最高位returnkmalloc_caches[index];}

七、Slab分配器的调试与统计

7.1 查看slab信息

# 查看所有slab缓存的统计信息cat/proc/slabinfo# 示例输出:# slabinfo - version: 2.1# name <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab># task_struct 256 280 4352 1 1# mm_struct 180 200 1024 4 1# dentry 32000 32500 192 42 2

7.2 sysfs接口

# 查看特定缓存的详细信息ls/sys/kernel/slab/kmalloc-1024/# 输出包括:# - objects: 对象总数# - object_size: 对象大小# - slabs: slab数量# - cpu_slabs: Per-CPU slab数量# - partial: 部分空闲slab数量

7.3 内存泄漏检测

启用CONFIG_DEBUG_SLAB或CONFIG_SLUB_DEBUG可以跟踪对象分配:

/* 启用调试后可以使用 */echo1>/sys/kernel/slab/<cache_name>/trace

八、总结

8.1 三种分配器的关系总结

内核内存管理层次结构 ┌─────────────────────────────────────────────┐ │ 高层接口(API) │ │ kmalloc/kfree | vmalloc/vfree │ └─────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────┐ │ 中间层(对象管理) │ │ │ │ ┌─────────────┐ ┌──────────────┐ │ │ │ Slab分配器 │ │ vmalloc管理 │ │ │ │ - 对象缓存 │ │ - 虚拟区域 │ │ │ │ - Per-CPU │ │ - 页表映射 │ │ │ └─────────────┘ └──────────────┘ │ └─────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────┐ │ 底层(页框管理) │ │ Buddy分配器 │ │ - 伙伴系统算法 │ │ - 以页为单位 │ │ - 2的幂次方分配 │ └─────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────┐ │ 物理内存(RAM) │ └─────────────────────────────────────────────┘

8.2 选择建议

  • 小对象(<2KB):使用kmalloc(底层Slab)
  • 中等对象(2KB-128KB):使用kmalloc(底层Buddy)
  • 大对象(>128KB)或可接受不连续:使用vmalloc
  • 特定类型对象频繁分配:创建专用kmem_cache
  • 需要DMA:必须使用kmalloc或直接使用Buddy(保证物理连续)

8.3 关键要点

  1. Slab是Buddy的上层:Slab通过Buddy获取页面,在页面上实现对象级管理
  2. vmalloc与Slab并列:两者都使用Buddy,但服务不同场景
  3. 性能排序:Slab > Buddy > vmalloc
  4. 连续性要求:Slab和Buddy保证物理连续,vmalloc不保证
  5. 适用场景不同:根据对象大小、频率、连续性需求选择合适的分配器

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

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

相关文章

物理内存组织架构与Buddy分配器关系分析

物理内存组织架构与Buddy分配器关系分析 在Linux内核中&#xff0c;物理内存的管理是一个分层级的复杂系统。为了高效地应对不同硬件架构&#xff08;如NUMA&#xff09;和不同的内存需求&#xff08;如DMA访问限制&#xff09;&#xff0c;Linux建立了严密的物理内存组织架构…

【数据分享】2025年全国范围各城市的公交路线及站点数据(分省/分城市)

本文分享一份2025年全国范围各城市的路线及站点数据。包含&#xff1a;安徽省、澳门、北京市、重庆市、福建省、甘肃省、广东省、广西省、贵州省、海南省、河北省、河南省、黑龙江、湖北省、湖南省、吉林省、江苏省、江西省、辽宁省、内蒙古、宁夏省、青海省、山东省、山西省、…

Agent2Agent (A2A) Protocol( A2A 协议)简介、组件

Agent2Agent (A2A) Protocol&#xff08;简称 A2A 协议&#xff09;是旨在让不同 AI 代理&#xff08;agents&#xff09;之间互联互通、协作的开放标准。内容包括协议的主要组件&#xff08;building blocks&#xff09;、各组件作用&#xff0c;以及这些组件在一个典型流程中…

期货反向跟单—从小白到高手进阶历程 六十三(研究人性不是重点)

在期货反向跟单领域&#xff0c;“研究人性” 似乎成了多数团队的共识性动作。不少团队投入大量人力、物力搭建心理干预体系&#xff0c;从资金奖惩机制到每日口头引导&#xff0c;试图通过干预盘手的心理状态来优化跟单效果。然而现实往往事与愿违&#xff0c;多数团队耗费数月…

系列教程十三 | 探索阿里云 Wan 2.1:零基础入门文本生成视频教程

一.背景介绍近年来&#xff0c;人工智能内容生成&#xff08;AIGC&#xff09;在视频创作领域取得了突破性进展&#xff0c;其中文本到视频&#xff08;Text-to-Video&#xff09;生成技术因其在内容创作、广告营销和教育可视化等方面的巨大潜力而备受关注。Wan 2.1作为阿里云推…

系列教程十四 | 基于CosyVoice 2.0实现语音风格迁移

一.背景介绍 随着生成式人工智能的快速发展&#xff0c;语音合成&#xff08;Text-to-Speech, TTS&#xff09;技术正在迈向更自然、更智能、更具情感表达的新时代。过去的 TTS 模型虽然已在音质和语义准确度方面取得显著进步&#xff0c;但在跨语言、情感表达、个性化模拟等方…

外包开发三年

外包开发的三年&#xff1a;困在代码牢笼里的日子这三年就像被困在一座没有出口的迷宫&#xff0c;每天重复着同样的路线&#xff0c;却永远走不到尽头。刚入行时还带着点期待&#xff0c;想着好歹能攒点经验&#xff0c;可现实像一盆冷水&#xff0c;从头顶浇到脚底。外包公司…

解析ASTM D4169:运输包装性能测试的核心标准有哪些

ASTM D4169 是国际公认的运输集装箱和系统性能测试标准&#xff0c;通过模拟真实分销环境中的各类危险元素&#xff0c;为包装运输性提供统一评估依据。该标准包含多个分配周期&#xff08;DC&#xff09;&#xff0c;其中 DC4、DC6、DC12、DC13 是医疗行业界最常选用的周期&am…

提示工程的认知架构设计:架构师的深度思考

提示工程的认知架构设计:架构师的深度思考 引言:AI时代的认知革命 在人工智能技术迅猛发展的今天,提示工程(Prompt Engineering)已经从一项简单的交互技巧演变为一门系统的工程学科。作为架构师,我们需要超越表面的指令编写,深入思考提示工程背后的认知架构设计。这不仅…

Java Web 企业客户管理系统系统源码-SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0【含文档】

摘要 随着信息技术的快速发展&#xff0c;企业客户管理系统的需求日益增长&#xff0c;传统的手工管理模式已无法满足现代企业对高效、精准客户管理的需求。企业客户管理系统能够有效整合客户信息&#xff0c;优化业务流程&#xff0c;提升客户满意度和企业竞争力。当前&#x…

网上超市设计与实现信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】

摘要 随着互联网技术的快速发展和电子商务的普及&#xff0c;网上超市逐渐成为消费者购物的主要渠道之一。传统的线下超市面临着租金成本高、管理效率低、客户覆盖面有限等问题&#xff0c;而网上超市能够突破时间和空间的限制&#xff0c;为消费者提供更加便捷的购物体验。同时…

Java SpringBoot+Vue3+MyBatis 在线文档管理系统系统源码|前后端分离+MySQL数据库

摘要 随着信息技术的快速发展&#xff0c;文档管理已成为企业和个人高效工作的核心需求。传统的文档管理方式依赖本地存储或简单的文件共享工具&#xff0c;存在版本混乱、协作效率低、安全性不足等问题。在线文档管理系统通过云端存储和实时协作功能&#xff0c;能够有效解决这…

大数据诊断性分析:从入门到精通的完整指南

大数据诊断性分析&#xff1a;从入门到精通的完整指南 一、引言&#xff1a;为什么你做了一堆报表&#xff0c;却还是找不到问题的根因&#xff1f; 你有没有过这样的经历&#xff1f; 月底盯着复购率下降20%的报表抓耳挠腮&#xff0c;翻了几十张用户行为折线图&#xff0c;…

【2025最新】基于SpringBoot+Vue的甘肃非物质文化网站管理系统源码+MyBatis+MySQL

&#x1f4a1;实话实说&#xff1a;CSDN上做毕设辅导的都是专业技术服务&#xff0c;大家都要生活&#xff0c;这个很正常。我和其他人不同的是&#xff0c;我有自己的项目库存&#xff0c;不需要找别人拿货再加价&#xff0c;所以能给到超低价格。摘要 非物质文化遗产作为中华…

快速排序 - 原理、时空分析、优化

过程 快速排序分为三个过程&#xff1a; 将数列根据划分值 mmm 划分为两部分&#xff1b;递归到两个子序列中分别进行快速排序&#xff1b;不用合并&#xff0c;因为此时数列已经完全有序。 具体来说&#xff0c;第一步要是要把数列分成两个部分&#xff0c;然后保证前一个子…

Java SpringBoot+Vue3+MyBatis 教师工作量管理系统系统源码|前后端分离+MySQL数据库

&#x1f4a1;实话实说&#xff1a;CSDN上做毕设辅导的都是专业技术服务&#xff0c;大家都要生活&#xff0c;这个很正常。我和其他人不同的是&#xff0c;我有自己的项目库存&#xff0c;不需要找别人拿货再加价&#xff0c;所以能给到超低价格。摘要 随着教育信息化的快速发…

企业级企业客户管理系统管理系统源码|SpringBoot+Vue+MyBatis架构+MySQL数据库【完整版】

&#x1f4a1;实话实说&#xff1a;CSDN上做毕设辅导的都是专业技术服务&#xff0c;大家都要生活&#xff0c;这个很正常。我和其他人不同的是&#xff0c;我有自己的项目库存&#xff0c;不需要找别人拿货再加价&#xff0c;所以能给到超低价格。摘要 随着信息技术的快速发展…

2. 假新闻检测 - 《FakingRecipe: Detecting Fake News on Short Video Platforms from the Perspective of ...》

前言 本文阅读论文《FakingRecipe: Detecting Fake News on Short Video Platforms from the Perspective of Creative Process》。现有的假新闻检测方法主要侧重于分析所呈现内容&#xff0c;而文章的实证分析揭示了假新闻视频在素材选择和编辑方面的独特特征。 核心内容细节…

Java SpringBoot+Vue3+MyBatis 网上超市设计与实现系统源码|前后端分离+MySQL数据库

&#x1f4a1;实话实说&#xff1a;CSDN上做毕设辅导的都是专业技术服务&#xff0c;大家都要生活&#xff0c;这个很正常。我和其他人不同的是&#xff0c;我有自己的项目库存&#xff0c;不需要找别人拿货再加价&#xff0c;所以能给到超低价格。摘要 随着互联网技术的快速发…