Linux的进程概念
目录
1、冯诺依曼体系结构
2、操作系统(Operating System)
2.1 基本概念
编辑
2.2 目的
3、Linux的进程
3.1 基本概念
3.1.1 PCB
3.1.2 struct task_struct
3.1.3 进程的定义
3.2 基本操作
3.2.1 查看进程
3.2.2 初识fork
3.3 进程状态
3.3.1 操作系统的进程状态
3.3.2 Linux的进程状态
3.4 进程优先级
3.4.1 基本概念
3.4.2 PRI&&NI
3.4.3 竞争&&独立&&并行&&并发
3.5 进程切换
3.6 Linux2.6内核进程O(1)调度队列
4、Linux的环境变量
4.1 基本概念
4.2 常见的环境变量
4.3 环境变量的相关命令
4.3.1 查看环境变量
4.3.2 修改环境变量
4.3.3 删除环境变量
4.4 环境变量的特点
5、Linux的进程虚拟地址空间
5.1 程序地址空间
5.2 问题抛出
5.3 进程虚拟地址空间和分页机制
5.4 虚拟地址空间和分页机制的作用
5.5 拓展
1、冯诺依曼体系结构
- 输入设备:键盘,鼠标,网卡,磁盘等。
- 输入设备:显示器,网卡,磁盘等。
- 存储器:即内存。
- CPU:简单来说,是中央处理器(运算器+控制器)。
注意:
- 因为输入输出设备的传输效率低,但是,让输入输出的设备的传输效率变高,成本太高,所以出现内存,即效率与成本之间的平衡,才普及了电脑。
- 程序的运行需要CPU,而CPU只能访问内存,所以程序必须加载到内存中。
- 数据流动的本质:多台冯诺依曼体系结构的交互。
2、操作系统(Operating System)
2.1 基本概念
操作系统包括:
- 内核(进程管理,内存管理,文件管理,驱动管理)
- 其他程序(例如函数库,shell程序等等)
2.2 目的
操作系统,是一款进行 软硬件 管理 的软件。管理:先描述(类),再组织(数据结构)。
sysrem call(系统调用),驱动程序,都是为了屏蔽底层细节,外部实现统一。安全且方便。
-
系统调用封装内核 → 对应用程序统一。
-
驱动程序封装硬件 → 对操作系统统一。
3、Linux的进程
3.1 基本概念
3.1.1 PCB
PCB(Process Control Block),进程控制块,一种类型,Linux中的PCB为:struct task_struct。
3.1.2 struct task_struct
内容分类(后续会详细介绍)
- 标识符(PID):描述本进程的唯一标识符,用于区分其他进程。
- 状态:任务状态,包括退出代码、退出信号等。
- 优先级:相对于其他进程的优先级。
- 程序计数器:程序中即将被执行的下一条指令的地址。
- 内存指针:包括程序代码和进程相关数据的指针,以及与其他进程共享的内存块指针。
- 上下文数据:进程执行时处理器的寄存器中的数据(例如:CPU 寄存器状态,需附图说明)。
- I/O 状态信息:包括未完成的 I/O 请求、分配给进程的 I/O 设备,以及进程使用的文件列表。
- 记账信息:可能包括处理器占用时间、时钟周期总和、时间限制、计账号等。
- 其他信息:与进程相关的其他数据。
在 Linux 内核中,所有进程均通过 struct task_struct 结构体描述,并以双向链表的形式(即队列)组织和管理。
3.1.3 进程的定义
进程 = 内核数据结构对象(PCB)+代码和数据
对进程的管理,就是对数据结构的增删改查。
3.2 基本操作
3.2.1 查看进程
1. 通过 /proc 文件系统查看进程信息
-
/proc 是一个虚拟文件系统,提供内核和进程信息的实时访问。
-
每个进程的信息存储在 /proc/[PID]/ 目录下,例如:
ls /proc/1/ # 查看 PID=1 的进程信息(通常是 init/systemd)
2. top:动态查看进程状态(CPU、内存占用等)
top # 默认动态显示所有进程(按 CPU 占用排序)
top -p PID1,PID2,PID3 # 只监控指定 PID 的进程
top -u username # 只显示某用户的进程
交互命令(在 top 运行时使用)
-
k → 结束指定 PID 的进程(输入 PID 后回车)。
-
M → 按内存占用排序。
-
P → 按 CPU 占用排序(默认)。
-
q → 退出 top 。
3. ps:静态查看进程列表
ps aux # 适用于查看所有进程的资源占用,进程状态等
ps -l PID # 适用于查看进程的父子关系,进程优先级等
注意:
- 可以配合grep进行搜索。
- ;和&&可以同时执行多条命令。
- 命令本身也是进程。
4. 通过系统调用,获取进程标识符(PID & PPID)
-
getpid():获取当前进程的 PID。
-
getppid():获取当前进程的父进程 PPID。
如:
#include <stdio.h>
#include <unistd.h>int main() {printf("PID: %d\n", getpid()); // 当前进程 IDprintf("PPID: %d\n", getppid()); // 父进程 IDreturn 0;
}
3.2.2 初识fork
通过fork(系统调用),创建子进程。
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{int ret = fork();printf("hello proc : %d!, ret: %d\n", getpid(), ret);sleep(1);return 0;
}
- 两个返回值,对父进程返回子进程的PID,对子进程返回0。因为父:子 = 1:N,父进程需要区分子进程,而子进程能通过PPID找到父进程。所以可以if,让父子进程执行不同的语句。
-
fork() 创建子进程后,父子进程从 fork() 返回处继续执行。注意:子进程不会执行fork()之前的代码。
-
当父子进程尝试修改数据,会发生写时拷贝,重新拷贝一份数据。所以父子进程独立运行。
3.3 进程状态
3.3.1 操作系统的进程状态
以上可以分为三类:
- 运行:PCB对象在调度队列中,正在运行(运行)或准备运行(创建+就绪)。
- 阻塞:等待某种设备或资源就绪,PCB对象进入设备队列或资源队列。
- 挂起:内存不足,将进程的代码和数据放到磁盘中,进程是运行状态就是就绪挂起,进程是阻塞状态就是阻塞挂起。
注意:
- 一个CPU,一个调度队列
- PCB对象,可以同时在不同的数据结构中,即可以在不同的队列中。
- 进程的状态,就是PCB对象在不同队列之间的流动,本质是数据结构的增删改查。
3.3.2 Linux的进程状态
/** The task state array is a "bitmap" of reasons to sleep.* "Running" is 0, other states can be combined via bit tests.*/
static const char *const task_state_array[] = {"R (running)", /* 0 - 运行中或就绪 */"S (sleeping)", /* 1 - 可中断睡眠(等待事件)*/"D (disk sleep)", /* 2 - 不可中断睡眠(通常等待I/O)*/"T (stopped)", /* 4 - 被信号暂停(如SIGSTOP)*/"t (tracing stop)", /* 8 - 被调试器跟踪暂停 */"X (dead)", /* 16 - 完全终止(不会出现在任务列表)*/"Z (zombie)", /* 32 - 僵尸进程(已终止但未回收)*/
};
- R:运行中或就绪(进程一创建,就进入就绪状态)。
- S:可中断休眠(浅睡眠,一种阻塞),能被操作系统杀死。
- D:不可中断休眠(深睡眠,一种阻塞),不能被操作系统杀死。
- T:暂停,如:Ctrl+z。
- t:暂停,如:debug的断点。
- X:死亡,进程结束。
- Z:僵尸,子进程退出,父进程需要获取子进程退出前的信息(即子进程PCB对象里面的信息,其指向的代码和数据已被释放),并释放子进程的PCB对象,如果父进程没有获取子进程退出前的信息,那么子进程被称为"僵尸进程",其PCB对象将会一直存在,造成内存泄漏。如果父进程先结束,其子进程称为"孤儿进程",会被1号进程"领养",不会成为"僵尸进程"。
注意:
阻塞是进程的 正常状态(因等待资源主动暂停),而 饥饿是 异常现象(可能是一直阻塞,或进程可能无需等待资源,但因调度问题无法运行等)
3.4 进程优先级
3.4.1 基本概念
进程得到CPU资源的先后顺序。
注意:
- 优先级是一种数字,值越低,优先级越高。
- 优先级,能得到某种资源(只是先后问题),权限,能否得到某种资源。
- Linux,基于时间片的分时操作系统,要考虑公平性,所以优先级变化不大。
3.4.2 PRI&&NI
- PRI:进程的优先级,默认80。
- NI:nice值,进程优先级的修正数据,默认0。范围是[-20,19]。
注意:
- 进程真实的优先级PRI = 80 + NI。所以优先级的范围是[60,99]。保证公平性。
-
NI 的存在 是为了在 灵活性(用户态调整)和 稳定性(内核控制)之间取得平衡。
3.4.3 竞争&&独立&&并行&&并发
- 竞争:系统中进程数量远多于 CPU 资源(如单核 CPU 只能同时运行 1 个进程),因此进程之间需要竞争 CPU 时间片、内存、I/O 等资源。通过 优先级(Priority) 或 调度算法(如时间片轮转)来合理分配资源,确保高优先级或关键任务能优先执行。
- 独立:每个进程拥有独立的地址空间、文件描述符、寄存器状态等资源,一个进程崩溃不会直接影响其他进程。
- 并行:多个进程在 多个 CPU/核心上真正同时运行(物理层面的同时执行)。
- 并发:多个进程在 单个 CPU 上通过快速切换(时间片轮转) 模拟“同时运行”的效果(逻辑层面的交替执行)。
3.5 进程切换
CPU上下文切换(Context Switch),实际上是任务切换,或CPU寄存器的切换。
流程:
-
保存现场:
当多任务操作系统决定切换到另一个任务时,首先将当前运行任务的CPU寄存器状态完整保存到该任务的私有堆栈中。 -
恢复现场:
从待运行任务的堆栈中加载其之前保存的寄存器状态到CPU。 -
切换执行:
CPU开始执行新任务的指令流。
注意:
- 进程在一个时间片内占用CPU,不会一直占用。
- 进程切换的本质:保存和恢复 进程硬件上下文的数据(即CPU寄存器的状态)。
3.6 Linux2.6内核进程O(1)调度队列
- 对于active队列,先看nr_active,有没有进程,再通过bitmap[5],按照优先级,快速定位队列,最后挑队首的进程,执行。
- 进程执行完一个时间片,进入expired队列(防止高优先级进程执行完一个时间片,又插队)。当active队列为空时,swap(&active,&expired),交换两个指针,继续调度active队列。
- 新来一个进程,如果放到expired队列,就是就绪状态,如果放到active队列,也是就绪状态,但是"插队"了。
- 如果active中的进程,更改NI(nice值),即更改优先级,因为麻烦,所以执行完一个时间片后,进入过期队列时,再更新优先级。
4、Linux的环境变量
4.1 基本概念
环境变量是操作系统中用于指定运行环境参数的键值对(KEY=VALUE)。
KEY是环境变量的名字,VALUE是环境变量的内容。
4.2 常见的环境变量
4.3 环境变量的相关命令
4.3.1 查看环境变量
命令行:
- env:显示当前进程 所有的环境变量。
- echo $环境变量名字:显示环境变量的内容。
- set:显示当前进程 所有的变量。如:直接i=10或i,定义本地变量i。
系统调用:
- int main(int argc,char* argv[ ],char* env[ ]){ return 0;},argv是命令行输入的命令字符串数组(以空格为分隔符,将命令分成若干个字符串,数组以NULL结尾),argc是argv数组元素的个数,env是该进程 环境变量的字符串数组(环境变量放在字符串里,数组以NULL结尾)。
- getenv(),在当前进程,根据环境变量的名字,获取环境变量的内容。
- 全局变量environ(环境变量字符串数组,数组以NULL结尾),必须先extern char** environ;声明,再使用。
4.3.2 修改环境变量
- 环境变量名=$环境变量名:内容,给环境变量加内容。如:PATH=$PATH:/home/Lzc/test。
- export 变量名=“值”,新增环境变量。
注意:
以上关闭终端,重新登录,就会失效。想要永久生效,就要更改配置文件(~/.bashrc或~/.bash_profile),因为bash每次都是拷贝配置文件的内容。
4.3.3 删除环境变量
- unset 变量名:清除变量,本地变量和环境变量都可以。
4.4 环境变量的特点
- 新创建的子进程会继承父进程的环境变量(全局性)。进程相互独立,所以环境变量也独立,互不影响。
- 本地变量不会被新创建的子进程继承。
5、Linux的进程虚拟地址空间
5.1 程序地址空间
以32位机器为例:
5.2 问题抛出
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>int g_val = 0; // 全局变量,初始化为0int main() {pid_t id = fork(); // 创建子进程if (id < 0) { // fork失败perror("fork");return 0;}else if (id == 0) { // 子进程分支g_val = 100; // 子进程修改全局变量printf("child[%d]: %d : %p\n", getpid(), g_val, &g_val);} else { // 父进程分支sleep(3); // 父进程休眠3秒,确保子进程先执行printf("parent[%d]: %d : %p\n", getpid(), g_val, &g_val);}sleep(1); // 防止父进程或子进程提前终止return 0;
}
为什么地址一样,内容却不一样?
说明:
- 该地址绝对不是物理地址!
- 在Linux系统下,这种地址称为**虚拟地址**。
- 我们用C/C++语言看到的地址都是虚拟地址,物理地址对用户完全不可见,由操作系统统一管理。
5.3 进程虚拟地址空间和分页机制
所以,程序地址空间,准确来说是,进程虚拟地址空间。
首先,一个进程,一个虚拟地址空间。
struct task_struct {/*...*/struct mm_struct *mm; // 指向进程用户空间虚拟地址空间描述符// - 对普通用户进程:指向其虚拟地址空间的用户空间部分// - 对内核线程:NULL(因内核线程无独立用户空间)struct mm_struct *active_mm; // 内核线程使用的替代mm字段// - 内核线程的mm为NULL时,可借用其他进程的地址空间// - 所有进程的内核空间映射相同,故内核线程可复用/*...*/
};struct mm_struct {/*...*/struct vm_area_struct *mmap; // 虚拟内存区域(VMA)链表头struct rb_root mm_rb; // VMA红黑树根节点(加速查找)unsigned long task_size; // 用户虚拟地址空间大小/* 各段地址边界 */unsigned long start_code, end_code; // 代码段起止unsigned long start_data, end_data; // 数据段起止unsigned long start_brk, brk; // 堆段起止unsigned long start_stack; // 栈起始地址unsigned long arg_start, arg_end; // 命令行参数段unsigned long env_start, env_end; // 环境变量段/*...*/
};// 1.当虚拟区较少时采取单链表,由mmap指针指向这个链表;
// 2.当虚拟区间多时采取红⿊树进⾏管理,由mm_rb指向这棵树。
struct vm_area_struct {unsigned long vm_start; // 虚拟内存区域起始地址unsigned long vm_end; // 虚拟内存区域结束地址/* 链表与树结构 */struct vm_area_struct *vm_next, *vm_prev; // 双向链表指针struct rb_node vm_rb; // 红黑树节点unsigned long rb_subtree_gap;/* 关联的地址空间 */struct mm_struct *vm_mm; // 所属的mm_struct/* 权限与标志 */pgprot_t vm_page_prot; // 访问权限(读/写/执行)unsigned long vm_flags; // 区域标志(如VM_READ|VM_WRITE)/* 共享与反向映射 */struct {struct rb_node rb;unsigned long rb_subtree_last;} shared;struct list_head anon_vma_chain;struct anon_vma *anon_vma;/* 操作方法与文件映射 */const struct vm_operations_struct *vm_ops; // 区域操作函数集unsigned long vm_pgoff; // 文件映射偏移量(以页为单位)struct file *vm_file; // 映射的文件指针(若为文件映射)void *vm_private_data; // 驱动私有数据/* 其他配置 */atomic_long_t swap_readahead_info;
#ifdef CONFIG_NUMAstruct mempolicy *vm_policy; // NUMA内存策略
#endifstruct vm_userfaultfd_ctx vm_userfaultfd_ctx;
} __randomize_layout;
如图所示:
一个进程,一个页表,进行虚拟地址和物理地址的映射。
将物理地址转化为虚拟地址,提供给用户使用。
5.4 虚拟地址空间和分页机制的作用
- 将地址,"无序"变"有序"。
- 地址转化的过程中,可以对操作进行合法判定,进而保护物理内存(根据权限)。
- 让进程管理和内存管理在一定程度上解耦合。
5.5 拓展
- 可以不加载代码和数据到物理内存,只有struct task_struct,struct mm_struct,页表,需要访问时,“缺页中断”,再加载。所以创建进程,先有struct task_struct,struct mm_struct等,再有代码和数据。
- 当物理内存不足时,对于阻塞的进程,通过页表换出物理地址(释放内存),变为阻塞挂起,腾出内存空间。
相关文章:

