当前位置: 首页 > news >正文

用户态到内核态:Linux信号传递的九重门(一)

1. 信号的认识

1.1. 信号的特点

  • 异步通知:信号是异步的,发送信号的进程无需等待接收进程的响应。
  • 预定义事件:每个信号对应一个预定义的事件(如终止、中断、段错误等)。
  • 轻量级:信号不携带大量数据,仅通过编号(整数)标识不同事件。

1.2. 技术应用层面的信号

1.2.1. 一个样例

//test.cpp#include<iostream>
#include<unistd.h>int main()
{while(1){std::cout<< "I am a signal!"<<std::endl;sleep(1);}return 0;
}

 ⽤户输⼊命令,在Shell下启动⼀个前台进程。⽤⼾按下 Ctrl+C ,这个键盘输⼊产⽣⼀个硬件中断,被OS获取,解释成信号,发送给⽬标前台进程。前台进程因为收到信号,进⽽引起进程退出。

1.2.2. 一个系统调用函数 

NAME
        signal - ANSI C signal handling
SYNOPSIS
        # include <signal.h>
        typedef void (* sighandler_t )( int );
        sighandler_t signal ( int signum, sighandler_t handler);
参数说明:
signum :信号编号 [ 后⾯解释,只需要知道是数字即可。
handler :函数指针,表⽰更改信号的处理动作,当收到对应的信号,就回调执⾏ handler方法。

⽽其实, Ctrl+C 的本质是向前台进程发送 SIGINT 2 号信号,我们证明⼀下,这⾥需要引⼊⼀

个系统调⽤函数。
Test1.cpp
#include<iostream>
#include<unistd.h>
#include<signal.h>void handler(int signum)
{std::cout<<"我是"<<signum<<"号信号!"<<std::endl;
}int main()
{signal(2, handler);while(1){std::cout<< "I am a signal! My pid is:"<<getpid()<<std::endl;sleep(1);}return 0;
}

执行结果:

1.3. 信号概念

信号是进程之间事件异步通知的⼀种⽅式,属于软中断。

1.3.1. 查看信号

编号34以上的是实时信号,此博客不讨论实时信号。这些信号各⾃在什么条件下产⽣,默认的处理动作是什么,在signal(7)中都有详细说明: man 7 signal 

 1.3.2. 信号处理

可选的处理动作有以下三种:忽略信号,自定义处理信号,默认处理。

  • 忽略信号

        Test2.cpp

#include<iostream>
#include<unistd.h>
#include<signal.h>int main()
{//设置2号信号的处理方式时SIG_IGN(忽略指定信号)宏signal(2, SIG_IGN);while(1){std::cout<< "I am a signal! My pid is:"<<getpid()<<std::endl;sleep(1);}return 0;
}

 运行结果:无论输入多少次的2号信号CTRL+C进程都没有终止。

  • 默认处理

        Test3.cpp

#include<iostream>
#include<unistd.h>
#include<signal.h>int main()
{while(1){std::cout<< "I am a signal! My pid is:"<<getpid()<<std::endl;sleep(1);}return 0;
}

运行结果:进程直接终止

  • 自定义处理       

        Test4.cpp

#include<iostream>
#include<unistd.h>
#include<signal.h>void handler(int signum)
{std::cout<<"我是"<<signum<<"号信号!"<<std::endl;
}int main()
{signal(2, handler);while(1){std::cout<< "I am a signal! My pid is:"<<getpid()<<std::endl;sleep(1);}return 0;
}

运行结果,进程接受2号信号之后执行自定义方法

2. 产生信号

2.1. 通过命令行输入产生信号

  • Ctrl+C (SIGINT) 已经验证过,这⾥不再重复。 
  • Ctrl+\(SIGQUIT)可以发送终⽌信号并⽣成core dump⽂件,⽤于事后调试。
  • Ctrl+Z(SIGTSTP)可以发送停⽌信号,将当前前台进程挂起到后台等。

2.2. 调⽤系统命令向进程发信号

测试代码:

#include <iostream>
#include <unistd.h>
#include <signal.h>int main()
{while(true){std::cout<<"I am waiting signal, My pid is:"<<getpid()<<std::endl;sleep(1);}return 0;
}

 程序正常运行,我们在另外的终端输入kill -9 杀死正在运行的进程。

2.3. 使用函数产生信号

2.3.1. kill

kill 命令是调⽤ kill 函数实现的。 kill 函数可以给⼀个指定的进程发送指定的信号。

NAME
        kill - send signal to a process
SYNOPSIS
        # include <sys/types.h>
        # include <signal.h>
        int kill ( pid_t pid, int sig);
RETURN VALUE
        On success (at least one signal was sent), zero is returned. On error,  -1 is returned, and errno is set appropriately.

 自定义实现kill命令

#include<iostream>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>// mykill -signumber pid
int main(int argc, char *argv[])
{if(argc != 3){std::cout<<"There is an error in your input format. Please re-enter it! "<<std::endl;exit(1);}int signum = std::stoi(argv[1]+1);int pid = std::stoi(argv[2]);int n = kill(pid, signum);return 0;
}

2.3.2 raise

raise 函数可以给当前进程发送指定的信号(⾃⼰给⾃⼰发信号)。
NAME
        raise - send a signal to the caller
SYNOPSIS
        # include <signal.h>
        int raise ( int sig);
RETURN VALUE
        raise () returns 0 on success, and nonzero for failure.

测试代码:

#include <iostream>
#include <signal.h>
#include <unistd.h>int main()
{int cnt = 0;while (true){cnt++;std::cout << "I am waiting signals! My pid is:" << getpid() << std::endl;sleep(1);if (cnt == 6){raise(2);}}return 0;
}

运行结果:程序执行6条cout语句之后自己给自己发送2号信号

 2.3.3. abort

abort 函数使当前进程接收到信号⽽异常终⽌。
NAME
        abort - cause abnormal process termination
SYNOPSIS
        # include <stdlib.h>
        void abort ( void );
RETURN VALUE
        The abort () function never returns.
// 就像 exit 函数⼀样 ,abort 函数总是会成功的 , 所以没有返回值

测试代码:

#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>void handler(int signumber)
{std::cout << "获取了⼀个信号: " << signumber << std::endl;
}int main()
{signal(SIGABRT, handler);while (true){sleep(1);abort();}
}

运行结果:

2.4. 由软条件产生信号

SIGPIPE 是⼀种由软件条件产⽣的信号,在“管道”中已经介绍过了。本节主要介绍 alarm 函数和 SIGALRM 信号。

NAME
        alarm - set an alarm clock for delivery of a signal
SYNOPSIS
        # include <unistd.h>
        unsigned int alarm ( unsigned int seconds);
RETURN VALUE
        alarm () returns the number of seconds remaining until any previously
        scheduled alarm was due to be delivered, or zero if there was no previ
        ously scheduled alarm.

调⽤ alarm 函数可以设定⼀个闹钟,也就是告诉内核在 seconds 秒之后给当前进程发 送SIGALRM 信号,该信号的默认处理动作是终⽌当前进程。这个函数的返回值是0或者是以前设定的闹钟时间还余下的秒数。

2.4.1. 通过alarm验证体会IO效率

程序的作⽤是1秒钟之内不停地数数,1秒钟到了就被SIGALRM信号终⽌。
必要的时候,对SIGALRM信号进⾏捕捉。
alarm1.cpp(IO多)
#include <iostream>
#include <unistd.h>
#include <signal.h>int main()
{int count = 0;alarm(1);while (true){std::cout << "count : "<< count << std::endl;count++;}return 0;
}

alarm2.cpp(IO少)

#include <iostream>
#include <unistd.h>
#include <signal.h>int count = 0;void handler(int signumber)
{std::cout << "count : " << count << std::endl;exit(0);
}int main()
{signal(SIGALRM, handler);alarm(1);while (true){count++;}return 0;
}

2.4.2. 如何理解软件条件

在操作系统中,信号的软件条件指的是由软件内部状态或特定软件操作触发的信号产⽣机制。这些条件包括但不限于定时器超时(如alarm函数设定的时间到达)、软件异常(如向已关闭的管道写数据产⽣的SIGPIPE信号)等。当这些软件条件满⾜时,操作系统会向相关进程发送相应的信号,以通知进程进⾏相应的处理。简⽽⾔之,软件条件是因操作系统内部或外部软件操作⽽触发的信号产⽣。

 2.5. 硬件异常产生信号

硬件异常被硬件以某种⽅式被硬件检测到并通知内核,然后内核向当前进程发送适当的信号。例如当前进程执⾏了除以0的指令, CPU的运算单元会产⽣异常, 内核将这个异常解释为SIGFPE信号发送给进程。再⽐如当前进程访问了⾮法内存地址, MMU会产⽣异常,内核将这个异常解释为SIGSEGV信号发送给进程。

2.5.1. 模拟除0

测试代码:

#include <stdio.h>
#include <signal.h>void handler(int sig)
{printf("catch a sig : %d\n", sig);
}int main()
{// signal(SIGFPE, handler); // 8) SIGFPEsleep(1);int a = 10;a /= 0;while (1);return 0;
}

运行结果:

2.5.2. 模拟野指针

测试代码:

#include <stdio.h>
#include <signal.h>void handler(int sig)
{printf("catch a sig : %d\n", sig);
}int main()
{// signal(SIGSEGV, handler);sleep(1);int *p = NULL;*p = 100;while (1);return 0;
}

运行结果:

相关文章:

用户态到内核态:Linux信号传递的九重门(一)

1. 信号的认识 1.1. 信号的特点 异步通知&#xff1a;信号是异步的&#xff0c;发送信号的进程无需等待接收进程的响应。预定义事件&#xff1a;每个信号对应一个预定义的事件&#xff08;如终止、中断、段错误等&#xff09;。 轻量级&#xff1a;信号不携带大量数据&#xf…...

c语言第一个小游戏:贪吃蛇小游戏01

hello啊大家好 今天我们用一个小游戏来增强我们的c语言&#xff01; 那就是贪吃蛇 为什么要做一个贪吃蛇小游戏呢&#xff1f; 因为这个小游戏所涉及到的知识有c语言的指针、数组、链表、函数等等可以让我们通过这个游戏来巩固c语言&#xff0c;进一步认识c语言。 一.我们先…...

JAVA EE_网络原理_网络层

晨雾散尽&#xff0c;花影清晰。 ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ ----------陳長生. ❀主页&#xff1a;陳長生.-CSDN博客❀ &#x1f4d5;上一篇&#xff1a;数据库Mysql_联…...

前端性能指标及优化策略——从加载、渲染和交互阶段分别解读详解并以Webpack+Vue项目为例进行解读

按照加载阶段、渲染阶段和交互阶段三个维度进行系统性阐述&#xff1a; 在现代 Web 开发中&#xff0c;性能不再是锦上添花&#xff0c;而是决定用户体验与业务成败的关键因素。为了全面监控与优化网页性能&#xff0c;我们可以将性能指标划分为加载阶段、渲染阶段、和交互阶段…...

Flink 系列之十五 - 高级概念 - 窗口

之前做过数据平台&#xff0c;对于实时数据采集&#xff0c;使用了Flink。现在想想&#xff0c;在数据开发平台中&#xff0c;Flink的身影几乎无处不在&#xff0c;由于之前是边用边学&#xff0c;总体有点混乱&#xff0c;借此空隙&#xff0c;整理一下Flink的内容&#xff0c…...

控制台打印带格式内容

1. 场景 很多软件会在控制台打印带颜色和格式的文字&#xff0c;需要使用转义符实现这个功能。 2. 详细说明 2.1.转义符说明 样式开始&#xff1a;\033[参数1;参数2;参数3m 可以多个参数叠加&#xff0c;若同一类型的参数&#xff08;如字体颜色&#xff09;设置了多个&…...

Linux为啥会重新设置中断请求号与中断向量号之间的关系?

Linux内核重新设置中断请求号&#xff08;IRQ&#xff09;与中断向量号之间的关系&#xff0c;主要出于以下核心原因和设计考量&#xff1a; ​1. 硬件多样性与抽象需求​ ​硬件中断号&#xff08;HW Interrupt ID&#xff09;的差异​ 不同处理器架构的中断控制器&#xff08…...

自然语言处理NLP中的连续词袋(Continuous bag of words,CBOW)方法、优势、作用和程序举例

自然语言处理NLP中的连续词袋&#xff08;Continuous bag of words&#xff0c;CBOW&#xff09;方法、优势、作用和程序举例 目录 自然语言处理NLP中的连续词袋&#xff08;Continuous bag of words&#xff0c;CBOW&#xff09;方法、优势、作用和程序举例一、连续词袋( Cont…...

计算机网络笔记(二十二)——4.4网际控制报文协议ICMP

4.4.1ICMP报文的种类 ICMP&#xff08;Internet Control Message Protocol&#xff09;是IP协议的辅助协议&#xff0c;主要用于传递控制消息、错误报告和诊断信息。其报文分为两大类&#xff1a;查询报文和错误报告报文。 1. 错误报告报文&#xff08;Error Messages&#x…...

【AI论文】作为评判者的感知代理:评估大型语言模型中的高阶社会认知

摘要&#xff1a;评估大型语言模型&#xff08;LLM&#xff09;对人类的理解程度&#xff0c;而不仅仅是文本&#xff0c;仍然是一个开放的挑战。 为了弥合这一差距&#xff0c;我们引入了Sentient Agent作为评判者&#xff08;SAGE&#xff09;&#xff0c;这是一个自动评估框…...

Kubernetes生产实战(二十七):精准追踪Pod数据存储位置

在生产环境中&#xff0c;快速定位Pod数据的物理存储位置是运维人员的基本功。本文将揭秘Kubernetes存储系统的核心原理&#xff0c;并提供一套经过实战检验的定位方法体系。 一、存储架构全景图 K8S存储架构 Pod --> Volume Mount --> PVC --> PV --> Storage P…...

极新携手火山引擎,共探AI时代生态共建的破局点与增长引擎

在生成式AI与行业大模型的双重驱动下&#xff0c;人工智能正以前所未有的速度重构互联网产业生态。从内容创作、用户交互到商业决策&#xff0c;AI技术渗透至产品研发、运营的全链条&#xff0c;推动效率跃升与创新模式变革。然而&#xff0c;面对AI技术迭代的爆发期&#xff0…...

[SIGPIPE 错误] 一个 Linux socket 程序,没有任何报错打印直接退出程序

1. 问题 在编写一个程序的时候&#xff0c;当然程序很复杂&#xff0c;遇到了一个 Linux socket 程序&#xff0c;没有任何报错打印直接退出程序&#xff0c;但是在程序里面我有很多 error log &#xff0c;在程序退出的时候完全没有打印。为了说明问题&#xff0c;我编写了一…...

Qt 界面优化(绘图)

目录 1. 绘图基本概念2. 绘制各种形状2.1 绘制线段2.2 绘制矩形2.3 绘制圆形2.4 绘制文本2.5 设置画笔2.6 设置画刷 3. 绘制图片3.1 绘制简单图片3.2 平移图片3.3 缩放图片3.4 旋转图片 4. 其他设置4.1 移动画家位置4.2 保存/加载画家的状态 5. 特殊的绘图设备5.1 QPixmap5.2 Q…...

AQS(AbstractQueuedSynchronizer)解析

文章目录 一、AQS简介二、核心设计思想2.1 核心设计思想回顾2.2 CLH锁队列简介2.3 AQS对CLH队列的改动及其原因 三、核心组件详解3.1 state 状态变量3.2 同步队列 (FIFO双向链表) 四、核心方法深度解析4.1 获取同步状态 (独占模式) - acquire(int arg)4.2 释放同步状态 (独占模…...

Java并发编程常见问题与陷阱解析

引言 随着计算机硬件技术的飞速发展&#xff0c;多核处理器已经变得普遍&#xff0c;Java并发编程的重要性也日益凸显。然而&#xff0c;多线程编程并非易事&#xff0c;其中充满了许多潜在的问题和陷阱。作为一名Java开发工程师&#xff0c;掌握并发编程的常见问题及其解决方案…...

DEEPPOLAR:通过深度学习发明非线性大核极坐标码(1)

原文&#xff1a;《DEEPPOLAR: Inventing Nonlinear Large-Kernel Polar Codes via Deep Learning》 摘要 信道编码设计的进步是由人类的创造力推动的&#xff0c;而且恰如其分地说&#xff0c;这种进步是零星的。极性码是在Arikan极化核的基础上开发的&#xff0c;代表了编码…...

Java多态详解

Java多态详解 什么是多态&#xff1f; 比如我们说&#xff1a;“驾驶一辆车”&#xff0c;有人开的是自行车&#xff0c;有人开的是摩托车&#xff0c;有人开的是汽车。虽然我们都说“开车”&#xff0c;但“怎么开”是由具体的车类型决定的&#xff1a;“开”是统一的动作&a…...

go程序编译成动态库,使用c进行调用

以下是使用 Go 语言打包成 .so 库并使用 C 语言调用的完整步骤&#xff1a; 1. Go 语言打包成 .so 库 &#xff08;1&#xff09;编写 Go 代码 创建一个 Go 文件&#xff08;如 calculator.go&#xff09;&#xff0c;并定义需要导出的函数。导出的函数名必须以大写字母开头…...

iVX:图形化编程与组件化的强强联合

在数字化浪潮中&#xff0c;软件开发范式正经历着从文本到图形的革命性转变。iVX 作为国产可视化编程领域的领军者&#xff0c;以 “图形化逻辑 组件化架构” 的双重创新&#xff0c;重新定义了软件开发的效率边界。其技术突破不仅体现在开发方式的革新&#xff0c;更通过一系…...

华为配置篇-RSTP/MSTP实验

MSTP 一、简介二、常用命令总结三、实验 一、简介 RSTP&#xff08;快速生成树协议&#xff09;​ RSTP&#xff08;Rapid Spanning Tree Protocol&#xff09;是 STP 的改进版本&#xff0c;基于 ​​IEEE 802.1w 标准​​&#xff0c;核心目标是解决传统 STP 收敛速度慢的问…...

端口号被占用怎么解决

windows环境下端口号被占用怎么解决 win r 快捷键打开cmd输入netstat -ano|findstr 端口号 通过这个命令找到pidtaskkill /pid pid端口号 /t /f 如下图所示 命令解读 netstat 是一个网络统计工具&#xff0c;它可以显示协议统计信息和当前的TCP/IP网络连接。 -a 参数告诉 nets…...

GO语言-导入自定义包

文章目录 1. 项目目录结构2. 创建自定义包3. 初始化模块4. 导入自定义包5. 相对路径导入 在Go语言中导入自定义包需要遵循一定的目录结构和导入规则。以下是详细指南&#xff08;包含两种方式&#xff09;&#xff1a; 1. 项目目录结构 方法1&#xff1a;适用于Go 1.11 &#…...

ES常识5:主分词器、子字段分词器

文章目录 一、主分词器&#xff1a;最基础的文本处理单元主分词器的作用典型主分词器示例 二、其他类型的分词器&#xff1a;解决主分词器的局限性1. 子字段分词器&#xff08;Multi-fields&#xff09;2. 搜索分词器&#xff08;Search Analyzer&#xff09;3. 自定义分词器&a…...

NoSQL数据库技术与应用复习总结【看到最后】

第1章 初识NoSQL 1.1 大数据时代对数据存储的挑战 1.高并发读写需求 2.高效率存储与访问需求 3.高扩展性 1.2 认识NoSQL NoSQL--非关系型、分布式、不提供ACID的数据库设计模式 NoSQL特点 1.易扩展 2.高性能 3.灵活的数据模型 4.高可用 NoSQL拥有一个共同的特点&am…...

单片机-STM32部分:12、I2C

飞书文档https://x509p6c8to.feishu.cn/wiki/MsB7wLebki07eUkAZ1ec12W3nsh 一、简介 IIC协议&#xff0c;又称I2C协议&#xff0c;是由PHILP公司在80年代开发的两线式串行总线&#xff0c;用于连接微控制器及其外围设备&#xff0c;IIC属于半双工同步通信方式。 IIC是一种同步…...

【英语笔记(四)】诠释所有16种英语时态,介绍每种时态下的动词变形!!含有所有时态的的动词变形汇总表格

1 时态的单词构成 1.1 现在 1.1.1 一般现在时态 动词原形动词原形s&#xff08;第三人称单数&#xff09; 1.1.1.1 表达事实 I eat carrots. 我吃胡萝卜&#xff1a;我是吃胡萝卜这种食物的.&#xff08;这个是事实陈述&#xff09; The rabbit eats carrots. 兔子吃胡萝卜…...

【质量管理】什么是过程?

在文章【质量管理】谁是顾客&#xff1f;什么是质量链&#xff1f;-CSDN博客 中我们了解了什么是顾客&#xff0c;顾客不仅仅是企业以外的人&#xff0c;在企业的内部我们也有大大小小的顾客。并且我们了解了什么是质量链&#xff0c;企业内部的各种供给方和客户形成了质量链。…...

效率办公新工具:PDF Reader Pro V5.0功能解析与使用体验

在日常文档处理与数字办公的场景中&#xff0c;PDF 文件依然是主流格式之一。从合同审批、项目文档、财务报表&#xff0c;到技术方案和用户手册&#xff0c;PDF 的编辑、转换、标注、归档需求始终存在。 面对这些需求&#xff0c;越来越多用户希望有一款功能完整、跨平台、智…...

Java对象内存布局和对象头

1、面试题 1&#xff09;说下JUC&#xff0c;AQS的大致流程 CAS自旋锁&#xff0c;是获取不到锁就一直自旋吗&#xff1f; 2&#xff09;CAS和synchronized区别在哪里&#xff0c;为什么CAS好&#xff0c;具体优势在哪里&#xff1f; 3&#xff09;sychro…...

Vue 跨域解决方案及其原理剖析

在现代 Web 开发中&#xff0c;跨域问题是前端开发者经常面临的挑战之一。当使用 Vue.js 构建应用时&#xff0c;跨域请求的处理尤为重要。本文将深入探讨 Vue 解决跨域的多种方法及其背后的原理&#xff0c;帮助开发者更好地理解和应对这一常见问题。 一、跨域问题概述 1. 同…...

TikTok 互动运营干货:AI 助力提升粘性

在 TikTok 运营的众多环节中&#xff0c;与用户的互动是建立紧密联系、提升账号粘性的关键所在。及时且真诚地回复评论和私信&#xff0c;能让用户切实感受到你的关注与尊重&#xff0c;从而极大地增强他们对你的好感与粘性。对于用户提出的问题&#xff0c;要以耐心、专业的态…...

Kids A-Z安卓版:儿童英语启蒙的优质选择

Kids A-Z安卓版 是一款由北美知名分级读物厂商 Learning A-Z 官方推出的英语分级学习应用&#xff0c;也被称为 Raz-Kids app。它专为 K-5 年级的学生设计&#xff0c;提供丰富的英语学习资源和互动学习体验&#xff0c;帮助孩子们在轻松愉快的环境中提升英语能力。通过动画、互…...

接口继承与扩展的使用技巧

在 TypeScript 中&#xff0c;接口继承和扩展是非常强大且灵活的功能&#xff0c;可以帮助我们更高效地管理类型和提高代码的可重用性。接口继承使得一个接口可以从另一个接口继承属性和方法&#xff0c;而接口扩展允许我们通过组合多个接口来构建更复杂的结构。这些特性使得 T…...

【React】Craco 简介

Craco 简介 Craco (Create React App Configuration Override) 是一个用于自定义 Create React App (CRA) 配置的工具&#xff0c;无需 eject&#xff08;弹出&#xff09;项目。 为什么需要 Craco Create React App 虽然提供了零配置的 React 开发体验&#xff0c;但其配置…...

HTML5中的Microdata与历史记录管理详解

Microdata 简介 Microdata 是 HTML5 引入的一种标记方式&#xff0c;用于在网页中嵌入机器可读的语义信息。通过使用 Microdata&#xff0c;开发者可以在 HTML 元素中添加特定的属性&#xff0c;以便搜索引擎和其他工具更好地理解网页内容。 Microdata 的核心属性包括 itemsc…...

UNet网络 图像分割模型学习

UNet 由Ronneberger等人于2015年提出&#xff0c;专门针对医学图像分割任务&#xff0c;解决了早期卷积网络在小样本数据下的效率问题和细节丢失难题。 一 核心创新 1.1对称编码器-解码器结构 实现上下文信息与高分辨率细节的双向融合 如图所示&#xff1a;编码器进行了4步&…...

Babel 深度解析:现代 JavaScript 开发的桥梁

1. 什么是 Babel&#xff1f; Babel 是一个 JavaScript 编译器&#xff08;又称转译器&#xff09;&#xff0c;核心使命是解决 JavaScript 的环境兼容性问题。它允许开发者使用最新的语言特性&#xff08;如 ES6、JSX、TypeScript&#xff09;&#xff0c;同时将代码转换为旧…...

MyBatis源码解读2(2.1、核心对象)

二、MyBatis的核心对象 2.1、核心对象 2.1、MappedStatement MyBatis其实是对JDBC的进一步封装&#xff0c;我们都知道JDBC有几个重要的对象&#xff1a; StatementPrepared StatementCallable StatementResultSet Statement、Prepared Statement、Callable Statement分别…...

03.three官方示例+编辑器+AI快速学习webgl_animation_multiple

本实例主要讲解内容 这个示例展示了Three.js中骨骼动画的高级应用技巧&#xff0c;重点演示了如何使用SkeletonUtils.clone()方法复制模型&#xff0c;并展示了两种不同的骨骼动画管理方式&#xff1a; 独立骨骼模式&#xff1a;每个模型拥有独立的骨骼结构&#xff0c;可播放…...

无锁秒杀系统设计:基于Java的高效实现

引言 在电商促销活动中&#xff0c;秒杀场景是非常常见的。为了确保高并发下的数据一致性、性能以及用户体验&#xff0c;本文将介绍几种不依赖 Redis 实现的无锁秒杀方案&#xff0c;并提供简化后的 Java 代码示例和架构图。 一、基于数据库乐观锁机制 ✅ 实现思路&#xf…...

MyBatis快速入门——实操

默认&#xff1a;电脑搭建好了Maven环境 本次入门实验使用的idea版本&#xff1a;ideaU2022.1 目录 一&#xff1a;前期准备工作 1. 创建一个springboot工程 2. Maven环境配置 3. 在mysql数据库中创建一个user表 4. 编写实体类User 二&#xff1a; 引入MyBatis的相关依赖…...

假如你的项目是springboot+vue怎么解决跨域问题

1. 前端代理&#xff08;开发环境推荐&#xff09; 适用场景&#xff1a;Vue 开发环境调试时&#xff0c;避免直接请求后端接口的跨域问题。 实现步骤&#xff1a; 在 Vue 项目的 vue.config.js 中配置代理&#xff1a; module.exports {devServer: {proxy: {/api: { // 代理…...

OpenResty反向代理

通过在 OpenResty 的配置文件中定义不同的 location 块&#xff0c;将匹配特定 URL 路径的请求转发到不同的后端 FastAPI 应用&#xff08;即使它们运行在不同的端口或甚至是不同的服务器/容器上&#xff09;。 核心思路&#xff1a; 多个 FastAPI 应用实例&#xff1a; 你的每…...

《Effective Python》第1章 Pythonic 思维详解——深入理解 Python 条件表达式(Conditional Expressions)

《Effective Python》第1章 Pythonic 思维详解——深入理解 Python 条件表达式&#xff08;Conditional Expressions&#xff09; 在 Python 中&#xff0c;条件表达式&#xff08;conditional expressions&#xff09;提供了一种简洁的方式来在一行中实现 if/else 的逻辑。它…...

【Typenum】 3 类型位运算(bit.rs)

一、源码 代码定义了一个类型级别的位&#xff08;bit&#xff09;系统&#xff0c;主要用于编译时的类型运算。 //! 类型级比特位实现 //! //! 这些是基础的比特位类型&#xff0c;作为本库中其他数值类型的构建基础 //! //! 已实现的**类型运算符**&#xff1a; //! //! - …...

python:trimesh 用于 STL 文件解析和 3D 操作

python&#xff1a;trimesh 是一个用于处理三维模型的库&#xff0c;支持多种格式的导入导出&#xff0c;比如STL、OBJ等&#xff0c;还包含网格操作、几何计算等功能。 Python Trimesh 库使用指南 安装依赖库 pip install trimesh Downloading trimesh-4.6.8-py3-none-any.w…...

stm32week15

stm32学习 十一.中断 2.NVIC Nested vectored interrupt controller&#xff0c;嵌套向量中断控制器&#xff0c;属于内核(M3/4/7) 中断向量表&#xff1a;定义一块固定的内存&#xff0c;以4字节对齐&#xff0c;存放各个中断服务函数程序的首地址&#xff0c;中断向量表定…...

数据库分库分表实战指南:从原理到落地

1. 为什么要分库分表&#xff1f; 1.1 单库瓶颈表现 存储瓶颈&#xff1a;单表数据超过5000万行&#xff0c;查询性能急剧下降性能瓶颈&#xff1a;单库QPS超过5000后响应延迟显著增加可用性风险&#xff1a;单点故障导致全系统不可用 1.2 突破性优势 --------------------…...

雷达工程师面试题目

雷达工程师面试题目 一、基础知识类 简述雷达的工作原理 请从电磁波的发射、传播、反射以及回波接收处理等环节,详细阐述雷达如何实现对目标的探测、定位与跟踪。 常见雷达体制及其特点 列举至少三种常见的雷达体制(如脉冲雷达、连续波雷达、相控阵雷达等),并分别说明…...