从内核到应用层:深度剖析信号捕捉技术栈(含sigaction系统调用/SIGCHLD回收/volatile内存屏障)
Linux系列
文章目录
- Linux系列
- 前言
- 一、进程对信号的捕捉
- 1.1 内核对信号的捕捉
- 1.2 sigaction()函数
- 1.3 信号集的修改时机
- 二、可重入函数
- 三、volatile关键字
- 四、SIGCHLD信号
前言
Linux系统中,信号捕捉是指进程可以通过设置信号处理函数来响应特定信号。通过信号捕捉机制,进程可以对异步事件做出及时响应,从而提高程序的健壮性和灵活性。
一、进程对信号的捕捉
图中内容及执行流程我已在Linux系列上上篇博客中介绍了,这里就不重复了。
1.1 内核对信号的捕捉
当信号的处理动作是用户自定义函数,在信号递达时就调用这个函数,这称为捕捉信号。由于信号处理函数的代码是在用户空间的,处理过程比较复杂,举例如下:
1、用户程序注册(对指定信号捕捉)了SIGQUIT
信号的处理函数sighandler
。
2、 当前正在执行main
函数,这时发生中断或异常切换到内核态。
3、 在中断处理完毕后要返回用户态的main函数之前检查到有信号SIGQUIT
递达。
4、 内核决定返回用户态后,不是恢复main函数的上下文继续执行,而是执行sighandler
函数,sighandler
和main
函数使用不同的堆栈空间,它们之间不存在调用和被调用的关系,是两个独立的控制流程。
5、 sighandler
函数返回后自动执行特殊的系统调用sigreturn
再次进入内核态。
6、 再次检测sigpending
位图,如果没有新的信号要递达,这次再返回用户态就是恢复main
函数的上下文继续执行了。
1.2 sigaction()函数
#include <signal.h>
int sigaction(int signum, const struct sigaction *act,
struct sigaction *oldact);
功能:捕捉指定信号,并读取和修改与指定捕捉信号相关联的处理动作。
参数
signum:指定捕捉信号的编号。
act: 输入型参数,act
若非空,则根据act
来修改信号的处理动作。
oldact:输出型参数,oldact
若非空,则获取信号原来的处理动作。
struct sigaction:系统为用户提供的结构体类型,帮助用户访问内核级结构体:
今天我们主要使用,上面两个成员对象。
- 信号处理方法,该方法需要一个整形变量,函数指针类型
act.sa_mask
所代表的是在信号处理函数执行期间需要阻塞的信号集合。也就是说,当 指定信号被捕获并且处理函数handler
开始执行时,sa_mask
里的信号会被阻塞,一直到处理函数执行完毕。
下面我们通过两个场景来认识他们:
例一
#include<iostream>
#include<signal.h>
#include<unistd.h>
using namespace std;void handler(int signum)
{cout<<"I catch a signal:"<<signum<<endl;return;
}
int main()
{struct sigaction act;struct sigaction olact;memset(&act,0,sizeof(act));//初始化内存空间memset(&olact,0,sizeof(olact));sigaction(2,&act,&olact);//对二号信号捕获,并修改处理方法while(true){cout<<"I am process,Pid:"<<getpid()<<endl;sleep(1);}return 0;
}
可以看到这样我们,就完成了对二号进程的捕获并修改执行方法为自定义的行为。
例二
#include<iostream>
#include<signal.h>
#include<unistd.h>
#include<cstring>
using namespace std;void handler(int signum)
{cout<<"I catch a signal:"<<signum<<endl;sleep(10);//在执行handler方法期间,blocksig阻塞信号集中的信号被阻塞return;
}
int main()
{struct sigaction act;struct sigaction olact;memset(&act,0,sizeof(act));//初始化内存空间memset(&olact,0,sizeof(olact));sigset_t blocksig;sigaddset(&blocksig,2);//将二信号添加进blocksigact.sa_handler=handler;//将处理方法添加到act对象中act.sa_mask=blocksig;//将想要阻塞的信号位图赋值给actsigaction(2,&act,&olact);//对二号信号捕获,并修改处理方法while(true){cout<<"I am process,Pid:"<<getpid()<<endl;sleep(1);}return 0;
}
从执行结构可以得到,当二号信号被捕获执行处理方法,到该方法执行结束,二号信号一直被阻塞,当解除阻塞后,二号信号再次递达。这里也可以使用SIG_IGN
(忽略信号)、SIG_DFL
(执行默认方法),来设定act.sa_handler
。测试时建议尝试其他信号,因为即使我们不手动的将二号信号添加到阻塞信号集,系统在执行二号信号时也会将它先阻塞,下面我们来详细探讨。
1.3 信号集的修改时机
当我们完成对指定信号的捕捉并执行对应处理方法时,操作系统会在执行该方法前,先将pending
位图中对应信号的标志位由1
置为0
,并将该信号添加到对应的阻塞信号集中。具体来说,在二号信号处理方法执行期间,即便进程再次收到二号信号,该信号也不会被递达。只有当上一个信号处理方法执行完毕并返回后,操作系统解除对二号信号的阻塞,新收到的二号信号才会被递达。
#include<iostream>
#include<signal.h>
#include<unistd.h>
#include<cstring>
using namespace std;void printsig()
{sigset_t set;sigemptyset(&set);sigpending(&set);for(int i=1;i<=31;i++)//依次检测信号集{if(sigismember(&set,i))cout<<1;else cout<<0;}cout<<endl;return ;
}
void handler(int signum)
{int cnt=5;while(cnt--){printsig();sleep(1);}cout<<"I catch a signal:"<<signum<<endl;sleep(5);//在执行handler方法期间,blocksig阻塞信号集中的信号被阻塞return;
}
int main()
{struct sigaction act;struct sigaction olact;memset(&act,0,sizeof(act));//初始化内存空间memset(&olact,0,sizeof(olact));act.sa_handler=handler;//将处理方法添加到act对象中sigaction(2,&act,&olact);//对二号信号捕获,并修改处理方法while(true){cout<<"I am process,Pid:"<<getpid()<<endl;sleep(1);}return 0;
}
从程序执行结果可以得出,当方法被执行时,操作系统会先将pending
信号集1--->0
,并将该信号阻塞,知道上次执行结束才会完成递达。
二、可重入函数
结合图中展示,分析函数调用链
在程序运行过程中,
main
函数调用insert
函数,打算向链表head
中插入节点node1
。insert
函数的插入操作分为两个步骤,当main
函数调用的insert
函数刚完成第一步时,硬件中断出现,进程被切换到内核态。在从内核态再次返回用户态之前,系统检测到有信号需要处理,于是进程转而执行sighandler
函数。在sighandler
函数中,同样调用了insert
函数,并且向同一个链表head
中插入节点node2
。sighandler
函数中的insert
操作顺利完成了两个步骤,之后从sighandler
函数返回内核态,接着再次回到用户态时,恢复上下文数据,程序从main
函数调用的insert
函数中断处继续执行,完成了剩余的第二步操作。原本main
函数和sig handler
函数先后尝试向链表中插入两个不同的节点,但最终链表中实际上仅成功插入了一个节点。
在上述执行流程中,insert函数被main和handler两条执行流重复调用,这一情况引发了结点丢失问题,并进而导致内存泄漏。像insert函数这种在被重复调用时可能出错或已经出错的函数,我们称之为不可重入函数;与之相对应的,则被称为可重入函数。
不可重入函数的特点:
调用了malloc或free,因为malloc也是用全局链表来管理堆的。
调用了标准I/O库函数。标准I/O库的很多实现都以不可重入的方式使用全局数据结构。
三、volatile关键字
接下来会通过这个关键字,拓展部分知识
例一
#include<iostream>
#include<signal.h>
#include<unistd.h>
#include<cstring>
using namespace std;int flag=0;void handler(int signum)
{cout<<"I captured a signal:"<<signum<<endl;flag=1;
}
int main()
{struct sigaction act;memset(&act,0,sizeof(act));act.sa_handler=handler;sigaction(2,&act,nullptr);while(!flag);cout<<"process quit "<<endl;return 0;
}
mytest:mytest.ccg++ -o $@ $^ -std=c++11
相信这个执行结果大家都能理解,我就不对上面代码作解释了。
这里将flag设为全局变量,是因为main和sighandler是两个独立的执行流
例二
代码同上
mytest:mytest.ccg++ -o $@ $^ -std=c++11 -O2
从程序执行结果可知,当将g++
编译器的优化级别设置为-O2
时,即便通过发送二号信号(SIGINT)将flag
变量修改为1
,循环仍无法终止。这一现象的根源在于:当使用-O2
这类高级优化级别编译代码时,编译器会对代码进行多维度优化以提升执行效率。针对while(!flag);
这一循环结构,编译器通过静态代码分析发现,循环体内部不存在对flag
变量的修改操作,因此推断该变量的值在循环过程中不会发生变化。
基于“内存访问速度相对较慢”这一特性,编译器为减少对内存的频繁访问,会将flag
变量的值从内存加载至CPU寄存器中缓存。此后,在循环条件判断时,CPU会直接从寄存器中读取flag
的值,而非重新从内存中获取最新数据,这就导致flag
内存不可见了。然而,信号处理机制对flag
变量的修改是直接作用于内存的,由于寄存器中的缓存值未及时刷新,导致循环条件判断始终基于寄存器中的旧值,最终造成循环无法终止的现象。
对于上面的结果我们可以,将 flag
声明为 volatile
类型,即 volatile int flag = 0;
。volatile
关键字的作用是保存flag
的内存可见性,告诉编译器,这个变量的值可能会被意外地改变,例如被硬件或者其他线程、信号处理函数等修改,因此编译器不能对其进行优化,这里就不展示了。
四、SIGCHLD信号
之前我们探讨过使用 wait
和 waitpid
函数来清理僵尸进程。在处理子进程结束的问题上,父进程有两种选择:一是进行阻塞等待,直至子进程结束;二是采用非阻塞的轮询方式,周期性地检查是否有子进程结束,以便及时清理。然而,这两种方式都存在明显的弊端。若采用阻塞等待的方式,父进程在等待期间会被阻塞,无法处理自身的任务,这会极大地降低父进程的工作效率。而采用轮询方式,虽然父进程可以在处理自身工作的同时检查子进程的状态,但这要求父进程时刻记得进行轮询操作,无疑增加了程序实现的复杂度,也容易出现疏漏。实际上,当子进程终止时,它会向父进程发送 SIGCHLD
信号。该信号的默认处理方式是被忽略,但我们可以对其进行优化。父进程可以自定义 SIGCHLD
信号的处理函数,这样一来,父进程就能够专注于自身的工作,无需时刻关注子进程的状态。当子进程终止时,会自动通知父进程,父进程只需在信号处理函数中调用 wait
函数,即可完成子进程的清理工作,既高效又便捷。 下面我们通过这样的方式实现一下:
#include<iostream>
#include<signal.h>
#include<unistd.h>
#include<cstring>
#include<sys/wait.h>
#include<sys/types.h>
using namespace std;void handler(int signum)
{pid_t wid=waitpid(0,nullptr,WNOHANG);if(wid)cout<<"child quit success"<<endl;return;
}
int main()
{signal(SIGCHLD,handler);pid_t id=fork();if(id==0){sleep(5);//模拟子进程工作exit(0);}while(true){cout<<"I am father process"<<endl;sleep(1);}return 0;
}
从执行结果可以得出,子进程在退出时给父进程发送了SIGCHLD
信号。
当然还有一种防止僵尸进程的方法:父进程调 用sigaction
将SIGCHLD
的处理动作置为SIG_IGN
,这样fork
出来的子进程在终止时会自动清理掉,不会产生僵尸进程,也不会通知父进程:
int main()
{struct sigaction act;memset(&act,0,sizeof(act));act.sa_handler=SIG_IGN;sigaction(SIGCHLD,&act,nullptr);pid_t id=fork();if(id==0){sleep(5);exit(0);}while(true){cout<<"I am father process"<<endl;sleep(1);}return 0;
}
这个结果不方便展示,你自己尝试一下。
本篇就分享到这里了,如果文章的知识,或代码有错误请您联系我,不胜感激!!!
相关文章:
从内核到应用层:深度剖析信号捕捉技术栈(含sigaction系统调用/SIGCHLD回收/volatile内存屏障)
Linux系列 文章目录 Linux系列前言一、进程对信号的捕捉1.1 内核对信号的捕捉1.2 sigaction()函数1.3 信号集的修改时机 二、可重入函数三、volatile关键字四、SIGCHLD信号 前言 Linux系统中,信号捕捉是指进程可以通过设置信号处理函数来响应特定信号。通过信号捕捉…...
【KWDB 创作者计划】_嵌入式硬件篇---寄存器与存储器截断与溢出
文章目录 前言一、寄存器与存储器1. 定义与基本概念寄存器(Register)位置功能特点存储器(Memory)位置功能特点2. 关键区别3. 层级关系与协作存储层次结构协作示例4. 为什么需要寄存器性能优化指令支持减少总线竞争5. 其他寄存器类型专用寄存器程序计数器(PC)栈指针(SP)…...
Python torchvision.datasets 下常用数据集配置和使用方法
torchvision.datasets 提供了许多常用的数据集类,以下是一些常用方法(datasets中有大量数据集处理方法,这里仅展示了部分数据集处理方法)及其实现类的介绍、用法和输入参数解释: CIFAR CIFAR10 :包含 10 个…...
unity使用iTextSharp生成PDF文件
iTextSharp 可以在VS中工具下面得NuGet包管理器中下载 ,具体操作可以搜一下 很多 , 我直接把我得生成pdf代码附上 我这个是生成我一个csv文件内容和图片 using System.IO; using UnityEngine; using iTextSharp.text; using iTextSharp.text.pdf; using…...
django admin 添加自定义页面
在Django中,你可以通过多种方式向Django Admin添加自定义页面。以下是一些常见的方法: 方法1:使用ModelAdmin的get_urls()方法 如果你只是想添加一个简单的页面来展示信息,你可以在你的ModelAdmin类中重写get_urls()方法。 from…...
Java并发编程|CompletableFuture原理与实战:从链式操作到异步编排
🔥 本文系统讲解Java并发编程核心类CompletableFuture,涵盖线程池配置策略、异步编程实践、异常处理机制等关键技术。通过电商订单系统与物流调度实战案例,深度解析:1)CompletableFuture链式操作与异步编排 2)多线程任务聚合与结果处理 3)生产级异常处理方案 4)组合操…...
动态自适应分区算法(DAPS)设计流程详解
动态自适应分区算法(Dynamic Adaptive Partitioning System, DAPS)是一种通过实时监测系统状态并动态调整资源分配策略的智能算法,广泛应用于缓存优化、分布式系统、工业制造等领域。本文将从设计流程的核心步骤出发,结合数学模型…...
优雅实现网页弹窗提示功能:JavaScript与CSS完美结合
在现代Web开发中,弹窗提示是提升用户体验的重要元素之一。本文将深入探讨如何实现一个优雅、可复用的弹窗提示系统,避免常见问题如重复触发、样式混乱等。 核心代码解析 // 控制弹窗是否可以显示的标志 let alertStatus true;// 显示提示信息 functio…...
LeetCode-Hot100
数组 1.数组——最大子数组和 解题思路:动态规划 动态规划解决问题的步骤:1.理解题意。题目要求只返回结果,不要求得到最大的连续子数组的哪一个,这样的问题常常可以用动态规划。 2.定义子问题:eg:以 −…...
【Redis】有序集合类型Sortedset 常用命令详解
此类型和 set 一样也是 string 类型元素的集合,且不允许重复的元素 不同的是每个元素都会关联一个double类型的分数,redis正是通过分数来为集合中的成员进行从小到大的排序 有序集合的成员是唯一,但分数(score)却可以重复 1. zadd - 添加 语法…...
前缀和-724.寻找数组的中心下标-力扣(LeetCode)
一、题目解析 我们需要求出中心下标处两边的和是否相等。 二、算法解析 解法1:暴力枚举 O(n*2)(时间复杂度) 固定i,计算[0,i-1]的和,计算[i1,n-1]的和,然后比较是否相等。遍历i为n次,每次计算n-1个数据的值ÿ…...
缓存与数据库数据一致性:旁路缓存、读写穿透和异步写入模式解析
旁路缓存模式、读写穿透模式和异步缓存写入模式是三种常见的缓存使用模式,以下是对三种经典缓存使用模式在缓存与数据库数据一致性方面更全面的分析: 一、旁路缓存模式(Cache - Aside Pattern) 1.数据读取流程 应用程序首先向缓…...
HTML邮件背景图兼容 Outlook
在 HTML 邮件中设置背景图片时,Outlook(尤其是桌面版的 Outlook for Windows)经常不会正确显示背景图,这是因为outlook 是使用 Word 作为邮件渲染引擎,而不是标准的 HTML/CSS 渲染方式。 推荐的解决方案:使…...
Linux之七大难命令(The Seven Difficult Commands of Linux)
Linux之七大难命令 、背景 作为Linux的初学者,肯定要先掌握高频使用的指令,这样才能让Linux的学习在短时间内事半功倍。但是,有些指令虽然功能强大,但因参数多而让初学者们很害怕,今天介绍Linux中高频使用࿰…...
每日Html 4.24
📚 每日一个Html小知识 🐍 每天花1分钟,解锁一个Html实用技巧/冷知识!无论是新手还是老手,这里都有让你眼前一亮的编程干货。 ✨ 今日主题:<dialog> 标签 💡 你知道吗? 浏览…...
YOLOv11改进-双Backbone架构:利用双backbone提高yolo11目标检测的精度
一、引言:为什么我们需要双Backbone? 在目标检测任务中,YOLO系列模型因其高效的端到端检测能力而备受青睐。然而,传统YOLO模型大多采用单一Backbone结构,即利用一个卷积神经网络(CNN)作为特征提…...
嵌入式Linux驱动开发:LED实验
在嵌入式Linux驱动开发中,LED实验可以通过多种方式实现,主要包括设备树下的LED实验、新字符设备驱动的LED实验和GPIO子系统的LED实验。这三种方式在硬件资源管理、驱动架构和开发流程上有显著区别,下面从多个维度进行对比分析: 1.…...
系统与网络安全------弹性交换网络(2)
资料整理于网络资料、书本资料、AI,仅供个人学习参考。 Eth-Trunk 组网中经常会遇到的问题 链路聚合技术 概述 Eth-Trunk(链路聚合技术)作为一种捆绑技术,可以把多个独立的物理接口绑定在一起,作为一个大带宽的逻辑…...
Kotlin Multiplatform--01:项目结构基础
Kotlin Multiplatform--01:项目结构基础 引言Common CodeTargetsExpected 和 actual1.使用函数2.使用接口 引言 以下为使用 Android Studio 创建的默认 Kotlin Multiplatform 的项目结构,本章将对项目结构进行简单介绍,让读者对 Kotlin Multi…...
SEO(Search Engine Optimization,搜索引擎优化)相关知识点
SEO(Search Engine Optimization)是指搜索引擎优化,是计算机领域中通过技术手段和内容策略,提升网站在搜索引擎(如Google、Bing、百度)中自然(非付费)排名的系统性方法。是一种通过优…...
轻松完成视频创作,在线视频编辑器,无需下载软件,功能多样实用!
小白工具的在线视频编辑https://www.xiaobaitool.net/videos/edit/ 功能丰富、操作简便,在线裁剪或编辑视频工具,轻松完成视频创作能满足多种视频编辑需求。 格式支持广泛:可编辑超百种视频格式,基本涵盖常见和小众视频格式&#…...
typescript学习笔记(全)
1.安装 全局安装 npm i -g typescript局部安装 npm i typescript初始化 tsc --init就会在所在目录下创建出一个tsconfig.json的ts配置文件 2.编译 如果是全局安装 tsc index.ts就会在同目录下编译出一个index.js文件 如果是局部安装 npx tsc index.ts3.特性 1.静态类…...
centos挂载新的硬盘
如果要将 nvme0n1 挂载到 /data 目录(而不是 /),操作会更简单,无需迁移系统文件。以下是详细步骤: 1. 检查磁盘情况 lsblk输出: NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 …...
客户案例 | 西昊智能家具:日事清【目标】【日程】【项目】助力高效OKR管理
随着社会现代化、科技化的发展,人们越来越青睐智能化的家具产品,以此来提升家居的安全性、便利性与舒适性。目前,智能家具的行业规模正在不断扩张,产业也逐渐步入高质量增长模式。面对繁荣的市场前景,西昊智能家具与日…...
16.磁环在EMC设计中的选型与运用
磁环在EMC设计中的选型与运用 1. 磁环选型的参数和注意事项2. 磁环的选型方法3. 非晶磁环 1. 磁环选型的参数和注意事项 (1)损耗电阻R(f)和L(f)是频率的函数,因此IL也是频率的函数; (2)fL段,R(f…...
oralce 查询未提交事务和终止提交事务
查询提交记录 SELECT s.sid,s.serial#,s.username,s.status,t.start_time,t.used_ublk,t.log_io,t.phy_io FROM v$session sJOIN v$transaction t ON s.saddr t.ses_addr; 查到的记录如下: 如果要终止第一次提交,如下操作 ALTER SYSTEM KILL SESSION…...
智能小助手部署 Win10 + ollama的Deepseek + CentOS+ maxKB
一、适用场景 1、企业内部知识管理 (1)快速查询政策与流程文档: 员工通过自然语言提问,MaxKB 能迅速定位相关文档并给出准确答案,减少人工检索成本,提升企业内部知识获取的效率。 (2࿰…...
CentOS 7 系统中,防火墙要怎么使用?
在 CentOS 7 系统中,默认有两个防火墙管理工具: firewalld(默认的动态防火墙,基于 D-Bus 管理) iptables(传统的静态防火墙,底层由 netfilter 提供支持) 是否需要关闭这两个防火墙…...
网页版 deepseek 对话问答内容导出为 PDF 文件和 Word 文件的浏览器插件下载安装和使用说明
文章目录 网页版 deepseek 浏览器扩展应用程序插件1. 预览效果2. 功能介绍3. 浏览器扩展应用程序下载3.1. 下载方式13.2. 下载方式24. 安装教程4.1. Chrome 浏览器安装步骤4.2. Edge 浏览器安装步骤5. 使用说明网页版 deepseek 浏览器扩展应用程序插件 1. 预览效果 预览效果 导…...
MySQL 报错解析:SQLSyntaxErrorException caused by extra comma before FROM
一、遇到的错误 在日常开发中,尤其是使用 MyBatis 等 ORM 框架操作 SQL 时,我们经常会遇到类似下面的错误。 ### Error querying database. Cause: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that co…...
高光谱相机在生物医学中的应用:病理分析、智慧中医与成分分析
高光谱成像技术(Hyperspectral Imaging, HSI)通过捕捉物质的连续光谱信息与空间信息,形成“光谱立方体”,能够揭示传统成像技术无法获取的分子级特征。作为国内光谱技术领域的领军企业,深圳市中达瑞和科技有限公司依托…...
2025 年“泰迪杯”数据挖掘挑战赛B题——基于穿戴装备的身体活动监测问题分析
摘要 本文聚焦于基于穿戴设备采集的加速度计数据,深入研究志愿者在日常活动中的行为特征,构建了多个数学建模框架,实现从身体活动监测、能耗预测、睡眠阶段识别到久坐预警等多个目标。我们依托于多源数据融合与机器学习模型,对人体活动状态进行识别与分析,为健康管理、行…...
10.接口而非实现编程
10.接口而非实现编程 目录介绍 01.接口编程原则 1.1 接口指导思想 02.如何理解接口 2.1 重点搞清楚接口2.2 抽象的思想 03.来看一个案例 3.1 图片存储的案例3.2 业务拓展问题3.3 代码演变设计思想3.4 重构后的代码 04.定义接口的场景 4.1 要有接口意识4.2 接口具体的场景4.3 …...
基于大语言模型的AI智能体开发:构建具备工具使用能力的智能助手
本文将结合大语言模型(LLM)与工具调用能力,构建新一代AI智能体系统。通过ReAct框架实现智能思考-行动循环,集成网络搜索、计算器、API调用等外部工具,并基于LangChain实现可扩展的智能体架构。 一、新一代AI智能体技术…...
DS B/B+/B*树及其应用(21)
文章目录 前言一、常见的搜索结构内查找外查找 二、B树的概念三、B树的插入分析四、B树的插入实现B树的节点设计B树的查找B树插入Key / Key & Value的过程B树的完整插入代码B树的中序遍历B树的删除B树的性能分析 五、B树六、B*树七、B树系列总结及其应用总结 前言 我们计算…...
04-stm32的标准外设库
一、概述 1、STM32标准外设库(Standard Peripheral Library)是STMicroelectronics为STM32系列微控制器提供的一个软件库,它提供了一组API函数来简化对STM32微控制器硬件的访问。这个库包含了对各种外设(如GPIO、USART、SPI、I2C等…...
ORACLE RAC环境使用ASM机制零宕机时间更换存储的实践
ORACLE RAC使用存储,随时系统的发展,磁盘空间以及存储的老化、更换是一个典型的动作;基于ASM数据自动均衡分配到各个磁盘LUN的特性,可以使用此方式进行在线的迁移,ORACLE MOS上有一个文档:中文版࿱…...
03_JavaScript
文章目录 一、概述1.1、JavaScript简介1.2、JavaScript组成部分1.3、为什么要学习JavaScript1.4、学习的目的1.5、JavaScript与Java的关系 二、使用位置及运行说明2.1、使用位置2.2、如何运行 三、JavaScript基础语法3.1、变量3.2、运算符3.3、控制流程3.3.1、分支结构3.3.2、循…...
Kafka消息可视化工具Offset Explorer
参考文献 Kafka消息可视化工具:Offset Explorer(原名kafka Tool)的使用方法【转】 - paul_hch - 博客园 https://zhuanlan.zhihu.com/p/722232008 正文 官网下载地址为Offset Explorer 双击offsetexplorer_64bit.exe 安装 双击 使用kafka…...
AXP2101入门
目录 核心功能与特性封装与配置安全与可靠性 AXP2101 是一款由全志公司开发的单电池 NVDC 电源管理集成电路(PMIC),专为锂离子/锂聚合物单电池应用设计,适用于需要多通道电源输出的设备。 核心功能与特性 1.输入与充电管理 输入…...
Bytebase 取得 SOC 2 Type 1 认证
我们很高兴地宣布,Bytebase 已成功取得 SOC 2 Type 1 认证,印证了我们在数据库 DevSecOps 平台始终以最高标准保障安全性、可用性和保密性的承诺。 为了实现并维持 SOC 2 合规性,我们与 Vanta 合作进行自动安全监控和合规性验证。审计由独立…...
反爬系列 IP 限制与频率封禁应对指南
在数据采集领域,IP 限制与频率封禁是反爬机制中最常见的防御手段。随着网站安全策略的升级,单靠传统爬虫技术已难以应对高强度的检测。本文将从反爬机制解析、实战应对策略两个维度,系统讲解如何突破 IP 限制与频率封禁。 一、反爬机制解析 …...
Java的进阶学习
注解 Java注解(Annotation)又称为Java标注,是JDK5.0引入的一种注释机制,可以用在类、方法、变量、参数成员上,在编译期间,会被编译到字节码文件中,运行时通过反射机制获得注解内容进行解析。 内置注解 Java语言已经定…...
从零开始学习SLAM|技术路线
概念 视觉SLAM(Simultaneous Localization and Mapping)系统中,整个过程通常分为 前端 和 后端 两个主要部分。前端处理的是从传感器数据(如相机图像、激光雷达等)中提取和处理信息,用于实时定位和建图&am…...
vue3:十一、主页面布局(修改顶部导航栏样式-右侧:用户信息+退出登录+全屏显示)
一、效果 完成效果,增加顶部导航栏,右侧用户信息(其中个人中心需要后续进行页面开发,这里只写了退出登录功能),以及全屏功能 二、搭建并引入右侧组件 将右侧内容封装到单独的组件,直接引入(像左侧导航条等内容也是可以做成这种形式) 1、新建右侧组件的页面 在layout中…...
车载客流记录仪简介
一、产品概述 车载客流记录仪技术是采用智能视频分析算法,通过人体形态特征(头部和肩部)及上下车的运动规律研判,在设定区域内分析出上下车人数数量,实现相关人数数据的统计和记录。能够为公共交通企业、公共交通管理…...
2025新版懒人精灵零基础及各板块核心系统视频教程-全分辨率免ROOT自动化开发
2025新版懒人精灵零基础安装调试lua基础UI设计交互常用方法封装项目实战项目打包安装板块-视频教程(初学者必修课) 1.懒人精灵核心API基础和lua基础视频教程:https://www.bilibili.com/video/BV1Vm9kYJEfM/ 其它板块教程(包含:对接AI、实战、插件、UI、…...
从 Java 到 Kotlin:在现有项目中迁移的最佳实践!
全文目录: 开篇语 1. 为什么选择 Kotlin?1.1 Kotlin 与 Java 的兼容性1.2 Kotlin 的优势1.3 Kotlin 的挑战 2. Kotlin 迁移最佳实践2.1 渐进式迁移2.1.1 步骤一:将 Kotlin 集成到现有的构建工具中2.1.2 步骤二:逐步迁移2.1.3 步骤…...
矩阵运营的限流问题本质上是平台与创作者之间的流量博弈
矩阵运营的限流问题本质上是平台与创作者之间的流量博弈,要系统性解决这一问题,需从技术规避、内容优化、运营策略三个维度构建防御体系。以下结合平台算法逻辑与实战案例,深度解析限流成因及破解之道: 一、技术层:突…...
一种Spark程序运行指标的采集与任务诊断实现方式
一种Spark程序运行指标的采集与任务诊断实现方式 编写时间:2023年8月2日 第一次校准时间:2023年8月2日 文章目录 一种Spark程序运行指标的采集与任务诊断实现方式数据链路采集器的类图CustomSparkListener采集的指标task相关stage相关Job相关Executors相关诊断诊断分类调度阶…...