Linux:深入了解进程信号(上)
目录
1. 什么是信号
1.1 引入
1.2 概念
1.3 特性
1.4 信号的三个方面
2. 信号的产生
2.1 键盘按键产生
2.2 signal捕捉信号函数
2.3 发送信号原理
2.4 硬件中断
2.5 指令和函数接口
2.5.1 kill指令
2.5.2 kill函数
2.5.3 raise与abort函数
2.6 软件条件
2.7 异常错误产生信号
1. 什么是信号
1.1 引入
在我们的日常生活中,会遇到许多信号,比如红绿灯、铃声和乌云。看到红灯,我们知道需要停下来等待;绿灯亮起,我们可以安全通行。教室里的铃声响起,我们明白这是下课的信号。当看到天空中布满乌云,我们就知道应该把晾晒的衣服收回家了。这些信号帮助我们按照既定的规则和自然的指示来安排我们的行动。
1.2 概念
信号是用户、操作系统、其他进程,向目标进程发送异步事件的一种方式。
什么是异步事件?异步事件(Asynchronous Event)是指在一个系统或程序中,事件的发生和它的处理不是在同一个时间序列或流程中进行的。
比如,当你正在玩游戏时,突然快递到你家楼下,你需要暂时中断游戏去取快递。这两个活动各自独立,展现了异步事件的特点。
1.3 特性
为什么我们能识别信号呢?当我们看到红绿灯,知道这是交通信号。因为有人告诉我们,所以识别信号是内置的。
- 进程也是如此,识别信号的功能,是程序员内置的特性。
我们遇到红灯知道停下来,绿灯响才能过马路。这些都是别人规定的规则。
- 所以信号产生后,进程知道怎么处理,是程序员设定的。
当你在玩游戏时,突然快递到楼下了。你可能处在游戏的关键时刻,不能立即处理,需要过一会。
- 进程收到信号时,不一定要立即处理该信号,需要在合适的时候处理。
设定起床闹钟,是为了在特定时间提醒我们。当闹钟响时,有的人起床按掉闹钟,开始做计划之内的事情;有的人可能会按掉闹钟,继续睡觉;有的人可能会赖一会床,再起来。
- 同样的,进程在接受信号后也有不同的处理方式,分别是采取默认行为,忽略信号,或执行程序员设定的自定义动作。
1.4 信号的三个方面
信号的产生与处理是信号机制中不可或缺的两个环节。然而,还有一个重要的方面尚未提及,那就是信号的保存。
当进程在收到信号时恰好忙于处理其他任务,无法立即对信号作出响应,此时信号的保存机制便发挥了作用。它确保了信号能够被临时记录在案,以便进程在合适的时机对其进行后续处理。
因此,进程信号会从信号的产生,信号的保存和信号的处理这三方面着手讲起。
2. 信号的产生
2.1 键盘按键产生
#include <iostream>
#include <unistd.h>int main()
{ while(true){std::cout << "hello, world!" << std::endl;sleep(1);}return 0;
}
我们执行一个无限循环打印helloworld的代码。可以按键盘上Ctrl+C,来终止该进程。其中这种直接运行的进程时前台进程。
如果在可执行程序后面加上“&”符号,表示将该进程转为后台进程。
前台进程会占用了前台终端,导致shell进程无法接收输入的命令行来执行命令。所以Ctrl+C按键是发送给前台进程,作用是终止前台进程。
而后台进程允许shell进程执行命令行输入的指令。如下图,启动循环打印的程序,中间输入ll指令,显示该目录的文件内容。
如果想杀掉后台进程,可以打开一个新会话,使用kill指令配合-9选项,终止后台进程。
还可以使用nohup指令,将启动程序输出结果重定向到一个默认文件,叫做nohup.out。nohup.out文件不断记录进程输出内容。
此时,可以使用fg文件加上第一次启动进程中括号的数字1,可以将后台进程转为前台进程,再按Ctrl+C按键终止进程。
2.2 signal捕捉信号函数
其中sighandler是函数指针类型,signal函数用于捕捉信号,并使用传进来的函数指针对象对应的方法处理信号。
使用“kill -l”指令可以查看Linux系统提供的常见信号。1号到31号中的信号,是普通信号,之后的信号统称为实时信号。我们重点关注普通信号。其中每个信号名称其实都是一个宏,表示其编号。
其中Ctrl+C按键会发送一个信号给进程,该信号被操作系统解释为2号SIGINT信号。我们自定义一个返回值类型为void,函数参数只有一个整型变量的函数,然后使用signal函数捕捉2号信号。捕捉到2号信号,进程会按照Handler方法打印一条语句。
#include <iostream>
#include <unistd.h>
#include <signal.h>void Handler(int signo)
{std::cout << "Received signal, signal number: " << signo << std::endl;
}int main()
{ signal(SIGINT, Handler);while(true){std::cout << "hello, world!" << std::endl;sleep(1);}return 0;
}
启动该程序,按Ctrl+C按键,执行Handler函数,打印一条语句。这就证明了Ctrl+C按键,实质上是2号信号。
通过man 7 signal指令,可以查询到普通信号的默认处理动作,其中Term和Core都是终止进程。
2.3 发送信号原理
当按下键盘中Ctrl+C按键,操作系统会识别该操作,发送2号信号给进程。使用kill -l指令,会显示所有信号,你会发现信号编号是从1开始的。
因为进程PCB中有许多字段,其中使用位图上的比特位0和1两个状态,来表示该位数信号是否有接受到。还有个字段是sighandler_t类型的数组,sighandler_t是函数指针类型,也就是说该字段是函数指针数组。
当操作系统发送2号信号给进程时,其实向进程PCB位图中的第二位比特位写入1,表示该进程接受2号信号,并通过函数指针数组中下标为2的函数指针,执行该函数。如果使用signal函数,则会将该数组对应下标的内容修改为Handler函数的地址。
2.4 硬件中断
当用户按下Ctrl+C组合键时,键盘硬件检测到这一动作,并将按键编码转换为相应的信号。此时,键盘准备就绪,将数据通过中断请求线(IRQ)发送给CPU的特定引脚,以此发起一个中断请求。这个中断信号即刻通知操作系统,有来自键盘的外部事件需要被关注和处理。
操作系统接收到中断信号后,随即响应,它会暂停当前正在执行的任务,并将控制权转交给专门处理键盘输入的中断服务例程(ISR)。该例程负责将键盘缓冲区中的数据读取出来,并将其安全地拷贝到系统的内存中,以便CPU可以进一步处理这些输入。
所以,操作系统不需要对外部设备进行轮询检测,当执行完当前指令,只要等外部设备发送中断请求。操作系统如公司老板一般,指挥手底下的员工干活,自己只需要等待员工汇报工作进展,从而达到外设与操作系统并行。
2.5 指令和函数接口
2.5.1 kill指令
kill指令可以向目标进程发送指定信号。我们写一份代码,使用signal函数捕捉1到31号信号,然后打个死循环,使用kill指令发送信号。
#include <iostream>
#include <unistd.h>
#include <signal.h>void Handler(int signo)
{std::cout << "Received signal, signal number: " << signo << std::endl;
}int main()
{ for(int signo = 1; signo <= 31; signo++){signal(signo, Handler);}while(true){sleep(1);}return 0;
}
我们使用kill指令发送1号、2号和6号信号,都被sig进程处理为打印一条语句。有人会说把所有信号捕捉,采用自己自定义方法,那进程岂不是无法终止。其实操作系统设计者也想到了这个问题,所以有些信号是无法被捕捉的,只会使用默认方式处理,如9号信号,可以终止所有你可以终止的进程。
2.5.2 kill函数
kill也是系统调用函数,向指定进程发送信号。我们可以使用这个函数写一个自己的kill指令。
#include <iostream>
#include <string>
#include <sys/types.h>
#include <signal.h>void Usage(std::string proc)
{std::cout << "Usage: " << proc << "signumber processid" << std::endl;
}// ./mykill 9 12345
int main(int argc, char* argv[])
{ if(argc < 3){Usage(argv[0]);exit(1);}int signumber = std::stoi(argv[1]);pid_t pid = std::stoi(argv[2]);int n = kill(pid, signumber);if(n < 0){perror("kill");exit(2);}exit(0);
}
如下图,执行mykill进程需要输入三个参数,可以杀掉普通进程。
2.5.3 raise与abort函数
raise函数是发送信号给调用该函数的进程。写一个五秒后发送9号信号给自己的代码。
#include <iostream>
#include <unistd.h>
#include <signal.h>int main(int argc, char* argv[])
{ int cnt = 0;while(true){std::cout << "I am alive!" << std::endl;cnt++;if(cnt > 4)raise(SIGKILL);sleep(1);}return 0;
}
abort函数作用是通过发送SIGABRT信号给调用该函数的进程,以此终止该进程。这算作异常退出。
#include <iostream>
#include <string>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>void Handler(int signo)
{std::cout << "Received signal, signal number: " << signo << std::endl;
}int main(int argc, char* argv[])
{ signal(SIGABRT, Handler);int cnt = 0;while(true){std::cout << "I am alive!" << std::endl;cnt++;if(cnt > 4)abort();sleep(1);}
}
2.6 软件条件
软件没准备好,软件条件不具备引起信号的产生。常见的是管道的读端关闭,而某个进程向管道写入,操作系统会发送SIGPIPE信号给该进程,并终止进程。
alarm函数用来设置发送信号的闹钟,该信号是SIGALRM信号。
#include <iostream>
#include <unistd.h>int main()
{ alarm(1); //1s后,会收到SIGALRM信号int number = 0;while(true){printf("count: %d\n", number++);}return 0;
}
上面的代码实现了测试服务器1s能完成多少次IO的功能,差不多稳定在七万次左右。但是对于CPU每秒几亿执行次数来说,已经很慢了。
#include <iostream>
#include <string>
#include <unistd.h>
#include <signal.h>int number = 0;void Die(int signumber)
{printf("get a signal %d, count: %d\n", signumber, number);exit(0);
}int main(int argc, char* argv[])
{ alarm(1);signal(SIGALRM, Die);while(true){number++;}
}
上面的代码,没有进行调用printf进行IO。运行结果如下,结果接近6亿次,相比于上面的结果,快了将近一万倍。说明IO操作十分耗时。
2.7 异常错误产生信号
#include <iostream>
#include <unistd.h>
#include <signal.h>int main()
{ int *p = nullptr;*p = 10; while(true);
}
上面是野指针问题,程序启动后会,操作系统会发送11号SIGSEGV信号给进程,终止该进程。
#include <iostream>
#include <unistd.h>
#include <signal.h>int main()
{ int a = 10;a /= 0;while(true);
}
上面代码是除零错误,会导致栈溢出,操作系统会发送8号SIGFPE信号给进程。
当CPU执行该进程“a /= 0”代码时,实际上被解释为“a = a / 0”,CPU会用三个寄存器存储三个值。
- eax存储一开始a变量的值,ebx存储0,再通过计算把结果存储到ecx寄存器中。CPU还有一个状态寄存器Eflags,其中有个溢出标记位,专门记录结果是否正常。
- a变量除0后,结果会溢出,Eflags中的标记位会写入为1。
- CPU因溢出标记位为1,得知计算结果有问题,会触发硬件中断。操作系统就会知道CPU内部出错,会向执行此代码的进程发送终止信号。
- 即使使用signal函数捕捉SIGSEGV信号,不终止该进程。当进程被CPU执行时,该进程的上下文数据重新加载到CPU时,Eflags上的溢出标记位还是1,照样会引起硬件中断,操作系统就会不断发送信号来终止进程。
创作充满挑战,但若我的文章能为你带来一丝启发或帮助,那便是我最大的荣幸。如果你喜欢这篇文章,请不吝点赞、评论和分享,你的支持是我继续创作的最大动力!
相关文章:
Linux:深入了解进程信号(上)
目录 1. 什么是信号 1.1 引入 1.2 概念 1.3 特性 1.4 信号的三个方面 2. 信号的产生 2.1 键盘按键产生 2.2 signal捕捉信号函数 2.3 发送信号原理 2.4 硬件中断 2.5 指令和函数接口 2.5.1 kill指令 2.5.2 kill函数 2.5.3 raise与abort函数 2.6 软件条件 2.7 异…...
Java小白入门基础知识(二)
1.标识符 概念: 在程序中给类,方法,变量取的名称叫做标识符 规范: 字母,数字,下划线,$符号 注意: 不能以数字开头,也不能是关键字,严格区分大小写(一般定义常量就是大写) 软性建议: 1)类名:每个单词首字母大写(大驼峰) 2)方法名:首字母小写,后面每个单词首字母大写(小驼…...
Servlet中,WebServlet注解的使用方法
案例:声明abc接口,在接口内部获取配置信息 WebServlet(urlPatterns"/abc",loadOnStartup6,initParams {WebInitParam(name"username", value"mmm", description"this is username"),WebInitParam(name"a…...
重新出发的LLM本地部署——DeepSeek加持下的Ollama+OpenWebUI快速部署
DeepSeek 这真的是太惊艳了,发布出来的模型这么能打,在线的版本使用起来也是丝滑连招,感觉效果比起之前一直用智谱 chatglm4 更好用,想着本地化部署一下。 本来以为,会和之前在开发测试 transformers 的模型和代码一样…...
【Python爬虫(1)】专栏开篇:夯实Python基础
【Python爬虫】专栏简介:本专栏是 Python 爬虫领域的集大成之作,共 100 章节。从 Python 基础语法、爬虫入门知识讲起,深入探讨反爬虫、多线程、分布式等进阶技术。以大量实例为支撑,覆盖网页、图片、音频等各类数据爬取ÿ…...
低代码组态软件-BY组态
引言 在工业4.0与智能制造浪潮的推动下,组态软件作为工业自动化的核心工具,正逐步从传统单机模式向Web化、智能化方向演进。BY组态作为一款基于Web的嵌入式组态插件工具,凭借其低代码、高灵活性和跨平台特性,成为工业物联网&#…...
【计算机网络】数据链路层数据帧(Frame)格式
在计算机网络中,数据帧(Frame) 是数据链路层的协议数据单元(PDU),用于在物理介质上传输数据。数据帧的格式取决于具体的链路层协议(如以太网、PPP、HDLC 等)。以下是常见数据帧格式的…...
[特殊字符] C语言中打开和关闭文件的两种方法:标准库 VS 系统调用
C语言中对文件打开关闭操作 前言方法一:标准输入输出库(stdio.h)—— 高级文件操作的利器打开文件💡 关闭文件:fclose示例代码📝 个人见解 方法一:系统调用(fcntl.h 和 unistd.h&…...
如何将ubuntu下的一个目录,保存目录结构为一个git仓库并上传
目录 1. 初始化本地Git仓库 2. 添加文件到仓库 3. 提交更改 4. 创建并关联远程仓库 5. 推送代码到远程仓库 完整流程总结 要将Ubuntu下的一个目录(例如rpc)保存为一个Git仓库并上传到远程仓库,您可以遵循以下步骤: 1. 初始…...
应用分层、三层架构和MVC架构
前言 在前面中,我们已经学习了Spring MVC 的一些基础操作,那么后面就用一些简单的案例来巩固一下。 在开始学习做案例之前,我们先来了解一下在软件开发中常见的设计模式和架构。 应用分层 含义 应用分层是一种软件开发设计思想࿰…...
前端实现防抖功能的详细解读
在前端开发中,防抖(Debounce) 是一种优化技术,用于限制某个函数在短时间内被频繁调用的次数。它的核心思想是:在一定时间内,无论触发多少次事件,只执行最后一次操作。防抖通常用于处理用户输入、…...
VUE3环境搭建
最近准备用Vue编写一点前端页面,我在前端一直是个小白,之前用的Vue2写了几个页面,现在已经是VUE3了,重新安装下环境开始。 1.npm安装 Vue需要用npm安装,npm是nodejs的package manager,这里我们安装下node…...
1-16 tortoiseGit分支与Git操作
1-1 创建分支 什么时候需要开分支? - 隔离线上版本和开发版本 - 大功能开发,不想影响到其他人,自己独立开个分支去开发 SVN经典目录结构: - trunk-------------------------开发中的文件 - bran…...
【VB语言】EXCEL中VB宏的应用
【VB语言】EXCEL中VB宏的应用 文章目录 [TOC](文章目录) 前言一、EXCEL-VB1.实验过程2.代码 二、EXCEL-VB 生成.c.h文件1.实验过程2.代码 四、参考资料总结 前言 1.WPS-VB扩展包 提示:以下是本篇文章正文内容,下面案例可供参考 一、EXCEL-VB 1.实验过…...
前端优化可以从哪些方面下手及优化方案
前端优化是提升网页性能、提升用户体验和降低服务器负担的重要手段。可以从多个角度入手,以下是一些常见的优化方向和方案: 1. 性能优化 减少请求数量:尽量减少页面加载时发起的 HTTP 请求,例如使用合并文件(CSS 和 …...
类和对象(5)——抽象类和接口
目录 1. 抽象类 1.1 抽象类的概念 1.2 抽象类语法:abstract关键字 1.3 抽象类的特性 1.4 抽象类的作用 2. 接口 2.1 接口的概念 2.2 接口语法:interface关键字 2.3 接口的实现:implements关键字 2.4 接口的特性 2.5 实现多个接口 …...
海康摄像头IPV6模式,手动,自动,路由公告
海康摄像头DS-2DC7220IW-A 网络设置中的IPv6配置选项。IPv6是互联网协议(IP)的第六版,用于替代IPv4,提供更多的IP地址和改进的网络功能。图片中的选项允许用户选择如何配置设备的IPv6网络连接: 手动:用户可…...
LabVIEW与USB设备开发
开发一台USB设备并使用LabVIEW进行上位机开发,涉及底层驱动的编写、USB通信协议的实现以及LabVIEW与设备的接口设计。本文将详细介绍如何开发USB设备驱动、实现LabVIEW与USB设备的通信以及优化数据传输,帮助用户顺利完成项目开发。下面是一个详细的说明&…...
BY组态:工业自动化的未来,触手可及
在工业4.0的浪潮下,智能化、数字化已成为制造业发展的核心驱动力。作为工业自动化领域的重要工具,组态软件在实现设备监控、数据采集、流程控制等方面发挥着不可替代的作用。然而,传统的组态软件往往存在开发周期长、学习成本高、灵活性不足等…...
深入理解Python多进程编程 multiprocessing
深入理解Python多进程编程 multiprocessing flyfish Python 的 multiprocessing 模块允许创建多个进程,从而可以利用多核处理器的能力来并行执行任务。这意味着程序的不同部分可以在不同的CPU核心上同时运行,极大地提高了处理效率,特别是在…...
使用DeepSeek建立一个智能聊天机器人0.12
为了确保这段代码能够在Windows和Linux系统上都能正常运行,我考虑以下几个方面: 路径分隔符:在Windows和Linux中,文件路径的分隔符不同。Windows使用反斜杠(\),而Linux使用正斜杠(/)。我们可以使用 os.path.join 来处理路径,以确保跨平台兼容性。 消息框:tkinter.…...
基于VLC的Unity视频播放器(三)
关于UMP插件 UMP插件不更新了,我测试在Ubuntu24.04上编辑器和运行时都无法正常播放,在替换lib之后编辑器可以播放,但打包后不行……很奇怪 继续更新了一下UnityVLC 添加了对Linux的支持,勉强都可以播放了…… Win截图 Ubuntu2…...
每日一题——把数字翻译成字符串
把数字翻译成字符串 题目描述示例示例1示例2 题解动态规划代码实现复杂度分析 总结 题目描述 有一种将字母编码成数字的方式:‘a’->1, ‘b’->2, … , ‘z’->26。 现在给一串数字,返回有多少种可能的译码结果。 数据范围:字符串…...
基于状态观测器和物联网基础设施的智能电网高速孤岛检测
论文标题 中文标题: 基于状态观测器和物联网基础设施的智能电网高速孤岛检测 英文标题: High-Speed Islanding Detection in Smart Grids Using a State Observer and IoT Infrastructure 作者信息 Shahid Karim<sup>1,2, *</sup>, Prajo…...
FPGA的星辰大海
编者按 时下风头正盛的DeepSeek,正值喜好宏大叙事的米国大统领二次上岗就业,OpenAI、软银、甲骨文等宣布投资高达5000亿美元“星际之门”之际,对比尤为强烈。 某种程度上,,是低成本创新理念的直接落地。 包括来自开源社区的诸多赞誉是,并非体现技术有多“超越”,而是…...
【Black Mesa】黑山起源用服务器开服多人联机教程
1、登录服务器(百度莱卡云游戏面板) 进入控制面板后会出现正在安装的界面,安装大约10分钟(如长时间处于安装中请联系我们的客服人员) 2、修改端口 看到一下图片的界面时说明服务器已经安装完成,服务器需要…...
【学习笔记】深度学习网络-深度模型中的优化
作者选择了由 Ian Goodfellow、Yoshua Bengio 和 Aaron Courville 三位大佬撰写的《Deep Learning》(人工智能领域的经典教程,深度学习领域研究生必读教材),开始深度学习领域学习,深入全面的理解深度学习的理论知识。 在之前的文章中介绍了深度学习中…...
java八股文之Redis
1.Rdis常见的使用场景 缓存分布式锁(redision,setnx)计数器保存token消息队列延迟队列 2.说明一下缓存雪崩,缓存穿透和缓存击穿以及解决方式 1.缓存雪崩 定义: 缓存雪崩指的是当大量的缓存数据同时失效,…...
ubuntu系统下KVM设置桥接网络(失败)
20250216 - 概述 因实验需求,需要设置KVM下的虚拟机采用桥接模式进行通信,这种方式将使虚拟机与主机类似使用同一网段的IP。实际上,为了实现这个功能,我已经在自己mac上VMware使用过,虚拟机获得了自己独立的IP。 但…...
CentOS 7操作系统部署KVM软件和创建虚拟机
CentOS 7.9操作系统部署KVM软件和配置指南,包括如何创建一个虚拟机。 步骤 1: 检查硬件支持 首先,确认您的CPU支持虚拟化技术,并且已在BIOS中启用: egrep -c (vmx|svm) /proc/cpuinfo 如果输出大于0,则表示支持虚拟…...
驱动开发系列38 - Linux Graphics 3D 绘制流程(一)- 创建画布
一:概述 当应用程序创建 OpenGL 上下文时,它通常需要申请帧缓冲(Framebuffer,即画布)。在 X11 体系下,应用程序不会直接向内核的 DRM 模块请求创建帧缓冲,而是通过 X 服务器进行申请。 虽然从技术上讲,应用程序可以直接使用 DRM 接口创建帧缓冲对象(BO),但为了将其与…...
Spring Boot过滤器链:从入门到精通
文章目录 一、过滤器链是什么?二、为什么需要过滤器链?三、Spring Boot中的过滤器链是如何工作的?(一)过滤器的生命周期(二)过滤器链的执行流程 四、如何在Spring Boot中定义自己的过滤器&#…...
QT 读写锁
一、概述 1、读写锁是一种线程同步机制,用于解决多线程环境下的读写竞争问题。 2、读写锁允许多个线程同时获取读锁(共享访问),但只允许一个线程获取写锁(独占访问)。 3、这种机制可以提高并发性能&…...
C++中的智能指针
智能指针总结 智能指针其作⽤是管理⼀个指针,避免程序员申请的空间在函数结束时忘记释放,造成内存泄漏这种情况滴发⽣。使⽤智能指针可以很⼤程度上的避免这个问题,因为智能指针就是⼀个类,当超出了类的作⽤域是,类会…...
IntelliJ IDEA 接入 AI 编程助手(Copilot、DeepSeek、GPT-4o Mini)
IntelliJ IDEA 接入 AI 编程助手(Copilot、DeepSeek、GPT-4o Mini) 📊 引言 近年来,AI 编程助手已成为开发者的高效工具,它们可以加速代码编写、优化代码结构,并提供智能提示。本文介绍如何在 IntelliJ I…...
【R语言】非参数检验
一、Mann-Whitney检验 在R语言中,Mann-Whitney U检验(也称为Wilcoxon秩和检验)用于比较两个独立样本的中位数是否存在显著差异。它是一种非参数检验,适用于数据不满足正态分布假设的情况。 1、独立样本 # 创建两个独立样本数据…...
PyTorch 源码学习:阅读经验 代码结构
分享自己在学习 PyTorch 源码时阅读过的资料。本文重点关注阅读 PyTorch 源码的经验和 PyTorch 的代码结构。因为 PyTorch 不同版本的源码实现有所不同,所以笔者在整理资料时尽可能按版本号升序,版本号见标题前[]。最新版本的源码实现还请查看 PyTorch 仓…...
04运维实用篇(D4_日志)
目录 一、简介 二、代码中使用日志工具记录日志 1. 操作步骤 步骤1:添加日志记录操作 步骤2:设置日志输出级别 步骤3:设置日志组 2. 知识小结 三、优化日志对象创建代码 1. 实例 2. 总结 四、日志输出格式控制 1. 实例 2. 总结 …...
Linux文件管理:硬链接与软链接
文章目录 1. 硬链接的设计目的(1)节省存储空间(2)提高文件管理效率(3)数据持久性(4)文件系统的自然特性 2. 软链接的设计目的**(1)跨文件系统引用****&#x…...
【零基础学Mysql】常用函数讲解,提升数据操作效率的利器
以耳倾听世间繁华,以语表达心中所想 大家好,我是whisperrrr. 前言: 大家好,我是你们的朋友whisrrr。在日常工作中,MySQL作为一款广泛使用的开源关系型数据库,其强大的功能为我们提供了便捷的数据存储和管理手段。而在…...
小米平板怎么和电脑共享屏幕
最近尝试使用小米平板和电脑屏幕分屏互联 发现是需要做特殊处理的,需要下载一款电脑安装包:小米妙享 关于这个安装包,想吐槽的是: 没有找到官网渠道,是通过其他网络方式查到下载的 不附录链接,原因是因为地…...
宝藏软件系列 篇一:My APK(Android)
文章目录 系列文章官方网站特色功能同类软件 系列文章 官方网站 My APK 官方版本是在 谷歌商店 中上架的。 官方下载地址:Google Play 商店页面。(需要外网) 2025.2最新版本的CSDN本地下载地址(因为是Android App Bundle&…...
本地 Ollama 部署 Deepseek R1 并使用 Spring AI Alibaba 构建 Chat 应用示例
本地部署 Deepseek R1 并使用 Spring AI Alibaba 构建 Chat 应用示例 Ollama 部署 Deepseek R1 官网:https://www.deepseek.com/ Github:https://github.com/deepseek-ai Ollama:https://ollama.com/ Docker Compose 部署一个 Ollama 和…...
centos8.0 docker ngnix
问题1:镜像拉取不下来,用DAO云加速器 问题2:ngnix镜像不能运行, 无法检索OCI运行时错误 在CentOS上使用Docker来运行Nginx是一个常见的做法,因为它提供了快速、一致的环境配置方式,并且可以很容易地扩展。…...
位运算在数据库中的运用实践-以MySQL和PG为例
目录 前言 一、两种不同的数据库设计 1、状态字段存储JSON 2、使用位运算 二、数据库中的位运算实践 1、MySQL中的位运算实践 2、PostgreSQL中位运算实践 三、总结 前言 最近在解决某用户的一个业务需求时,遇到一个很有意思的场景。首先先跟大家分享一下需…...
IoTDB 常见问题 QA 第五期
关于 IoTDB 的 Q & A 情人节之际,让 IoTDB Q&A 陪您一起共度解惑!我们将定期汇总我们将定期汇总社区讨论频繁的问题,并展开进行详细回答,通过积累常见问题“小百科”,方便大家使用 IoTDB。 Q1:导入…...
【kafka系列】日志存储设计 消息写入、读取
目录 日志存储设计 1. 日志存储的目录结构 2. 日志内容格式设计 3. 日志索引设计 4. 设计优势 消息写入流程 示例 流程图 消息读取流程 示例 关键设计细节 流程图 日志存储设计 Kafka的日志存储是其高吞吐、持久化能力的核心设计,其结构包含目录组织、…...
Python实现语音识别详细教程【2025】最新教程
文章目录 前言一、环境搭建1. 下载 Python2. 安装 Python3 使用 pip 安装必要的库 二、使用 SpeechRecognition 库进行语音识别1.识别本地音频文件2.实时语音识别3. 使用其他语音识别引擎 注意事项 前言 以下是一份较为完整的 Python 语音识别教程,涵盖环境搭建、使…...
【一文读懂】HTTP与Websocket协议
HTTP协议 概述 HTTP (Hypertext Transfer Protocol),即超文本传输协议,是一种用于在客户端和服务器之间传输超文本(例如网页、图片、音频、视频等)的通信协议。它是万维网(WWW)的基础,负责在浏…...
SpringBoot+微信小程序+数据可视化的宠物到家喂宠服务(程序+论文+讲解+安装+调试+售后等)
感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,我会一一回复,希望帮助更多的人。 系统介绍 在经济高速发展、物质生活极大丰富的当下,人们的精神需求愈发凸显࿰…...