Linux的进程概念
目录 1、冯诺依曼体系结构 2、操作系统(Operating System) 2.1 基本概念 编辑 2.2 目的 3、Linux的进程 3.1 基本概念 3.1.1 PCB 3.1.2 struct task_struct 3.1.3 进程的定义 3.2 基本操作 3.2.1 查看进程 3.2.2 初识fork 3.3 进程状态 3.3.1 操作系统的进程状…...
C++ map容器: 插入操作
1. map插入操作基础 map是C STL中的关联容器,存储键值对(key-value pairs)。插入元素时有四种主要方式,各有特点: 1.1 头文件与声明 #include <map> using namespace std;map<int, string> mapStu; // 键为int,值…...
基于STC89C52的红外遥控的电子密码锁设计与实现
一、引言 电子密码锁作为一种安全便捷的门禁系统,广泛应用于家庭、办公室等场景。结合红外遥控功能,可实现远程控制开锁,提升使用灵活性。本文基于 STC89C52 单片机,设计一种兼具密码输入和红外遥控的电子密码锁系统,详细阐述硬件选型、电路连接及软件实现方案。 二、硬…...
Docker配置容器开机自启或服务重启后自启
要将一个 Docker 容器设置为开机自启,你可以使用 docker update 命令或配置 Docker 服务来实现。以下是两种常见的方法: 方法 1:使用 docker update 设置容器自动重启 使用 docker update 设置容器为开机自启 你可以使用以下命令,…...

