【Linux】信号处理以及补充知识
目录
一、信号被处理的时机:
1、理解:
2、内核态与用户态:
1、概念:
2、重谈地址空间:
3、处理时机:
补充知识:
1、sigaction:
2、函数重入:
3、volatile:
4、SIGCHLD:
前言:
信号在保存后,当OS准备对信号进行处理的时候,还需要到合适的时机才能进行处理,那么什么是合适的时机?
一、信号被处理的时机:
1、理解:
信号的产生是异步的
首先,要将信号进行处理之前就需要让OS知道某个进程收到了信号了,所以进程就需要在合适的时机查查其对应的block,pending,handler表,但是这三个表都属于内核级别的,我们用户级别的进程是不允许访问的,所以这里就自然涉及了进程的用户态和内核态之间的转化
合适的时机:在进程从内核态转化到用户态的时候对信号进行检测,如果有并未被屏蔽就进行处理
怎么进行处理:默认,忽略,用户自定义
2、内核态与用户态:
1、概念:
进程在执行代码的时候不仅仅是只执行用户的代码,还有操作系统的代码,想要访问操作系统就需要变成内核态,执行用户的代码就要变成用户态:
用户态:进程只能访问用户自己的代码和数据
内核态:进程允许访问操作系统的代码和数据
用户态-->内核态
进程时间片到了,进行进程切换的时候
调用系统调用接口:open,read等等
产生异常,中断的时候等等
内核态-->用户态
进程切换完毕
系统调用结束后
异常,中断处理完后
OS是不会收到信号就立即执行的,比如当前我正在进行系统调用或者正在切换进程等等,在从内核态转化为用户态的时候,就进行信号的查询三表和处理信号,所以要等到OS将更重要的事情忙完后,在进程从内核态到用户态的时候就进行信号的检测和处理
2、重谈地址空间:
如下,我们回顾下我们地址空间的知识:
每个进程都有其独有的虚拟地址空间,进程具有独立性
通过页表的映射+MMU机制进行虚拟到物理地址之间的转化
进程都具有其对应的虚拟地址空间,能够让进程以统一的时间看待我们的代码和数据
虚拟地址空间又可分为两个空间0~3GB的空间为用户空间,3~4GB的空间为内核空间
为什么要区分内核空间和用户空间?
因为内核空间中存放的是OS的代码和数据,是不允许进程随便访问的,需要进程切换到内核态才能进行访问,并且规划也能够OS进行更好的管理
其中:用户空间就是我们的代码和数据,当进程在用户态的时候就能够访问这段空间的代码和数据
内核空间中存放的就是OS的代码和数据,这里的虚拟地址通过特有的内核级页表从虚拟地址空间映射到物理内存中,由于OS是最先被加载的程序,所以其映射应该在较为底部的位置
我们知道每一个进程都有其对应的进程地址空间, 那么是不是每一个进程都有其独特的内核空间和内核级页表呢?
答案是只有一份
对应用户空间和用户级页表有很多份的,因为进程具有独立性
但是内核级页表只有一份,内核空间比较特殊,所有进程最终映射到物理内存都是同一块区域,进程只是将操作系统代码和数据映射入自己的进程地址空间而已,其中内核级页表只需将虚拟地址空间映射到物理内存,所有进程都是如此
所以,每一个进程看到的内核空间中的内容,看到的内核级页表资源,最后映射到的物理内存中的代码和数据都是一样的
所以在用户空间的代码区中执行对应的系统调用,
首先将进程从用户态转化到内核态,
然后在自己的内核空间中找到对应的系统调用方法,
然后通过内核级页表映射到物理内存找到对应的代码和数据,
然后在返回(在返回的时候进程从内核态转化为用户态),
这样就相当与在进程自己的进程地址空间中进行系统调用
那么上述的切换是如何进行切换的呢?
首先,我们知道,CR3 寄存器存储当前进程的页目录表物理地址,用于分页机制下的内存管理,
在CPU中同样还有一个叫做ESC寄存器的东西,这个寄存器的作用就是用来表示当前进程的状态:是用户态还是内核态
那么这个寄存器是怎样实现的呢?
在这个寄存器中,有着最后两个比特位,两个比特位有4种表示方式:00 01 10 11,其中只使用两种方式,00和11也就是对应十进制的0和3,
当这个寄存器最后两个比特位为0的时候,表示当前进程处于内核态
当这个寄存器最后两个比特位为1的时候,表示当前进程处于用户态
所以切换进程的状态就需要将ESC寄存器中的最后两个比特位修改为对应的值,CPU为我们提供了一种方法来修改自己的工作状态:int 0x80指令
小总结:
1、每一个进程中的0~3GB中的内容是不一样的,因为进程具有独立性
2、每一个进程中的3~4GB中的内容是一样的,在整个系统中,无论进程再怎么切换, 3~4GB中的内核空间内容是不变的
3、在进程视角:我们进行系统调用,就是在我自己的地址空间中进行执行的
4、操作系统视角:任何一个时刻,都有进程执行,想执行OS的代码可以随时执行
5、操作系统本质是一个基于时钟中断的一个死循环
怎么理解操作系统的执行逻辑呢或者说操作系统的本质是什么?
其可以理解为一种基于中断驱动的“死循环”模型,核心在于通过时钟中断等机制实现任务调度,资源管理和实时响应
主框架循环:
操作系统的核心代码是一个死循环(for(; ;) pause(); ),这个循环并非是空转的,而是通过中断机制被动唤醒的,当没有外部事件(用户输入,I/O完成)或内部事件(如时间片耗尽)时,操作系统会进入低功耗状态或执行空闲任务
其中操作系统本会一直卡在pause()这个行代码暂停,等到发生中断机制,被进程“推着走”才能够让代码得以运行
那有什么中断机制呢?
时钟中断:每过一定很短的时间产生一次,用于更新系统时间、检查进程时间片、触发调度
硬件中断:如键盘输入,由外设通过中断控制器通知CPU
软件中断:如系统调用,允许用户程序访问内核空间
进程是如何被操作系统调用的呢?
进程被调度,就意味着它的时间片到了,操作系统会通过时钟中断,检测到是哪一个进程的时间片到了,然后通过系统调用函数schedule()保存进程的上下文数据,然后选择合适的进程去运行
3、处理时机:
有了上述铺垫的知识,接下来可以理解:
我们前面了解到,在进程从内核态转化到用户态的时候对信号进行检测,处理方式如下图:
对于上述的执行用户自定义有两个问题:
为什么要切回用户态再执行对应的方法:
因为如果在内核态中执行用户自定义的方法,可能自定义方法中存在危害操作系统的代码,这是不安全的
为什么在用户态执行完毕后还要返回内核态再到用户态
需要回到内核态找到进程的上下文,将上下文带出到用户态才行,并且自定义的动作和待返回的进程是属于不同的堆栈,不能够直接返回
对于信号捕捉的理解可以看看下面这张图
如上,这是一个横着的8,然后用一横贯穿,上面是用户态,下面是内核态,注意有4个交点,并且8的交点是在横线下方的也就是在内核态中
接下来解释上图:
四个绿色的圈圈就表示两态之间的切换了四次,当进程时间片到了,进行进程切换,产生异常,中断的时候等等就进行用户态到内核态之间的转化
进程切换完毕,系统调用结束后,异常,中断处理完后进行内核态到用户态之间的转化
此时就进行信号的检测:首先看pending表,如果其为1并且该信号没有被阻塞就执行对应动作,如果被屏蔽或者为0就继续从pending表向下找下一个,以此类推
二、补充知识:
1、sigaction:
其中有个新的结构体:sigaction,其内部成员如下
我们只关心第一个和第三个成员:
成功返回0,失败返回-1,错误码被设置
第一个参数signum:信号编号
第二个参数act: 传入该类结构体,设置屏蔽信号什么的在之前就要设置好
第三个参数oldact:保存修改前的结构体
其中sigaction中的第一个成员变量:就是signal的第二个参数,需要自己设置自定义
第三个成员变量就是屏蔽的信号集,怎么理解呢?
首先我们知道,比如当在处理2号信号的时候,如果sa_mask默认,那么OS就只会屏蔽2号信号,如果还想要屏蔽更多信号,就需要sigaddset(&act.sa_mask,1);这样在待传入结构体中的sa_mask进行更多的设置来屏蔽
void Printpending()
{sigset_t set;sigpending(&set);for(int signo = 31; signo>=1; signo--){if(sigismember(&set,signo)) cout <<"1";else cout<<"0";}cout << endl;
}void myhandler(int signo)
{cout << "get a signo : " << signo << endl;while(1){Printpending();sleep(1);}
}int main()
{struct sigaction act,oact;memset(&act,0,sizeof(act));memset(&oact,0,sizeof(oact));//清空信号集sigemptyset(&act.sa_mask);//添加屏蔽信号sigaddset(&act.sa_mask,1);sigaddset(&act.sa_mask,3);sigaddset(&act.sa_mask,4);sigaddset(&act.sa_mask,9);//设置自定义方法act.sa_handler = myhandler;sigaction(2,&act,&oact); while(1){cout << "i am a process mypid : " << getpid() << endl;sleep(1);}return 0;
}
如上,这样就将1 3 4号都屏蔽了,9号和19号信号可以经过试验发现不可屏蔽,
2、函数重入:
可以被重复进入的函数称为可重入函数
如下是一个场景:
如上,当在insert函数中捕捉到了信号,并且在信号的自定义动作中又调用了insert,这样函数就会重入,这样就会导致函数节点丢失,在释放的时候无法释放node2,就会导致内存泄漏
这就是函数重入导致的内存泄漏问题
我们把这种函数称为可重入函数(注意:这个是特性,不具有褒贬含义)
3、volatile:
int flag;void myhandler(int signo)
{cout << "get a signo : " << signo << endl;flag = 1;
}int main()
{signal(2,myhandler);while(!flag); //flag = 0 为假 !flag 为真cout << "a process quit ! " << endl;return 0;
}
如上,上述本来是一个死循环,但是当给当前进程发送2号信号的时候就会进入我们的自定义函数调用,这个时候在里面将flag修改为1,这样就能够退出while死循环了,并且我们的代码运行起来也是达到预期了
但是在编译中,有个-O1/O2/O3这种的优化,如下,我们把这种优化带着,在运行代码试试
如上,此时发现尽管我们给当前进程发送2号信号,并且也看到了自定义代码中打印的字符串,但是进程却没有退出while这个死循环
这是为什么呢?
这是因为在编译的时候进行了O1的优化
如上,正常情况下,CPU在每次进行逻辑检测的时候,每次都从内存中进行读入,这种IO比较费事,当进行O1的优化之后,就会对整个代码进行检测,此时没有信号就检查不到flag被修改了,此时就会将flag放入逻辑检测的寄存器中,这样,当在自定义中修改了flag,这只是把内存中的flag修改了,但是CPU寄存器中的flag并没有被修改,所以就会一直继续死循环
为了防止这种过度优化,保存内存的可见性,可以在全局变量前面加上volatile关键字修饰,这样就无法将flag放入到寄存器中,老老实实地每次都从内存中进行读入
4、SIGCHLD:
在前面实现进程等待的时候,每次当子进程退出的时候,父进程都需要等待,回收子进程,防止其成为僵尸进程造成内存泄漏问题
父进程有两种方式等待子进程:设置0为阻塞等待或者设置WNOHANG为非阻塞轮询
但是上述两种方式都有缺陷,要么父进程阻塞,不能做其自己的事情,要么每次工作的时候都还要关心关心子进程的状态
那么有没有一种方式能够让父进程不在关心子进程,当子进程退出的时候自动回收呢?
有的有的:
首先要了解:子进程在退出的时候会向父进程发送17号信号,所以我们可以在父进程中将17好信号捕捉,然后在自定义函数中等待,这里设置第一个参数为-1为等待任意进程
void myhandler(int signo)
{pid_t rid = waitpid(-1,nullptr,0);cout << "a signo get : " << signo << " mypid " << getpid() << " rid : " << rid << endl;
}int main()
{signal(17,myhandler);pid_t id = fork();if(id == 0){//childcout << "child process " << getpid() << " myppid : " << getppid() << endl;sleep(5);exit(0);}//fatherwhile(1){cout << "father process " << getpid() << endl;sleep(1);}return 0;
}
如上,这样父进程就可以不用管子进程了,能够完成子进程的自动回收
但是这样还不够,如果有多个子进程呢?能够全部回收吗
这显然是不会的,SIGCHLD这是一个信号,当父进程收到了第一个信号的时候,会将block表中的17号信号置为1使其屏蔽,这样,其他子进程的信号就丢失了,就会导致僵尸进程
那么如何解决呢?
我们在自定义中采取while循环的方式回收即可
当然,还有一种更方便的,但是只能在Linux中有效:
将SIGCHLD这个信号的默认动作设置为忽略,这样父进程不会对其处理,但是当子进程退出之后,OS会对其负责,这样的话就会自动清理资源并回收,不会产生僵尸进程引起内存泄漏
相关文章:
【Linux】信号处理以及补充知识
目录 一、信号被处理的时机: 1、理解: 2、内核态与用户态: 1、概念: 2、重谈地址空间: 3、处理时机: 补充知识: 1、sigaction: 2、函数重入: 3、volatile&…...
如何在rust中解析 windows 的 lnk文件(快捷方式)
一、从标题二开始看😁 这些天在使用rust写一个pc端应用程序,需要解析lnk文件获取lnk的图标以及原程序地址,之前并没有过pc端应用程序开发的经验, 所以在广大的互联网上游荡了两天。额🥺 今天找到了这个库 lnk_parse很…...
大模型系列课程学习-基于Vllm/Ollama/Ktransformers完成Deepseek推理服务部署
1.机器配置及实验说明 基于前期搭建的双卡机器装机教程,配置如下: 硬件名称参数备注CPUE5-2680V42 *2(线程28个)无GPU2080TI-22G 双卡魔改卡系统WSL Unbuntu 22.04.5 LTS虚拟机 本轮实验目的:基于VLLM/Ollama/ktran…...
Unity Shader学习总结
1.帧缓冲区和颜色缓冲区区别 用于存储每帧每个像素颜色信息的缓冲区 帧缓冲区包括:颜色缓冲区 深度缓冲区 模板缓冲区 自定义缓冲区 2.ImageEffectShader是什么 后处理用的shader模版 3.computerShader 独立于渲染管线之外,在显卡上运行,大量…...
Java多线程与高并发专题——什么是阻塞队列?
引入 阻塞队列(Blocking Queue)是一种线程安全的队列数据结构,它的主要特点是: 线程安全:多个线程可以安全地同时访问队列。阻塞操作:当队列为空时,从队列中获取元素的操作会被阻塞࿰…...
【Recon】CTF Web类题目主要类型
CTF Web类题目主要类型 1. 信息搜集类2. 注入类漏洞3. 文件处理漏洞4. 身份验证与会话漏洞5. 服务端漏洞6. 客户端漏洞7. 代码审计与PHP特性8. 业务逻辑漏洞总结 CTF(Capture The Flag)竞赛中的Web类题目主要考察参赛者对Web应用漏洞的识别与利用能力&am…...
comfyui(python)下载insightface失败
使用comfyui时,安装插件zenid、instantid、ip-adapter等换脸插件时,因为依赖insightface安装失败,导致插件中的节点无法正常使用,需要单独安装insightface。 下载insightface到本地,下载地址 选择与自己python版本一致…...
《DataWorks 深度洞察:量子机器学习重塑深度学习架构,决胜复杂数据战场》
在数字化浪潮汹涌澎湃的当下,大数据已然成为推动各行业发展的核心动力。身处这一时代洪流,企业对数据的处理与分析能力,直接关乎其竞争力的高低。阿里巴巴的DataWorks作为大数据领域的扛鼎之作,凭借强大的数据处理与分析能力&…...
Docker小游戏 | 使用Docker部署DOS游戏合集
Docker小游戏 | 使用Docker部署DOS游戏合集 前言项目介绍项目简介项目预览二、系统要求环境要求环境检查Docker版本检查检查操作系统版本三、部署dos-games网页小游戏下载镜像创建容器检查容器状态检查服务端口检查容器日志安全设置四、访问DOS游戏网页五、进阶玩法下载游戏拷贝…...
【redis】慢查询分析与优化
慢查询指在Redis中执行时间超过预设阈值的命令,其日志记录是排查性能瓶颈的核心工具。Redis采用单线程模型,任何耗时操作都可能阻塞后续请求,导致整体性能下降。 命令的执行流程 根据Redis的核心机制,命令执行流程可分为以下步骤…...
ThinkPHP框架
在电脑C磁盘中安装composer 命令 在电脑的D盘中创建cd文件夹 切换磁盘 创建tp框架 创建一个aa的网站,更换路径到上一步下载的tp框架路径 在管理中修改路径 下载压缩包public和view 将前面代码中的public和view文件替换 在PHPStom 中打开文件 运行指定路径 修改demo…...
从零构建高可用MySQL自动化配置系统:核心技术、工具开发与企业级最佳实践
在现代企业级数据库管理中,手动配置 MySQL 已无法满足高效、稳定和可扩展的需求。本文从 MySQL 配置管理的核心原理 出发,深入剖析 自动化配置工具的架构设计、关键技术实现,并结合 企业级落地方案,帮助读者构建一套 高可用、智能化的 MySQL 自动化配置系统。无论是 DevOps…...
qt 播放pcm音频
一、获取PCM音频 ffmpeg -i input.mp3 -acodec pcm_s16le -ar 44100 -ac 2 -f s16le output.pcm -acodec pcm_s16le:指定16位小端PCM编码格式(兼容性最佳)-ar 44100:设置采样率为CD标准44.1kHz(可替换为16000/8000等&a…...
开启mysql远程登录
目录 前言开启步骤 前言 为了安全考虑,mysql默认不允许远程登录,需要我们自己开启。当然在远程登录之前mysql的端口也要开放。下面是mysql开启远程登录的步骤。 开启步骤 本地登录mysql mysql -u root -p然后输入登录密码 给登录账号授权 GRANT AL…...
中级网络工程师面试题参考示例(5)
企业园区网络设计 问题: 请描述一下如何设计一个企业园区网络,包括核心层、汇聚层和接入层的功能及其关键技术。 解答: 核心层:负责高速数据交换,通常使用高性能的三层交换机,支持高带宽和低延迟。关键技…...
【每日学点HarmonyOS Next知识】输入框自动获取焦点、JS桥实现方式、Popup设置全屏蒙版、鼠标事件适配、Web跨域
1、HarmonyOS TextInput或TextArea如何自动获取焦点? 可以使用 focusControl.requestFocus 对需要获取焦点的组件设置焦点,具体可以参考文档: https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-universal-attribut…...
Git学习笔记(二)
Git学习笔记(二) 下载VSCode创建本地仓库推送远程仓库界面功能 使用 VSCode 进行Git仓库的项目管理 这篇文章是我学完使用 命令行终端 管理Git仓库额外学习的 文章主要用于巩固和方便后续复习 下载VSCode 可以看我这篇文章下载VSCode 创建本地仓库 …...
UDP协议和报文格式
✍作者:柒烨带你飞 💪格言:生活的情况越艰难,我越感到自己更坚强;我这个人走得很慢,但我从不后退。 📜系列专栏:网络安全从菜鸟到飞鸟的逆袭 目录 一,UDP协议1࿰…...
Java TCP 通信:实现简单的 Echo 服务器与客户端
TCP(Transmission Control Protocol)是一种面向连接的、可靠的传输层协议。与 UDP 不同,TCP 保证了数据的顺序、可靠性和完整性,适用于需要可靠传输的应用场景,如文件传输、网页浏览等。本文将基于 Java 实现一个简单的…...
升级到Android Studio 2024.2.2 版本遇到的坑
一、上来就编译报错,大概率是因为选择了替换安装,本地配置文件出错 找到本地当前版本的配置文件,删掉,重启studio就好了: 1、打开终端 2、“cd /Users/用户名/Library/Application\ Support/Google” //到Google目录 …...
hom_mat2d_to_affine_par 的c#实现
hom_mat2d_to_affine_par 的c#实现 背景:为课室贡献一个通用函数,实现halcon算子的同等效果,查询csdn未果,deepseek二哥与chtgpt大哥给不了最终程序,在大哥与二哥帮助下,最终实现同等效果。 踩坑…...
#9 【code】实现扩散模型的一个jupyter notebook
今天以一个简单的notebook入手,学习一下扩散模型的运行流程。有点困难不要紧,一个人吃了六个馒头才饱,他是吃第一个饱的,还是第六个饱的呢?始终坚信,现在的技术积累,终会成为未来高楼大厦的根基! import torch import torchvision import matplotlib.pyplot as pltdef …...
三星首款三折叠手机被曝外屏6.49英寸:折叠屏领域的新突破
在智能手机的发展历程中,折叠屏手机的出现无疑是一次具有里程碑意义的创新。它打破了传统手机屏幕尺寸的限制,为用户带来了更加多元和便捷的使用体验。而三星,作为手机行业的巨头,一直以来都在折叠屏技术领域积极探索和创新。近日,三星首款三折叠手机的诸多细节被曝光,其…...
《OkHttp:工作原理 拦截器链深度解析》
目录 一、OKHttp 的基本使用 1. 添加依赖 2. 发起 HTTP 请求 3. 拦截器(Interceptor) 4. 高级配置 二、OKHttp 核心原理 1. 责任链模式(Interceptor Chain) 2. 连接池(ConnectionPool) 3. 请求调度…...
Python 中多种方式获取屏幕的 DPI值
在 Python 中,可以通过多种方式获取屏幕的 DPI(每英寸点数)。以下是几种常见的方法: 方法 1:使用 tkinter 模块 tkinter 是 Python 的标准 GUI 库,可以通过它获取屏幕的 DPI。 import tkinter as tkdef …...
linux安装Mariadb10.5并修改端口
首先配置yum源 进入下方的文件进行配置 vim /etc/yum.repos.d/MariaDB.repo填写下方内容 [mariadb]name MariaDBbaseurl https:///mirrors.aliyun.com/mariadb/yum/10.5/centos8-amd64/gpgkeyhttps:///mirrors.aliyun.com/mariadb/yum/RPM-GPG-KEY-MariaDBmodule_hotfixes…...
Java EE 进阶:Spring IoCDI
IOC的简单介绍 什么是Spring?Spring是一个开源的框架,让我们的开发更加的简单,我们可以用一句更加具体的话来概括Spring,就是Spring是一个包含众多工具方法的IOC容器。 简单介绍一下IOC,我们之前说过通过ReqestContr…...
蓝桥杯备考:图论初解
1:图的定义 我们学了线性表和树的结构,那什么是图呢? 线性表是一个串一个是一对一的结构 树是一对多的,每个结点可以有多个孩子,但只能有一个父亲 而我们今天学的图!就是多对多的结构了 V表示的是图的顶点集…...
JVM类加载器面试题及原理
JVM只会运行二进制文件,类加载器的作用就是将字节码文件加载到JVM中,从而让Java程序能够启动起来。 1. 类加载器的种类 启动类加载器(BootStrap ClassLoader):加载JAVA_HOME/jre/lib目录下的库扩展类加载器ÿ…...
《V8 引擎狂飙,Node.js 续写 JavaScript 传奇》
”你没想过也许是这个镇子对你来说太小了吗? 对我而言,这个小镇容不下我的雄心壮志。 “ 什么是 Node.js? Node.js是一个跨平台JS运行环境,使开发者可以搭建服务器端的JS应用程序 作用:使用 Node.js 编写服务器端程序…...
关于Springboot 应配置外移和Maven个性化打包一些做法
期望达到的效果是每次更新服务器端应用只需要更新主程序jar 依赖jar单独分离。配置文件独立存放于文件夹内,更新程序并不会覆盖已有的配置信息。 一、配置外移 1、开发环境外移 做法:在项目同级或者上级创建config文件夹放置配置文件,具体m…...
Lab18_ SQL injection with filter bypass via XML encoding
文章目录 前言:进入实验室构造 payload 前言: 实验室标题为: 通关 XML 编码绕过过滤器的 SQL 注入 简介: 此实验室的库存检查功能中存在 SQL 注入漏洞。查询结果在应用程序的响应中返回,因此您可以使用 UNION 攻击…...
网络空间安全(21)验证码安全
一、基本概念 验证码(CAPTCHA)是“Completely Automated Public Turing test to tell Computers and Humans Apart”(全自动区分计算机和人类的图灵测试)的缩写,是一种区分用户是计算机还是人的公共全自动程序。它通过…...
DMA在STM32中的应用
在STM32微控制器中,DMA(直接内存访问)是实现高效数据搬运的核心技术,能够显著减轻CPU负担并提升系统性能。以下是STM32中DMA的典型应用及配置方法: 1. STM32的DMA控制器架构 DMA控制器数量:不同系列配置不同,如STM32F1系列有1个DMA控制器(DMA1,7通道),F4系列有2个(…...
V8引擎中的垃圾回收机制如何工作?
V8引擎中的垃圾回收机制主要通过分代回收和增量标记清除算法来管理内存。以下是其工作原理的详细说明: V8 的垃圾回收机制基于以下核心设计原则: 1. 分代假设:大多数对象的生命周期很短,只有少数对象会存活较长时间;…...
汇编的伪指令
一、介绍 伪指令是用于对汇编过程进行控制的指令,该类指令并不是可执行指令,没有对应机器码,只用于汇编过程中为汇编程序提供汇编信息,帮助编译器编译。当汇编结束时,伪指令的使命也就结束了。伪操作可以实现如下功能…...
【TI】如何更改 CCS20.1.0 的 WORKSPACE 默认路径
参考链接: 如何更改 CCS Theia 中工作区的默认位置?- Code Composer Studio 论坛 - Code Composer Studio™︎ - TI E2E 支持论坛 --- How to change the default location for the workspace in CCS Theia? - Code Composer Studio forum - Code Comp…...
GStreamer —— 2.13、Windows下Qt加载GStreamer库后运行 - “教程13:播放控制“(附:完整源码)
运行效果(音频) 简介 上一个教程演示了GStreamer工具。本教程介绍视频播放控制。快进、反向播放和慢动作都是技术 统称为 Trick Modes,它们都有一个共同点 修改 Normal playback rate。本教程介绍如何实现 这些效果并在交易中添加了帧步进。特别是,它 显…...
推荐一款好用在线免费软件工具箱-传道软件箱
推荐一款好用在线免费软件工具箱-传道软件箱 传道软件箱 传道软件箱是一款在线免费软件工具箱,无需登录,无需费用,用完就走的软件工具,包有BMI计算、倒计时、单位转换、密码生成器、摩斯电码、代码编辑器、计算器、快递查询、二维…...
机器学习数学基础:40.结构方程模型(SEM)中卡方值与卡方自由度比
结构方程模型(SEM)中卡方值与卡方自由度比教程 在结构方程模型分析里,卡方值和卡方自由度比是评估模型拟合程度的重要指标,下面为大家详细介绍。 一、卡方值(CMIN) (一)基本概念与…...
【JavaEE进阶】Spring AOP详解
目录 🍃什么是AOP 🌳什么是Spring AOP 🌴上手Spring AOP 🚩引入依赖 🚩编写AOP程序 🎍Spring AOP核心概念 🚩切点(Pointcut) 🚩连接点(Join Point) 🚩通知(Advi…...
Docker 的基本概念和优势,以及在应用程序开发中的实际应用
Docker 是一种开源的容器化平台,让开发人员能够打包、发布和运行应用程序在轻量级、可移植的容器中。Docker 容器包含应用程序的代码、运行时环境、系统工具、系统库等,使得应用程序能在任何环境中快速部署和运行。 Docker 的基本概念包括以下几点&…...
python flask
安装 pip install flask 查看版本 pip show flask 启动服务器 设置环境变量,在控制台执行命令,app.py是创建的文件名 windows set FLASK_APPapp.py mac/linux export FLASK_APPapp.py 启动内置web服务器,注意要进入到app.py所在的文…...
关于tomcat使用中浏览器打开index.jsp后中文显示不正常是乱码,但英文正常的问题
如果是jsp文件就在首行加 “<% page language"java" contentType"text/html; charsetUTF-8" pageEncoding"UTF-8" %>” 如果是html文件 在head标签加入: <meta charset"UTF-8"> 以jsp为例子,我们…...
双向选择排序算法
一 概述 双向选择排序(又称鸡尾酒选择排序)是选择排序的优化版本,核心改进在于每轮遍历同时确定未排序部分的最小值和最大值,分别交换到序列两端,从而减少遍历轮数。 二 时间复杂度 时间复杂度为(O(n^2)),但实际比较次数约为标准选择排序的 (1/2)。 三 C++实现代…...
P8662 [蓝桥杯 2018 省 AB] 全球变暖--DFS
P8662 [蓝桥杯 2018 省 AB] 全球变暖--dfs 题目 解析讲下DFS代码 题目 解析 这道题的思路就是遍历所有岛屿,判断每一块陆地是否会沉没。对于这种图的遍历,我们首先应该想到DFS。 代码的注意思想就是,在主函数中遍历找出所有岛屿,…...
2-kafka集群环境搭建
本文介绍kafka集群环境的搭建,我利用三个虚拟机搭建。文中我一步步演示了过程中可能会碰到的问题,在文章的最后,利用jmx,能看到详细的各个kafka broker的运行情况。 -1、环境 ubuntu :22.04-ltskafka: 2.8java: 17 …...
ROS2与Navigation2入门教程:构建与安装Nav2
Navigation2(Nav2)是ROS2中用于机器人导航的核心框架,支持路径规划、避障、SLAM等功能。本教程将详细介绍Nav2的安装与构建方法,涵盖二进制安装、源码编译及Docker部署等多种方式,适用于不同开发需求。 一、通过APT安…...
MySQL入门手册
MySQL入门手册:从零开始掌握数据库管理 📖 一、MySQL是什么? MySQL 是一个开源的关系型数据库管理系统(RDBMS),由瑞典MySQL AB公司开发,现隶属于Oracle旗下。它使用**结构化查询语言ÿ…...
深度学习算法实战——风格迁移(主页有源码)
✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ 1. 领域介绍 风格迁移(Style Transfer)是深度学习中的一个热门应用,旨在将一幅图像的风格迁移到…...