Linux系统:进程程序替换以及相关exec接口
本节重点
- 理解进程替换的相关概念与原理
- 掌握相关程序替换接口
- 程序替换与进程创建的区别
- 程序替换的注意事项
一、概念与原理
进程程序替换是操作系统中实现多任务和资源复用的关键机制,允许进程在运行时动态加载并执行新程序。
1.1 定义
进程程序替换是指用新程序的代码、数据和堆栈完全替换当前进程的地址空间(加载新程序到内存、更新页表映射、初始化虚拟地址空间,并将进程控制块(PCB)指向新程序),使进程执行新程序的逻辑,而进程ID(PID)保持不变。
1.2 与进程创建的区别
- 进程创建(fork):创建新进程,并分配PID
- 进程程序替换:不创建新进程,更改原程序的代码与数据
二、实现方法 exec函数(6+1)
2.1 语言封装(6)
2.1.1 execl
函数原型:
int execl(const char *pathname, const char *arg, ...);
参数:
pathname:新程序的路径+文件名
arg:传递给新程序的参数
代码示例:
#include<iostream>
#include<cstdio>
#include<unistd.h>
int main()
{printf("进程替换之前!\n");int ret=execl("/bin/ls","ls","-a","-l",NULL);//进程替换成功后后续代码不会执行//只有进程替换出错后才会执行后续代码,并设置错误码(void)ret;printf("进程替换之后!\n");return 0;
}
运行结果:
2.1.2 execlp
int execlp(const char *file, const char *arg, ...);
参数解析:
file:新程序的程序名
arg:传递给新程序的参数/执行的方法
代码示例:
#include<iostream>
#include<cstdio>
#include<unistd.h>int main()
{printf("进程替换之前!:\n");int ret=execlp("ls","ls","-a","-l",NULL);(void)ret;if(ret==-1)printf("execlp fail!\n");printf("进程替换之后!:\n");return 0;
}
运行结果:
2.1.3 execle
int execle(const char *pathname, const char *arg, char *const envp[]);
参数解析:
pathname:新程序的路径+文件名
arg:传递给新程序的参数/执行新程序的方法
envp:传递给新程序的环境变量表(以NULL结尾)
代码示例:
code.cc
#include<iostream>
#include<cstdio>
#include<unistd.h>int main()
{printf("进程替换之前!:\n");char* const env[]={(char* const)"other=12345",(char* const)"n1=45612",(char* const)"n2=56784",(char* const)"n3=12034",(char* const)"n4=yuejianhua",(char* const)"n5=jinzhiqi",NULL,};int ret=execle("./text","text",NULL,env);if(ret==-1)printf("execlp fail!\n");printf("进程替换之后!:\n");return 0;
}
text.cc
#include<iostream>
#include<cstdio>
#include<unistd.h>int main(int argc,char* argv[],const char* env[])
{//打印环境变量表:int i=0;while(env[i]){std::cout<<env[i]<<std::endl;i++;}i=0;//打印命令行参数列表:while(argv[i]){std::cout<<argv[i]<<std::endl;i++;} return 0;
}
运行结果:
2.1.4 execv
int execv(const char *pathname, char *const argv[]);
参数解析:
pathname:新程序的路径+文件名
argv:传递给新程序的命令行参数列表(以NULL结尾)
代码示例:
#include<iostream>
#include<cstdio>
#include<unistd.h>int main()
{printf("进程替换之前!:\n");char* const argv[]={(char* const)"ls",(char* const)"-a",(char* const)"-l",NULL,};int ret=execv("/bin/ls",argv);if(ret==-1)printf("execlp fail!\n");printf("进程替换之后!:\n");return 0;
}
运行结果:
2.1.5 execvp
int execvp(const char *file, char *const argv[]);
参数解析:
file:新程序的文件名
argv:传递给新程序的命令行参数表(以NULL结尾)
代码示例:
code.cc
#include<iostream>
#include<cstdio>
#include<unistd.h>int main()
{printf("进程替换之前!:\n");char* const argv[]={(char* const)"yuejianhua",(char* const)"jinzhiqi",NULL,};int ret=execvp("./text",argv);if(ret==-1)printf("execlp fail!\n");printf("进程替换之后!:\n");return 0;
}
text.cc
#include<iostream>
#include<cstdio>
#include<unistd.h>int main(int argc,char* argv[],char* env[])
{//打印环境变量表:int i=0;//打印命令行参数列表:while(argv[i]){std::cout<<argv[i]<<std::endl;i++;} return 0;
}
运行结果:
2.1.6 execvpe
int execvpe(const char *file, char *const argv[],char *const envp[]);
参数解析:
file:新程序的函数名
argv:传递给新程序的命令行参数列表(以NULL结尾)
envp:传递给新程序的环境变量表(以NULL结尾)
code.cc
#include<iostream>
#include<cstdio>
#include<unistd.h>int main()
{printf("进程替换之前!:\n");char* const argv[]={(char* const)"yuejianhua",(char* const)"jinzhiqi",NULL,};char* const env[]={(char* const)"other=12345",(char* const)"n1=45612",(char* const)"n2=56784",(char* const)"n3=12034",NULL,};int ret=execvpe("./text",argv,env);if(ret==-1)printf("execlp fail!\n");printf("进程替换之后!:\n");return 0;
}
text.cc
#include<iostream>
#include<cstdio>
#include<unistd.h>int main(int argc,char* argv[],char* env[])
{//打印环境变量表:int i=0;while(env[i]){std::cout<<env[i]<<std::endl;i++;} i=0;//打印命令行参数列表:while(argv[i]){std::cout<<argv[i]<<std::endl;i++;} return 0;
}
运行结果:
2.2 系统调用(1)
2.2.1 execve
int execve(const char *pathname, char *const argv[],char *const envp[]);
参数解析:
pathname:新程序的路径+文件名
argv:传递给新程序的命令行参数表(以NULL结尾)
envp:传递给新程序的环境变量表(以NULL结尾)
代码示例:
code.cc
#include<cstdio>
#include<iostream>
#include<unistd.h>
int main()
{std::cout<<"这是进程替换之前"<<std::endl;//传递自己的命令行参数与环境变量表char* const argv[]={(char* const)"yuejianhua",(char* const)"jinzhiqi",NULL,};char* const env[]={(char* const)"n1=12345",(char* const)"n2=45678",(char* const)"n3=lut",NULL,};int ret=execve("./text",argv,env);//替换成功后续代码不会执行if(ret<0){std::cout<<"进程替换失败!"<<std::endl;}std::cout<<"进程替换之后"<<std::endl;return 0;
}
text.cc
#include<cstdio>
#include<iostream>int main(int argc,char* argv[],char* env[])
{int i=0;while(argv[i]){std::cout<<argv[i]<<std::endl;i++;}i=0;while(env[i]){std::cout<<env[i]<<std::endl;i++;}return 0;
}
运行结果:
2.3 总结
函数 | 参数传递方式 | 环境变量 | 路径搜索 | 示例调用 |
---|---|---|---|---|
execl | 可变参数列 表 | 继承 | 需完整路 径 | execl("/bin/ls", "ls", "-l", NULL) |
execlp | 可变参数列表 | 继承 | 支持 PATH | execlp("ls", "ls", "-l", NULL) |
execle | 可变参数列表 | 显式传递 | 需完整路径 | execle("/bin/ls", "ls", "-l", NULL, envp) |
execv | 参数数组 | 继承 | 需完整路径 | char *argv[] = {"ls", "-l", NULL}; execv("/bin/ls", argv); |
execvp | 参数数组 | 继承 | 支持 PATH | execvp("ls", argv); |
execve | 参数数组 | 显式传递 | 需完整路径 | execve("/bin/ls", argv, envp); |
知识点:
进程程序替换所关联的exec族函数都有一个显著特征就是exec+参数传递的方式,每个字母代表特定的传参方法,以下是关于这一类型的总结:
- l (list) :表示给新进程传参需要一个个传
- p(PATH):表示索引新进程可以只传递文件名,但是要是自己的代码文件必须指明路径
- v(vector):表示给新进程传参可以直接使用自定义命令行参数列表
- e(env) :表示可以给新进程传递自定义环境变量表
这里需要注意的是命令行参数列表与环境变量表必须都以NULL结尾。
exec族函数在底层都封装了系统调用execve。
当在进程替换的时候显式地给新进程传递环境变量表时传递的环境变量表会覆盖默认的环境变量表,可以参考execle的代码演示。
三、进程替换的用途
在后期我们可以通过fork+exec机制创建子进程利用进程替换机制使子进程执行定义好的代码文件。
如:Shell执行命令(简易版):
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>int main() {pid_t pid = fork();if (pid == 0) {// 子进程:替换为 ls 命令char *argv[] = {"ls", "-l", NULL};execvp("ls", argv); // 自动搜索 PATHperror("execvp failed");exit(1);} else if (pid > 0) {// 父进程:等待子进程结束wait(NULL);printf("Command executed.\n");} else {perror("fork failed");}return 0;
}
fork+exec机制使用后要注意资源回收的问题,使用进程等待的方式回收或使用信signal(SIGCHLD, SIG_IGN)
自动回收(需谨慎)。
相关文章:
Linux系统:进程程序替换以及相关exec接口
本节重点 理解进程替换的相关概念与原理掌握相关程序替换接口程序替换与进程创建的区别程序替换的注意事项 一、概念与原理 进程程序替换是操作系统中实现多任务和资源复用的关键机制,允许进程在运行时动态加载并执行新程序。 1.1 定义 进程程序替换是指用新程…...
STM32复盘总结——芯片简介
1、stm32介绍 STM32是ST公司基于ARM Cortex-M内核开发的32位微控制器 STM32常应用在嵌入式领域,如智能车、无人机、机器人、无线通信、物联网、工业控制、娱乐电子产品等 STM32功能强大、性能优异、片上资源丰富、功耗低,是一款经典的嵌入式微控制器 目…...
安装深度环境anaconda+cuda+cudnn+pycharm+qt+MVS
下载anaconda,链接:link 默认电脑有显卡驱动,没有的话直接进NVIDIA官网:https://www.nvidia.cn/geforce/drivers/ 下载。 下载cuda 链接:https://developer.nvidia.com/cuda-toolkit-archive 下载cudnn安装包,链接:https://developer.nvidia.com/rdp/cudnn-archive 备注:…...
泰迪杯特等奖案例学习资料:基于多模态特征融合的图像文本检索系统设计
(第十二届泰迪杯数据挖掘挑战赛B题特等奖案例解析) 一、案例背景与核心挑战 1.1 应用场景与行业痛点 随着智能终端与社交媒体的普及,图像与文本数据呈现爆炸式增长,跨模态检索需求日益迫切。传统方法面临以下问题: 语义鸿沟:图像与文本的异构特征分布差异显著,导致跨模…...
进程与线程:05 内核级线程实现
内核级线程代码实现概述 这节课我们要讲内核级线程到底是怎么做出来的,实际上就是要深入探讨内核级线程的代码实现。 在前两节课中,我们学习了用户级线程和内核级线程是如何进行切换的,以及实现切换的核心要点。那两节课讲述的内容…...
Laravel 12 实现 API 登录令牌认证
Laravel 12 实现 API 登录令牌认证 在 Laravel 12 中实现基于令牌(Token)的 API 认证,可以使用 Laravel Sanctum 或 Laravel Passport。以下是两种方式的实现方法: 方法一:使用 Laravel Sanctum (轻量级 API 认证) 1. 安装 Sanctum compo…...
【Git】万字详解 Git 的原理与使用(上)
🥰🥰🥰来都来了,不妨点个关注叭! 👉博客主页:欢迎各位大佬!👈 文章目录 1. 初识 Git1.1 Git 是什么?1.2 为什么要有 Git 2. 安装 Git2.1 Linux-Ubuntu 安装 Git2.2 Windo…...
Python高级爬虫之JS逆向+安卓逆向1.7节: 面向对象
目录 引言: 1.7.1 先理解面向过程 1.7.2 再理解面向对象 1.7.3 面向对象的三大特征 1.7.4 类属性,类方法,静态方法 1.7.5 构造函数,对象属性,对象方法 1.7.6 爬虫接单实现了雪糕自由 引言: 大神薯条老师的高级爬虫+安卓逆向教程: 这套爬虫教程会系统讲解爬虫的初…...
SpringBoot基础(原理、项目搭建、yaml)
SpringBoot:javaweb的一个框架,基于Spring开发,SpringBoot本身并不提供Spring框架的核心特性以及扩展功能,只是用于快速、敏捷的开发新一代基于Spring框架的应用程序,它与Spring框架紧密结合用于提升Spring开发者体验的…...
MTV-SCA:基于多试向量的正弦余弦算法
3 正弦余弦算法 (SCA) 正弦余弦算法(SCA)是为全局优化而开发的,并受到两个函数,正弦和余弦的启发。与其他基于启发式种群的算法一样,SCA在问题的预设最小值和最大值边界内随机生成候选解。然后,通过应用方…...
STL之vector容器
vector的介绍 1.vector是可变大小数组的容器 2.像数组一样,采用连续的空间存储,也就意味着可以通过下标去访问,但它的大小可以动态改变 3.每次的插入都要开空间吗?开空间就要意味着先开临时空间,然后在拷贝旧的到新…...
Android学习总结之jetpack组件间的联系
在传统安卓开发中,UI 组件(Activity/Fragment)常面临三个核心问题: 生命周期混乱:手动管理 UI 与数据的绑定 / 解绑,易导致内存泄漏(如 Activity 销毁后回调仍在触发)。数据断层&am…...
linux的信号量初识
Linux下的信号量(Semaphore)深度解析 在多线程或多进程并发编程的领域中,确保对共享资源的安全访问和协调不同执行单元的同步至关重要。信号量(Semaphore)作为经典的同步原语之一,在 Linux 系统中扮演着核心角色。本文将深入探讨…...
【安装指南】Centos7 在 Docker 上安装 RabbitMQ4.0.x
目录 前置知识:RabbitMQ 的介绍 一、单机安装 RabbitMQ 4.0.7版本 1.1 在线拉取镜像 二、延迟插件的安装 2.1 安装延迟插件 步骤一:下载延迟插件 步骤二:将延迟插件放到插件目录 步骤三:启动延迟插件 步骤四:重启 RabbitMQ 服务 步骤五:验收成果 步骤六:手动…...
Android和iOS测试的区别有哪些?
作为移动端测试工程师,Android 和 iOS 的测试差异直接影响测试策略设计。本文从测试环境、工具链、兼容性、发布流程等维度全面解析,并附实战建议。 1. 测试环境差异 维度AndroidiOS设备碎片化高(厂商/分辨率/系统版本多样)低(仅苹果设备,版本集中)系统开放性开放(可Ro…...
spring中的@PostConstruct注解详解
基本概念 PostConstruct 是 Java EE 规范的一部分,后来也被纳入到 Spring 框架中。它是一个标记注解,用于指示一个方法应该在依赖注入完成后被自动调用。 主要特点 生命周期回调:PostConstruct 标记的方法会在对象初始化完成、依赖注入完成…...
大模型开发学习笔记
文章目录 大模型基础大模型的使用大模型训练的阶段大模型的特点及分类大模型的工作流程分词化(tokenization)与词表映射 大模型的应用 进阶agent的组成和概念planning规划子任务分解ReAct框架 memory记忆Tools工具\工具集的使用langchain认知框架ReAct框架plan-and-Execute计划…...
【android Framework 探究】pixel 5 内核编译
相关文章: 【android Framework 探究】android 13 aosp编译全记录 【android Framework 探究】android 13 aosp 全记录 - 烧录 一,环境 主机 -> Ubuntu 18.04.6 LTS 内存 -> 16GB 手机 -> pixel 5 代号redfin。kernel代号redbull 二…...
PowerBI实现点击空白处隐藏弹窗(详细教程)
PowerBI点击空白处隐藏弹窗 第五届PowerBI可视化大赛中亚军作品:金融企业智慧经营分析看板 有个功能挺好玩的:点击空白处隐藏弹窗,gif动图如下: 我们以一个案例分享下实现步骤: 第一步, 先添加一个显示按钮ÿ…...
【git】获取特定分支和所有分支
1 特定分支 1.1 克隆指定分支(默认只下载该分支) git clone -b <分支名> --single-branch <仓库URL> 示例(克隆 某一个 分支): git clone -b xxxxxx --single-branch xxxxxxx -b :指定分支…...
Windows配置grpc
Windows配置grpc 方法一1. 使用git下载grph下载速度慢可以使用国内镜像1.1 更新子模块 2. 使用Cmake进行编译2.1 GUI编译2.2 命令行直接编译 3. 使用Visual Studio 生成解决方法 方法二1. 安装 vcpkg3.配置vckg的环境变量2. 使用 vcpkg 安装 gRPC3. 安装 Protobuf4. 配置 CMake…...
【学习笔记】深入理解Java虚拟机学习笔记——第2章 Java内存区域与内存溢出异常
第2章 Java内存区域与内存溢出异常 2.1 概述 略 2.2 运行时数据区域 2.2.1 程序计数器 线程私有,记录执行的字节码位置 2.2.2 Java 虚拟机栈 线程私有,存储一个一个的栈帧,通过栈帧的出入栈来控制方法执行。 -栈帧:对应一个…...
数字智慧方案6189丨智慧应急综合解决方案(46页PPT)(文末有下载方式)
资料解读:智慧应急综合解决方案 详细资料请看本解读文章的最后内容。 在当前社会环境下,应急管理的重要性愈发凸显。国务院发布的《“十四五” 国家应急体系规划》以及 “十四五” 智慧应急专项规划,明确了应急管理体系建设的方向和重点&…...
解决 3D Gaussian Splatting 中 SIBR 可视化组件报错 uv_mesh.vert 缺失问题【2025最新版!】
一、📌 引言 在使用 3D Gaussian Splatting(3DGS)进行三维重建和可视化的过程,SIBR_gaussianViewer_app 是一款官方推荐的本地可视化工具,允许我们在 GPU 上实时浏览重建结果。然而,许多用户在启动该工具时…...
见多识广4:Buffer与Cache,神经网络加速器的Buffer
目录 前言传统意义上的Buffer与Cache一言以蔽之定义与主要功能BufferCache 数据存储策略二者对比 神经网络加速器的bufferInput BufferWeight BufferOutput Buffer与传统buffer的核心区别总结 前言 知识主要由Qwen和Kimi提供,我主要做笔记。 参考文献: …...
微服务中组件扫描(ComponentScan)的工作原理
微服务中组件扫描(ComponentScan)的工作原理 你的问题涉及到Spring框架中ComponentScan的工作原理以及Maven依赖管理的影响。我来解释为什么能够扫描到common模块的bean而扫描不到其他模块的bean。 根本原因 关键在于**类路径(Classpath)**的包含情况: Maven依赖…...
C++之类和对象基础
⾯向对象三⼤特性:封装、继承、多态 类和对象 一.类的定义1. 类的定义格式2.类域 二.实例化1.对象2.对象的大小 三.this指针 在 C 的世界里,类和对象构成了面向对象编程(Object-Oriented Programming,OOP)的核心框架&…...
【DIY小记】新手小白超频遇到黑屏问题解决分享
最近玩FPS游戏的时候,发现以前一顿操作超频之后的电脑,有一定概率会出问题。具体表现比如一种是,电脑显示器直接黑屏,所有键盘交互没有响应,只能直接重启电脑,还有一种是偶现卡顿,直接死机或者卡…...
虚幻引擎 IK Retargeter 编辑器界面解析
我来为您详细解释这段关于虚幻引擎IK Retargeter编辑器界面的文本,它描述了动画重定向系统的核心组件和工作原理。 Retarget Phases (重定向阶段) 这部分介绍了动画重定向过程中的三个关键计算阶段,每个阶段都可以单独启用或禁用,这对于调试…...
uc系统中常用命令、标准C库函数和系统调用
目录 一、常用命令 env echo $name 键值 export name unset name gcc -c xxx.c ar 命令 ar -r libxxx.a xxx1.o xxx2.o gcc -c -fpic xxx.c gcc -shared -fpic xxx1.c xxx2.c -o libxxx.so kill [-信号] PID kill -l 软链接:ln -s xxx yyy 硬链接&…...
OpenHarmony - 驱动使用指南,HDF驱动开发流程
OpenHarmony - HDF驱动开发流程 概述 HDF(Hardware Driver Foundation)驱动框架,为驱动开发者提供驱动框架能力,包括驱动加载、驱动服务管理、驱动消息机制和配置管理。并以组件化驱动模型作为核心设计思路,让驱动开发…...
C++负载均衡远程调用学习之UDP SERVER功能
目录 1.LARSV0.9-配置功能 2.LARSV0.10-upd-server的实现 3.LARSV0.10-udp-client的实现 1.LARSV0.9-配置功能 2.LARSV0.10-upd-server的实现 3.LARSV0.10-udp-client的实现...
word交叉引用图片、表格——只引用编号的处理方法
交叉引用图片/表格 在“引用”选项卡上的“题注”组中,单击“插入题注”。勾选【从题注中排除标签】。在文中插入题注。 【注 意】 这时候插入的题注只有编号项了。然后手动打上标签【TABLE】,并在标签和编号项之间加上【样式分隔符,AltCt…...
平台介绍-开放API接口-鉴权
平台的理念是一个组织内部只建一套系统。但是现实情况是,组织内部已经建立了很多系统,是不能一次性替代的,只能先搭起平台,然后逐步开始替换。这样就不可避免的存在其他系统和平台进行交互的问题。 平台为此设计了开放API接口。其…...
【Bootstrap V4系列】 学习入门教程之 组件-警告框(Alert)
Bootstrap V4 学习入门教程之 组件-警告框(Alert) 警告框(Alert)一、示例二、链接的颜色三、添加其它内容四、关闭警告框 通过 JavaScript 触发行为触发器本组件所暴露的事件 警告框(Alert) 通过精炼且灵活…...
【服务器通信-socket】——int socket(int domain, int type, int protocol);
#include <sys/types.h> #include <sys/socket.h> int socket(int domain, int type, int protocol); domain: AF_INET 这是大多数用来产生socket的协议,使用TCP或UDP来传输,用IPv4的地址 AF_INET6 与上面类似,不过是来用IPv6的地…...
洛谷P1014(Cantor 表[NOIP 1999 普及组])题解
题目大意:求Cantor表(按照Z字形排列(如第一项是1/1,然后是1/2,2/1,3/1,2/2))的第N项。 那么,我们需要找出Cantor表的排列规律。根据题目中的Z字形描述&#x…...
【愚公系列】《Manus极简入门》012-自我认知顾问:“内在探索向导”
🌟【技术大咖愚公搬代码:全栈专家的成长之路,你关注的宝藏博主在这里!】🌟 📣开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主! …...
密码学_加密
目录 密码学 01 密码基础进制与计量 02 加解密基操 替换 移位 编码 编码 置换 移位 加解密强度 03 对称加密算法(私钥) 工作过程 缺陷 对称加密算法列举? DES DES算法架构 DES分组加密公式 DES中ECB-CBC两种加密方式 3DES 由于DES密钥太短…...
w317汽车维修预约服务系统设计与实现
🙊作者简介:多年一线开发工作经验,原创团队,分享技术代码帮助学生学习,独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取,记得注明来意哦~🌹赠送计算机毕业设计600个选题excel文…...
云盘系统设计
需求背景 网盘面向大量C端用户 1000w用户 DAU 20% 每天10次 QPS: 1000w * 0.2 * 10 / 100k 500 峰值估计:500 * 5 2500 功能需求 支持上传,下载,多端共同在线编辑,数据冲突处理 非功能需求 1.latency 20s左右 2.可用性与…...
西电雨课堂《知识产权法》课后作业答案
目录 第 1 章 1.1 课后作业 1.2 课后作业 第 2 章 2.1 课后作业 2.2 课后作业 2.3 课后作业 2.4 课后作业 2.5 课后作业 2.6 课后作业 2.7 课后作业 2.8 课后作业 2.9 课后作业 2.10 课后作业 第 3 章 3.1 课后作业 3.2 课后作业 3.3 课后作业 3…...
通信协议记录仪-产品规格书
以下是为 通信协议记录仪(ProtoLogger Pro) 的详细产品规格书,覆盖 技术细节、场景需求、竞品差异化,确保可作为产品开发、市场营销及竞品分析的核心依据。 通信协议记录仪产品规格书 产品名称:ProtoLogger Pro(中文名称:蹲守…...
订单系统冷热分离方案:优化性能与降低存储成本
随着时间推移,订单数据不断积累。在电商平台或者服务型应用中,订单数据是核心数据之一。然而,随着数据量的增长,如何高效存储、管理和查询这些数据成为了系统架构设计的重要问题。在大多数情况下,订单数据的处理不仅涉…...
数据结构学习笔记
第 1 章 绪论 【考纲内容】 (一)数据结构的基本概念 (二)算法的基本概念 算法的时间复杂度和空间复杂度 【知识框架】 【复习提示】 本章内容是数据结构概述,并不在考研大纲中。读者可通过对本章的学习,初步…...
读懂 Vue3 路由:从入门到实战
在构建现代化单页应用(SPA)时,Vue3 凭借其简洁高效的特性成为众多开发者的首选。 而 Vue3 路由(Vue Router)则是 Vue3 生态中不可或缺的一部分,它就像是单页应用的 “导航地图”,帮助用户在不同…...
Aws S3上传优化
上传大约 3.4GB 的 JSON 文件,zip算法压缩后约为 395MB,上传至 S3 效率优化,有一些优化方案可以提高上传速率。下面是几种可能的优化方式,包括选择压缩算法、调整上传方式、以及其他可能的方案。 方案 1. 选择更好的压缩算法 压…...
Python 数据智能实战 (8):基于LLM的个性化营销文案
写在前面 —— 告别群发轰炸,拥抱精准沟通:用 LLM 为你的用户量身定制营销信息 在前面的篇章中,我们学习了如何利用 LLM 增强用户理解(智能分群)、挖掘商品关联(语义购物篮)、提升预测精度(融合文本特征的流失预警)。我们不断地从数据中提取更深层次的洞察。 然而,…...
html:table表格
表格代码示例: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body><!-- 标准表格。 --><table border"5"cellspacing&qu…...
2.maven 手动安装 jar包
1.背景 有的时候,maven仓库无法下载,可以手动安装。本文以pentaho-aggdesigner-algorithm-5.1.5-jhyde.jar为例。 2.预先准备 下载文件到本地指定位置。 2.1.安装pom mvn install:install-file \-Dfile/home/wind/tmp/pentaho-aggdesigner-5.1.5-jh…...