计算机单个进程内存布局的基本结构
这张图片展示了一个计算机内存布局的基本结构,从低地址(0x00000000)到高地址(0xFFFFFFFF)依次分布着不同的内存区域。 代码段 这是程序代码在内存中的存储区域。它包含了一系列的指令,这些指令是计算机执行…...

我的电赛(简易的波形发生器大一暑假回顾)
DDS算法:当时是用了一款AD9833芯片搭配外接电路实现了一个波形发生,配合stm32f103芯片实现一个幅度、频率、显示的功能; 在这个过程中,也学会了一些控制算法;就比如DDS算法,当时做了一些了解,可…...
AI工程 新技术追踪 探讨
文章目录 一、核心差异维度对比二、GitHub对AI工程师的独特价值三、需要警惕的陷阱四、推荐追踪策略五、与传统开发的平衡建议 以下内容整理来自 deepseek 作为AI工程师,追踪GitHub开源项目 对技术成长和职业发展的影响 比传统应用开发工程师 更为显著,…...

算法题(149):矩阵消除游戏
审题: 本题需要我们找到消除矩阵行与列后可以获得的最大权值 思路: 方法一:贪心二进制枚举 这里的矩阵消除时,行与列的消除会互相影响,所以如果我们先统计所有行和列的总和,然后选择消除最大的那一行/列&am…...
在 Vue 中插入 B 站视频
前言 在 Vue 项目中,有时我们需要嵌入 B 站视频来丰富页面内容,为用户提供更直观的信息展示。本文将详细介绍在 Vue 中插入 B 站视频的多种方法。 使用<iframe>标签直接嵌入,<iframe>标签是一种简单直接的方式,可将 B 站视频嵌…...

printf函数参数与入栈顺序
01. printf()的核心功能 作用:将 格式化数据 输出到 标准输出(stdout),支持多种数据类型和格式控制。 int printf(const char *format, ...);参数: format:格式字符串,字符串或%开头格式符...:…...

仿生眼机器人(人脸跟踪版)系列之一
文章不介绍具体参数,有需求可去网上搜索。 特别声明:不论年龄,不看学历。既然你对这个领域的东西感兴趣,就应该不断培养自己提出问题、思考问题、探索答案的能力。 提出问题:提出问题时,应说明是哪款产品&a…...
08、底层注解-@Configuration详解
# Configuration 注解详解 08、底层注解-Configuration详解 Configuration 是 Spring 框架中用于定义配置类的核心注解,它允许开发者以 Java 代码的形式替代传统的 XML 配置,声明和管理 Bean。 ## 一、基本作用 ### 1. 标识配置类 使用 Configuration…...

Go语言语法---输入控制
文章目录 1. fmt包读取输入1.1. 读取单个值1.2. 读取多个值 2. 格式化输入控制 在Go语言中,控制输入主要涉及从标准输入(键盘)或文件等来源读取数据。以下是几种常见的输入控制方法: 1. fmt包读取输入 fmt包中的Scan和Scanln函数都可以读取输入…...
蓝桥杯单片机按键进阶
蓝桥杯单片机按键进阶 ——基于柳离风老师模板及按键进阶教程 文章目录 蓝桥杯单片机按键进阶1、按键测试-按下生效2、按键进阶-松手生效3、按键进阶-按键禁用(未完待续) 1、按键测试-按下生效 key.c #include "key.h"/*** brief 独立按键…...

CSS- 4.3 绝对定位(position: absolute)学校官网导航栏实例
本系列可作为前端学习系列的笔记,代码的运行环境是在HBuilder中,小编会将代码复制下来,大家复制下来就可以练习了,方便大家学习。 HTML系列文章 已经收录在前端专栏,有需要的宝宝们可以点击前端专栏查看! 点…...
Flink 作业提交流程
Apache Flink 的 作业提交流程(Job Submission Process) 是指从用户编写完 Flink 应用程序,到最终在 Flink 集群上运行并执行任务的整个过程。它涉及多个组件之间的交互,包括客户端、JobManager、TaskManager 和 ResourceManager。…...
拓展运算符
拓展运算符(Spread Operator)是ES6中引入的新特性,以下是关于它的一些知识点总结: 语法 拓展运算符的语法是三个点(...),它可以将数组或对象展开成多个元素或属性。 数组中的应用 • 数组展…...

Seata源码—6.Seata AT模式的数据源代理一
大纲 1.Seata的Resource资源接口源码 2.Seata数据源连接池代理的实现源码 3.Client向Server发起注册RM的源码 4.Client向Server注册RM时的交互源码 5.数据源连接代理与SQL句柄代理的初始化源码 6.Seata基于SQL句柄代理执行SQL的源码 7.执行SQL语句前取消自动提交事务的源…...

计算机科技笔记: 容错计算机设计05 n模冗余系统 TMR 三模冗余系统
NMR(N-Modular Redundancy,N 模冗余)是一种通用的容错设计架构,通过引入 N 个冗余模块(N ≥ 3 且为奇数),并采用多数投票机制,来提升系统的容错能力与可靠性。单个模块如果可靠性小于…...

Spring Boot 与 RabbitMQ 的深度集成实践(一)
引言 ** 在当今的分布式系统架构中,随着业务复杂度的不断提升以及系统规模的持续扩张,如何实现系统组件之间高效、可靠的通信成为了关键问题。消息队列作为一种重要的中间件技术,应运而生并发挥着举足轻重的作用。 消息队列的核心价值在于其…...

黑马程序员2024新版C++笔记 第2章 语句
1.if逻辑判断语句 语法主体: if(要执行的判断,结果是bool型){判断结果是true会执行的代码; } 2.AI大模型辅助编程 在Clion中搜索并安装对应插件: 右上角齿轮点击后找到插件(TRONGYI LINGMA和IFLYCODE)安装后重启ide即可。 重启后会有通义登…...
HTML5中的Microdata与历史记录管理详解
HTML5中的Microdata与历史记录管理解析 一、Microdata结构化数据 核心属性 itemscope 声明数据范围itemtype 指定数据词汇表(如http://schema.org/Product)itemprop 定义数据属性 <div itemscope itemtype"http://schema.org/Book">…...
上位机知识篇---涂鸦智能云平台
文章目录 前言 前言 本文简单介绍了涂鸦智能云平台。...
面试中的线程题
原文链接:线程题大全 Java 并发库同步辅助类 CountDownLatch 工作机制:初始化一个计数器,此计数器的值表示需要等待的事件数量。 提供了两个主要方法: await():当一个线程调用此方法时,它将阻塞&#…...
济南国网数字化培训班学习笔记-第三组-2-电力通信光缆网认知
电力通信光缆网认知 光缆网架构现状 基础底座 电路系统是高度复杂,实时性、安全性、可靠性要求极高的巨系统,必须建设专用通信网 相伴相生 电力系统是由发电、输电、变电、配电、用电等一次设施,及保障其正常运行的保护、自动化、通信等…...

前端动画库 Anime.js 的V4 版本,兼容 Vue、React
前端动画库 Anime.js 更新了 V4 版本,并对其官网进行了全面更新,增加了许多令人惊艳的效果,尤其是时间轴动画效果,让开发者可以更精确地控制动画节奏。 这一版本的发布不仅带来了全新的模块化 API 和显著的性能提升,还…...

用 PyTorch 从零实现简易GPT(Transformer 模型)
用 PyTorch 从零实现简易GPT(Transformer 模型) 本文将结合示例代码,通俗易懂地拆解大模型(Transformer)从数据预处理到推理预测的核心组件与流程,并通过 Mermaid 流程图直观展示整体架构。文章结构分为四…...
前端JSON序列化中的隐形杀手:精度丢失全解析与实战解决方案
当你在电商平台看到订单ID从 “1298035313029456899” 变成 “1298035313029456900”,或者在金融系统中发现账户余额 100.01 元变成了 100.00999999999999 元时,这很可能遭遇了前端开发中最隐蔽的陷阱之一 —— JSON序列化精度丢失。本文将深入解析这一问…...

【通用大模型】Serper API 详解:搜索引擎数据获取的核心工具
Serper API 详解:搜索引擎数据获取的核心工具 一、Serper API 的定义与核心功能二、技术架构与核心优势2.1 技术实现原理2.2 对比传统方案的突破性优势 三、典型应用场景与代码示例3.1 SEO 监控系统3.2 竞品广告分析 四、使用成本与配额策略五、开发者注意事项六、替…...

Spring3+Vue3项目中的知识点——JWT
全称:JOSN Web Token 定义了一种简洁的、自包含的格式,用于通信双方以json数据格式的安全传输信息 组成: 第一部分:Header(头),记录令牌类型、签名算法等。 第二部分:Payload&am…...