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

【Linux系统篇】:什么是信号以及信号是如何产生的---从基础到应用的全面解析

✨感谢您阅读本篇文章,文章内容是个人学习笔记的整理,如果哪里有误的话还请您指正噢✨
✨ 个人主页:余辉zmh–CSDN博客
✨ 文章所属专栏:Linux篇–CSDN博客

在这里插入图片描述

文章目录

  • 一.信号概念
    • 1.生活角度的信号
    • 2.技术应用角度的信号
    • 3.补充内容
      • 前台进程和后台进程
      • 硬件中断
  • 二.信号产生
    • 1.键盘组合键
    • 2.kill命令
    • 3.系统调用
    • 4.异常
    • 5.软件条件
  • 三.补充内容--核心转储

一.信号概念

1.生活角度的信号

在平常的生活中,信号无处不在,比如说上下课铃声,红绿灯,快递取件码,外卖电话,闹钟等等。

1.对于这些生活中的信号,我们是如何认识这些信号的

当然是有人教我们怎么识别信号,以及信号到来后怎么处理信号

2.即便是当前没有信号产生,我们也知道信号产生后应该做什么

比如点外卖,我们平常点外卖都是下单之后,过一段时间骑手才能给我们送过来,当我们收到骑手的电话后,我们就知道外卖到了要下楼取餐。但是我们在等待的这个过程中,骑手还没有给我们打电话之前,我们依然知道收到电话之后要做什么。

3.信号产生之后,我们可能并不会立即处理这个信号,而是选择在合适的时候处理,因为我们可能正在做其他更重要的事情。所以,信号产生之后直到信号处理时,存在一个时间窗口,在这个时间窗口这一时间段内,我们必须记住信号到来

还是点外卖这个例子,我们在收到骑手的电话后,可能并不是立即下楼取餐,比如此时我们还在打游戏,中间不能断,直到游戏结束后,我们才下楼取餐。在接收到骑手电话直到游戏结束,这个时间段就是一个时间窗口,在这个时间窗口中我们需要记住外卖到了,然后游戏结束后再处理。

2.技术应用角度的信号

如果站在技术应用角度看待信号,同样可以根据上面的内容得出结论:

在计算机中,程序也就是进程代表的就是我们用户的身份。

1.进程必须可以识别以及处理信号

2.进程即便是没有收到信号,也能知道哪些信号该怎么处理。信号的处理能力,属于进程内置功能的一部分

3.当进程真的收到了一个具体的信号的时候,进程可能并不会立即处理这个信号,而是选择在合适的时候处理

信号的处理方式:

  • 默认动作
  • 忽略
  • 自定义动作

4.进程在收到信号后,到信号开始被处理的时候,也一定会有一个时间窗口,进程具有临时保存哪些信号已经发生的功能

举个例子:

写一个死循环的程序,在命令行上采用前台进程运行;当用户在进程运行的过程中,按下Ctrl+c键,该进程就会终止退出

#include <iostream>
#include <unistd.h>
using namespace std;int main(){while(true){cout << "I am a process" << endl;sleep(1);}return 0;
}

在这里插入图片描述

直接说明结论:Ctrl+c键的本质是被进程解释成为收到了2信号,前面提到过进程对信号的处理方式有三种,如果没有设置自定义动作,进程就会采用默认动作处理信号,而2号信号的默认动作就是终止退出

下面图中表示的是所有的信号,其中1~31个是普通信号,而34~64则是实时信号(需要理解处理),后面讲解信号时主要围绕前31个普通信号来讲解。

信号以宏定义的形式表示,本质上就是数字编号

在这里插入图片描述

验证上面的结论,Ctrl+c组合键本质上是发送2号信号,并且默认处理动作是终止退出:

  • signal函数
#include <signal.h>typedef void (*sighandler_t)(int);sighandler_t signal(int signum, sighandler_t handler);

功能:用于修改特定进程对于指定信号的处理动作,也就是自定义动作,这个过程叫做信号捕捉

参数

  • sig:信号编号或者信号名。
  • handler:自定义处理函数指针,或特殊值 SIG_IGN(忽略信号,表示的是数字1)和 SIG_DFL(恢复默认行为,表示的是数字0)。

返回值:成功时返回之前的处理函数指针,失败时返回 SIG_ERR

测试代码:

#include <iostream>
#include <unistd.h>
#include <signal.h>
using namespace std;void handler(int signo){cout << "process get a signal: " << signo << endl;
}int main(){signal(2, handler);while (true){cout << "I am a process, pid: " << getpid() << endl;sleep(1);}return 0;
}

用signal函数设置自定义动作,捕捉2号信号,因为自定义动作只是输出一条语句,所以处理完后(函数调用结束),并没有终止退出,因此可以验证2号信号的默认动作就是终止退出。

在这里插入图片描述

  • signal函数的注意事项

1.信号处理的三种方式只能三选一,使用自定义动作,就不能再执行默认动作;

2.signal函数只需要设置一次,在进程整个生命周期往后都会有效;

3.signal函数中设置的自定义动作函数handler是在执行后续代码的过程中收到信号才调用,没有收到就不会调用;

4.对于普通信号,除了9号和19号信号不能自定义动作捕捉外,其他都可以(可以将所有普通信号使用signal函数捕捉,然后依次发送每个信号进行测试);

5.多个信号可以设置同一个自定义动作,所以handler函数需要带一个参数,用来指定具体的目标信号。

3.补充内容

前台进程和后台进程

前台进程和后台进程是操作系统中两种不同的进程运行方式,在Linux中,一次登录,一个终端,一般会配上一个命令行解释器bash,每一个登录,只允许一个进程是前台进程,但是可以允许多个进程是后台进程。

  • 前台进程

    • 在终端中直接启动命令时默认为前台运行;

    • 一旦前台进程启动后,bash进程变成后台进程,就不再接收任何指令了,需要等待其完成才能执行其他指令

    • 前台进程直接与用户交互,可以接受用户的输入(比如键盘输入)

    • 可以通过Ctrl+c组合键终止

在这里插入图片描述

  • 后台进程
    • 在Linux中,可以通过在命令行后添加&符号来启动后台进程(比如./test &
    • 一旦后台进程启动后,bash进程还是前台进程,可以继续执行用户输入的指令
    • 后台进程不与用户直接交互,通常无法接受用户输入
    • 无法通过Ctrl+c组合键终止

在这里插入图片描述

前后台进程的区分就是谁来获取键盘的输入,键盘输入首先是被前台进程收到的

因为前台进程可以接收到用户输入的Ctrl+c组合键,通过硬件中断转变为接收到2号信号,执行默认动作处理从而使进程终止退出。

硬件中断

在上面的讲解例子中,键盘数据是如何输入给内核的,Ctrl+c组合键又是如何变成信号的?这就需要来了解一下关于硬件部分了。

进程是由CPU来执行的,在数据层面上,CPU不和外设直接交互;但是在控制层面上,CPU可以和外设直接交互,当外设某种事件完成后,就可以发起硬件中断,经过中断单后,向CPU发送中断信号,CPU根据中断请求线的电平变化来接收中断信号。

通过中断机制,外设可以需要时获得CPU的注意力,而不需要CPU不断检查外设状态,这样设计可以使CPU能够高效管理多个外设,而不必浪费时间在不需要服务的设备上

此外在内存中存储了一张中断向量表,中断向量表中存放的是中断服务程序的入口地址(也就是函数指针),系统通过CPU收到的中断信号,以中断信号为索引到表中找到对应的处理中断方法,然后执行对应的操作。

当我们从键盘中输入时,键盘被按下,存有数据时,键盘立刻会发起硬件中断,通过中断单元向CPU发送中断信号,中断信号被CPU保存下来,同时操作系统会立刻读取中断信号,以此为索引到中断向量表中找到对应的处理中断方法(从键盘读取到内存中),键盘上的数据在读取到内存上时,系统会进行判断,如果是控制类型的数据,比如Ctrl+c,系统就会将2号信号发送给进程。进程收到2号信号后,如果没有自定义捕捉,就会执行默认动作终止退出。

操作系统就是不断接受中断信号来处理外设的

对于外设和CPU的直接交互也仅仅局限于控制层面上的

除了有硬件中断,当然还存在软件中断:信号就是用软件方式,对进程模拟的硬件中断,虽然两者没有任何关联,但设计方式却是很相似(后面信号保存的时候再讲解)

当程序正在执行代码时,可能会产生信号,信号的产生和我们自己写的代码运行是异步的。信号就是进程之间事件异步通知的一种方式—属于软中断

二.信号产生

1.键盘组合键

常用的几个:

1.Ctrl+c

  • 信号SIGINT,信号编号为2
  • 默认行为:终止进程
  • 用途:强制中断前台进程的执行

2.Ctrl+\

  • 信号SIGQUIT,信号编号为3
  • 默认行为:终止进程并生成核心转储(暂时了解即可,后面会讲什么是核心转储)
  • 用途:强制终止进程并生成调试用的核心文件。

3.Ctrl+z

  • 信号SIGSTOP,信号编号为19
  • 默认行为:暂停进程,将进程放入后台(无法被捕捉)
  • 用途:暂停进程

2.kill命令

通过kill指令同样可以给指定进程发送信号:

kill [-信号编号或信号名] PID

注意:如果省略信号参数,或默认向指定进程发送SIGTERM(编号为15),优雅的终止进程。

常用信号及其用途

信号名编号默认行为典型场景
SIGTERM15优雅终止进程允许进程清理资源后退出
SIGKILL9强制终止进程立即杀死无响应的进程
SIGINT2终止进程(同 Ctrl+C手动终止前台进程
SIGSTOP19暂停进程(不可被捕获)调试时冻结进程状态
SIGCONT18恢复已暂停的进程继续运行被 SIGSTOP 暂停的进程

3.系统调用

1.kill函数

#include <signal.h>int kill(pid_t pid, int sig);

功能

向指定进程发送目标信号(类似于指令kill发送信号)。

参数

  • pid:发送信号的目标进程
  • sig:要发送的信号名或信号编号

返回值

成功返回0,失败返回-1并设置errno。

通过kill函数实现一个自己的kill指令:

signal.cc文件:

#include <iostream>
#include <unistd.h>
#include <signal.h>
using namespace std;void handler(int signo){cout << "process get a signal: " << signo << endl;
}int main(){// 所有普通信号全部捕捉for (int i = 1; i < 31; i++){signal(i, handler);}while (true){cout << "I am a process, pid: " << getpid() << endl;sleep(2);}return 0;
}

mykill.cc文件:

#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <string>
using namespace std;void handler(int signo){cout << "process get a signal: " << signo << endl;exit(0);
}int main(int argc, char *argv[]){if(argc!=3){cout << "Usage:\n\t" << "kill signal pid\n" << endl;exit(1);}int signum = stoi(argv[1]);pid_t pid = stoi(argv[2]);int n = kill(pid, signum);if(n == -1){perror("kill");exit(2);}return 0;
}

在这里插入图片描述

2.raise函数

#include <signal.h>int raise(int sig);

功能

向调用这个函数的当前进程发送目标信号(等价于kill(getpid(), sig))。

参数

sig:要发送的信号名或信号编号

返回值

成功返回0,失败返回-1并设置errno。

raise函数发送的信号,被捕捉后,只会执行自定义动作:

#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <string>
using namespace std;void handler(int signo){cout << "process get a signal: " << signo << endl;exit(0);
}int main(){signal(2, handler);int cnt = 5;while (true){cout << "I am a process, pid: " << getpid() << endl;sleep(1);cnt--;if(cnt==0){raise(2);}  }return 0;
}

这里对2号信号自定义动作添加了退出语句,所以执行完后回退出:

在这里插入图片描述

3.abort函数

#include <signal.h>int abort(void);

功能

向调用这个函数的当前进程发送6号信号(等价于kill(getpid(), 6))。

无参数无返回值

abort函数和raise不一样,被捕捉后,如果自定义动作没有退出,执行完自定义动作,还会执行默认动作,终止退出:

#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <string>
using namespace std;void handler(int signo){cout << "process get a signal: " << signo << endl;// exit(0);
}int main(){signal(6, handler);int cnt = 5;while(true){cout << "I am a process, pid: " << getpid() << endl;sleep(1);cnt--;if(cnt==0){abort();}}return 0;
}

对6号信号的自定义动作取消退出,但是最后依然会终止退出,就是因为被捕捉后,如果自定义动作没有退出,执行完自定义动作,还会执行默认动作,终止退出

在这里插入图片描述

4.异常

在刚开始学习进程的时候,在进程终止的那里讲解过进程有三种退出情况:1.代码执行完,结果正确退出;2.代码执行完,结果不正确退出;3.执行过程中出现错误,异常退出,代码没有执行完。

现在学到信号这里,就可以明白,进程在执行过程中出现错误,本质上是收到了对应的异常信号,因为信号的默认动作是终止退出,所以当前进程就结束执行退出了。

举例:

#include <iostream>
#include <unistd.h>
#include <signal.h>
using namespace std;int main(){// 除零错误// int a = 10;// int b = 0;// int c = a / b;// cout << c << endl;// 野指针错误// int *p = nullptr;// *p = 10;// cout << *p << endl;// return 0;
}

在这里插入图片描述

这两个错误分别对应信号SIGFPE(浮点异常)信号编号为8,以及信号SIGSEGV(段错误)信号编号为11.

任何异常只会影响当前进程本身,并不影响整个操作系统以及其它进程

这是因为CPU执行当前进程时,CPU寄存器中的数据只属于当前进程的上下文;

异常信号可以来自硬件异常(比如除0或者野指针错误),通常由CPU指令执行失败触发中断,系统是软硬件的管理者,系统就会知道对应的硬件错误信息,然后向当前进程发送对应的异常信号,当前进程收到异常信号,就会执行默认动作终止退出;而CPU则会获取下一个进程的上下文开始执行,所以并不会受到影响。

如果进程捕获了硬件异常信号但未终止退出,CPU会恢复该进程的上下文,使其从触发异常的指令位置继续执行。如果错误原因未修复,CPU调度执行该进程时,重新执行同一指令会再次触发异常,导致信号循环发送,形成死循环。

以上面的除0错误,进行捕捉但不退出为例:

#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <string>
using namespace std;void handler(int signo){cout << "process,pid: "<<getpid()<<" get a signal: " << signo << endl;// exit(0);
}int main(){// 硬件异常// 除零错误signal(8, handler);int a = 10;int b = 0;int c = a / b;cout << c << endl;return 0;
}

在这里插入图片描述

所以异常信号并不是为了让用户解决问题,而是提示用户当前进程终止退出的错误原因,尽管可以捕捉设置自定义动作,但是如果不退出就会一直报错陷入死循环,并不能解决什么问题,所以对于大部分处理最后都是要终止进程

5.软件条件

异常不光只会由硬件产生,也可能会是软件。

比如之前讲解进程通信时的管道,当通过管道进行通信的两个进程,读端关闭,写端就不能再继续写入,系统就会给写入的进程发送异常信号然后终止退出。

进程由系统进行管理,管道也是由系统创建的共享资源,所以这种就属于软件上的异常;除了这个,还有向未打开的文件进行写入和读取时也是属于软件上的异常。

而软件上除了异常可以产生信号,还有特殊事件—软件条件,比如闹钟就是一种软件条件

在操作系统中,“闹钟”是一种定时器机制,主要通过SIGALRM信号(编号为14)实现:

闹钟是进程可以设置的一种定时器,当指定时间到时,系统会向该进程发送14号信号,在Linux中通过alarm函数实现

#include <unistd.h>unsigned int alarm(unsigned int seconds);

参数seconds指定多少秒后向该进程发送14号信号

返回值:闹钟响时剩余的秒数,如果没有则返回0;如果连续设置多个闹钟,返回值就是上一次闹钟的剩余时间。

进程可以捕捉该信号并自定义处理函数,默认处理会终止进程;闹钟的存在可以实现超时处理机制或者定时执行某些操作

示例:

#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <string>
using namespace std;void handler(int signo){cout << "process,pid: "<<getpid()<<" get a signal: " << signo << endl;
}int main(){// 软件条件---闹钟signal(14, handler);int n = alarm(5);while(true){cout << "I am a process, pid" << getpid() << endl;sleep(1);}return 0;
}

在这里插入图片描述

闹钟不属于软件异常,是系统层面上的一种软件条件

上面5种就是常见的产生信号方式,最后总结一下:无论是哪种方式产生信号,本质上都是由系统发送给进程的,因为操作系统是进程的管理者

三.补充内容–核心转储

下面图中是所有的普通信号,其中大多数信号默认处理动作都是终止退出,但是有的是Term类型的退出(比如2号,9号等),有的是Core类型的退出(比如8号,11号等)

在这里插入图片描述

其中core类型的终止退出表示具有核心转储功能。

1.什么是核心转储

在父进程回收子进程,也就是调用waitpid函数时,用一个输出型参数int status用来表示子进程的退出信息。

其中有一个core dump标志位,如果当前进程收到的异常信号是Trem类型该标志位上就是0,Core类型的就是1。

用一段代码进行测试,父进程创建子进程后,在子进程运行时,向子进程分别发送Trem类型的2号信号和Core类型的8号信号,然后父进程回收子进程打印出status,观察两个不同类型信号最后status的core dump标志位。

#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>using namespace std;int main(){pid_t id = fork();if(id==0){// childint cnt = 100;while(cnt--){cout << "I am a child process, pid: " << getpid() << endl;sleep(1);}exit(0);}// fatherint status = 0;pid_t rid = waitpid(id, &status, 0);if(rid==id){cout << "child quit info, rid: " << rid << " exit code: " << ((status >> 8) & 0xFF) <<" exit signal: " << (status & 0x7F) <<" core dump: " << ((status >> 7) & 1) << endl;}return 0;
}

在这里插入图片描述

因为我这里使用的是云服务器,而云服务器上的core功能默认是关闭的,所以会看到两个都是0。

想要打开需要在命令行中输入下面的指令:

#查看特定的资源
ulimit -a#其中有一个core file size,大小为0,表示关闭
ulimit -c#开启core dump 设置对应的大小
ulimit -c 10240#关闭core dump 设置大小为0
ulimit -c 0

在这里插入图片描述

打开core dump之后再重新发送2和8号信号:

在这里插入图片描述

发送8号信号,core dump标志位变为1,并且生成了一个core.27353的文件。

打开core dump功能后,一旦进程出现异常,系统会将该进程在内存中的运行信息,dump(转储)到进程的当前目录(磁盘),并且形成core.pid文件,这就是核心转储功能

2.为什么要进行核心转储

一旦进程出现错误而异常终止,前面提到过异常信号只是让用户知道进程终止退出的错误原因,而核心转储可以具体定位原始代码中,在运行过程中哪方面出错误。

用一个简单的除0错误代码来测试:

#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>using namespace std;int main(){int a = 10, b = 0;int c = a / b;      // 11行这里的除0错误cout << c << endl;return 0;
}

使用g++编译时带上-g选项,编译后生成可执行文件并运行,最后除0错误而终止退出,生成一个core.1263文件,打开gdb进入调试

直接输入core-file core.1263后,就会自动打印出错误信息,收到8号信号而终止退出,出错原因在第11行。

在这里插入图片描述

核心转储功能加上调试,可以直接复现问题之后,直接定位到出错行,也就是先运行,再core-file事后调试。

所以核心转储功能就是方便进行事后调试。

以上就是关于信号第一部分:信号概念以及信号产生的讲解,如果哪里有错的话,可以在评论区指正,也欢迎大家一起讨论学习,如果对你的学习有帮助的话,点点赞关注支持一下吧!!!

相关文章:

【Linux系统篇】:什么是信号以及信号是如何产生的---从基础到应用的全面解析

✨感谢您阅读本篇文章&#xff0c;文章内容是个人学习笔记的整理&#xff0c;如果哪里有误的话还请您指正噢✨ ✨ 个人主页&#xff1a;余辉zmh–CSDN博客 ✨ 文章所属专栏&#xff1a;Linux篇–CSDN博客 文章目录 一.信号概念1.生活角度的信号2.技术应用角度的信号3.补充内容前…...

SpringSecurity源码解读AbstractAuthenticationProcessingFilter

一、介绍 AbstractAuthenticationProcessingFilter 是 Spring Security 框架里的一个抽象过滤器,它在处理基于表单的认证等认证流程时起着关键作用。它继承自 GenericFilterBean,并实现了 javax.servlet.Filter 接口。此过滤器的主要功能是拦截客户端发送的认证请求,对请求…...

Python torchvision.transforms 下常用图像处理方法

torchvision.transforms 是 PyTorch 用于处理图像数据的一个模块&#xff0c;提供了丰富的图像变换功能。 1. transforms.Compose 的使用方法 transforms.Compose 用于将多个 transforms 操作组合起来&#xff0c;形成一个变换序列&#xff0c;然后按顺序对图像进行处理。其输…...

Zynq7020 制作boot.bin及烧录到开发板全流程解析

Zynq7020作为Xilinx推出的经典SoC芯片&#xff0c;其PS&#xff08;Processing System&#xff09;与PL&#xff08;Programmable Logic&#xff09;协同工作的特性使其在嵌入式开发中广泛应用。然而&#xff0c;初次接触Zynq的开发者在制作启动文件boot.bin及烧录时&#xff0…...

【办公类-89-02】20250424会议记录模版WORD自动添加空格补全下划线

背景需求 4月23日听了一个MJB的征文培训&#xff0c;需要写会议记录 把资料黏贴到模版后&#xff0c;发现每行需要有画满下划线 原来做这套资料&#xff0c;就是手动按空格到一行末&#xff0c;有空格才会出现下划线&#xff0c;也就是要按很多的空格&#xff08;凑满一行&…...

Python-36:饭馆菜品选择问题

问题描述 小C来到了一家饭馆&#xff0c;这里共有 nn 道菜&#xff0c;第 ii 道菜的价格为 a_i。其中一些菜中含有蘑菇&#xff0c;s_i 代表第 ii 道菜是否含有蘑菇。如果 s_i 1&#xff0c;那么第 ii 道菜含有蘑菇&#xff0c;否则没有。 小C希望点 kk 道菜&#xff0c;且希…...

某大型电解铝厂电解系统谐波治理装置改造沃伦森电气

电解铝行业谐波治理解决方案——无源滤波装置优化升级&#xff0c;保障稳定运行 在电解铝生产过程中&#xff0c;谐波污染问题严重影响电网电能质量&#xff0c;甚至可能导致滤波装置损坏&#xff0c;引发群爆事故。河南登封某大型电解铝厂通过无源滤波装置智能化改造&#xff…...

基于YOLO+DeepSeek的农作物病虫害检测系统

前言 本系统是一个基于YOLODeepSeek的农作物病虫害检测系统。 可使用YOLOV1-YOLOV12的任意模型进行目标检测。可以实现检测图片、批量检测图片、视频检测、摄像头检测四种方式。 能够检测出[“苹果-黑腐病”, “苹果-健康”, “苹果-结痂”, “甜椒-细菌性斑疹”, “甜椒-健康…...

Python实现技能记录系统

Python实现技能记录系统 来自网络&#xff0c;有改进。 技能记录系统界面如下&#xff1a; 具有保存图片和显示功能——允许用户选择图片保存&#xff0c;选择历史记录时若有图片可预览图片。 这个程序的数据保存在数据库skills2.db中&#xff0c;此数据库由用Python 自带的…...

【专题刷题】二分查找(一):深度解刨二分思想和二分模板

&#x1f4dd;前言说明&#xff1a; 本专栏主要记录本人的基础算法学习以及LeetCode刷题记录&#xff0c;按专题划分每题主要记录&#xff1a;&#xff08;1&#xff09;本人解法 本人屎山代码&#xff1b;&#xff08;2&#xff09;优质解法 优质代码&#xff1b;&#xff…...

基于Python+Flask的MCP SDK响应式文档展示系统设计与实现

以下是使用Python Flask HTML实现的MCP文档展示系统&#xff1a; # app.py from flask import Flask, render_templateapp Flask(__name__)app.route(/) def index():return render_template(index.html)app.route(/installation) def installation():return render_templa…...

Flask + ajax上传文件(一)

一、概述 本教程将教你如何使用Flask后端和AJAX前端实现文件上传功能,包含完整的代码实现和详细解释。 二、环境准备 1. 所需工具和库 Python 3.xFlask框架jQuery库Bootstrap(可选,用于美化界面)2. 安装Flask pip install flask三、项目结构 upload_project/ ├── a…...

【每天一个知识点】熵(Entropy)

“熵&#xff08;Entropy&#xff09;”是信息论、热力学、机器学习等多个领域的核心概念。它可以用一句话概括为&#xff1a; &#x1f511; 熵表示系统的不确定性或信息混乱程度。 &#x1f4da; 一、信息论中的熵&#xff08;Information Entropy&#xff09; 在 Claude Sh…...

GIT 使用小记

全局设置 PS C:\workspace> git config --global user.name "FreeMan" PS C:\workspace> git config --global user.email "12323772wawhyuser.noreply.gitee.com" PS C:\workspace> git remote add origin https://gitee.com/wawhy/mountain.git…...

如何保证高防服务器中的系统安全?

对于高防服务器中的系统安全&#xff0c;企业通常会采取一系列的防护措施和策略防止网络攻击、入侵、恶意软件和其他网络安全威胁&#xff0c;下面是几个较为主要的安全防护措施&#xff0c;能够帮助企业提升高防服务器的安全性。 定期更新服务器中操作系统以及所有安装的软件&…...

【go语言】window环境从源码编译go

背景 早就听过go语言已经实现自举&#xff0c; 也就是使用旧版本go&#xff0c;来编译新版源码&#xff0c;得到新版本go。 步骤 1. 下载源码 git clone https://github.com/golang/go.git 2. 开始make cd go\src make.bat 3. 等待编译 卡住就按下回车 验证新版本 ……...

医学图像(DICOM数据)读取及显示(横断面、冠状面、矢状面、3D显示)为什么用ITK+VTK,单独用ITK或者VTK能实一样功能吗?

在医学图像处理中&#xff0c;结合使用 ITK 和 VTK 是常见的做法&#xff0c;因为它们各自专注于不同的核心功能。以下是逐步解释为何代码中同时使用两者&#xff0c;以及单独使用是否可行的分析&#xff1a; 1. 为什么用ITK处理DICOM数据&#xff1f; 1.1 ITK的DICOM处理优势…...

TiDB 深度解析与 K8S 实战指南

一、TiDB 核心特性与架构原理 1. 核心特性 分布式架构&#xff1a; 采用计算&#xff08;TiDB Server&#xff09;、存储&#xff08;TiKV&#xff09;、调度&#xff08;PD&#xff09;分离设计&#xff0c;支持水平扩展至 PB 级数据量。通过 PD 动态调度 Region&#xff08…...

WPS右键菜单中“上传到云文档”消失,使用命令行注册解决

关于上传到wps云文档&#xff0c;右键菜单莫名消失的问题 尝试在WPS设置显示上传到wps云文档的右键菜单&#xff0c;以及使用设置和修复工具修复&#xff0c;均无法显示菜单。 最终解决方法&#xff1a; regsvr32 "D:\Program Files (x86)\WPS Office\12.1.0.20784\offic…...

计算机求职面经内容与技巧分享

计算机求职面经内容与技巧分享 一、求职前的充分准备 &#xff08;一&#xff09;简历优化 突出技术能力&#xff1a;在简历中&#xff0c;务必清晰呈现自己精通的编程语言&#xff0c;例如熟练掌握 Java、Python 等语言的核心语法、常用库及框架。详细列举熟悉的技术栈&#x…...

java Springboot使用扣子Coze实现实时音频对话智能客服

一、背景 因公司业务需求&#xff0c;需要使用智能客服实时接听顾客电话。 现在已经完成的操作是&#xff0c;智能体已接入系统进行对练&#xff0c;所以本文章不写对联相关的功能。只有coze对接&#xff5e; 扣子提供了试用Realtime WebSocket&#xff0c;点击右上角setting配…...

焦化烧结行业无功补偿解决方案—精准分组补偿 稳定电能质量沃伦森

在焦化、烧结等冶金行业&#xff0c;负荷运行呈现长时阶梯状变化&#xff0c;功率波动相对平缓&#xff0c;但对无功补偿的分组精度要求较高。传统固定电容器组补偿方式无法动态跟随负荷变化&#xff0c;导致功率因数不稳定&#xff0c;甚至可能因谐波放大影响电网安全。 行业…...

机器人项目管理新风口:如何高效推动智能机器人研发?

在2025年政府工作报告中&#xff0c;“智能机器人”首次被正式纳入国家发展战略关键词。从蛇年春晚的秧歌舞机器人惊艳亮相&#xff0c;到全球首个人形机器人马拉松的热议&#xff0c;智能机器人不仅成为科技前沿的焦点&#xff0c;也为产业升级注入了新动能。而在热潮背后&…...

ZooKeeper配置优化秘籍:核心参数说明与性能优化

#作者&#xff1a;张桐瑞 文章目录 tickTime&#xff1a;Client-Server通信心跳时间initLimit&#xff1a;Leader-Follower初始通信时限syncLimit&#xff1a;Leader-Follower同步通信时限dataDir&#xff1a;数据文件目录clientPort&#xff1a;客户端连接端口服务器名称与地…...

uniapp -- 实现微信小程序、app、H5端视频上传

布局及实现代码&#xff1a; <template><view class"flex flex-column p-4 grid-gap-4"><view class"flex flex-column grid-gap-4 bg-white p-4 rounded-4"><view class"font-weight-600">视频名称</view><i…...

2025年Redis分片存储性能优化指南

一、分片规则与负载均衡 动态哈希分片‌ 采用CRC16算法计算键哈希值&#xff0c;通过hash_slot CRC16(key) % 16384确定槽位分布&#xff0c;结合Redis Cluster自动管理槽位迁移。 总分片数按需动态调整&#xff0c;例如从16节点扩容至32节点时&#xff0c;触发槽位重分配以…...

前端跨端框架的开发以及IOS和安卓的开发流程和打包上架的详细流程

以下是关于 前端跨端框架开发 以及 iOS/Android 原生开发流程与上架 的详细指南&#xff0c;涵盖技术选型、开发工具、打包发布全流程&#xff1a; 一、前端跨端开发框架对比与流程 主流跨端框架 框架技术栈性能接近原生生态成熟度适用场景React NativeJS/React80%⭐⭐⭐⭐⭐…...

项目《基于Linux下的mybash命令解释器》(二)

一、使用系统命令的完整代码 #include<stdio.h> #include<wait.h> #include<stdlib.h> #include<unistd.h> #include<assert.h> #include<string.h> #include<pwd.h>#define ARG_MAX 10//防止参数不够&#xff0c;可以做到一改全改…...

arm64适配系列文章-第十章-arm64环境上jenkins的部署

ARM64适配系列文章 第一章 arm64环境上kubesphere和k8s的部署 第二章 arm64环境上nfs-subdir-external-provisioner的部署 第三章 arm64环境上mariadb的部署 第四章 arm64环境上nacos的部署 第五章 arm64环境上redis的部署 第六章 arm64环境上rabbitmq-management的部署 第七章…...

PyTorch生成式人工智能实战(2)——PyTorch基础

PyTorch生成式人工智能实战&#xff08;2&#xff09;——PyTorch基础 0. 前言1. 创建 PyTorch 张量2. PyTorch 张量索引和切片3. PyTorch 张量形状4. 在 PyTorch 张量数学运算小结系列链接 0. 前言 为了训练生成式人工智能模型&#xff0c;我们可以使用多种数据格式&#xff…...

解决高德地图AMapUtilCoreApi、NetProxy类冲突

问题&#xff1a; Duplicate class com.amap.apis.utils.core.api.AMapUtilCoreApi found in modules jetified-3dmap-10.0.600 (com.amap.api:3dmap:10.0.600) and jetified-search-9.7.1 (com.amap.api:search:9.7.1) Duplicate class com.amap.apis.utils.core.api.NetProx…...

java—14 ZooKeeper

一、ZooKeeper简介 ZooKeeper是一种分布式协调服务&#xff0c;用于管理大型主机。在分布式环境中协调和管理服务 是一种复杂的过程&#xff0c;ZooKeeper通过简单的架构和API解决了这个问题。ZooKeeper运行开 发人员专注于核心应用程序逻辑&#xff0c;而不必担心应用程序的分…...

特征存储的好处:特征存储在机器学习开发中的优势

随着企业寻求提升机器学习生产力和运营能力 (MLOps),特征存储 (Feature Store) 的普及度正在迅速提升。随着 MLOps 技术的进步,特征存储正成为机器学习基础设施的重要组成部分,帮助企业提升模型的性能和解释能力,并加速新模型与生产环境的集成。这些存储充当集中式存储库,…...

【Promethus(普罗米修斯)介绍安装及使用】

一、系统介绍 1、什么是Prometheus? Prometheus:不仅是一款时间序列数据库,在整个生态上还是一套完整的监控系统。同时,还涉及许多以“explore”命名的客户端数据采集工具以及pushgateway网关。 官网:https://prometheus.io/ 文献:https://prometheus.io/docs/introdu…...

力扣热题100题解(c++)—矩阵

73.矩阵置零 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 int m matrix.size(); // 行数int n matrix[0].size(); // 列数bool firstRowZero false; // 标记第一行是否包含 0bool f…...

Spring Boot Controller 单元测试撰写

文章目录 引言标准用法必需依赖项核心注解说明代码示例 当涉及静态方法时的测试策略必需依赖项核心注解说明代码示例 引言 之前在编写 Controller 层的单元测试时&#xff0c;我一直使用 SpringBootTest 注解&#xff0c;但它会加载整个 Spring 应用上下文&#xff0c;资源开销…...

MVCC详解

目录 undo日志版本链 read view一致性视图 MVCC过程分析 读事务&写事务 Multi-Version Concurrency Control&#xff0c;多版本并发控制在读已提交和可重复读隔离级别下都实现了MVCC机制 undo日志版本链 一行数据被修改后&#xff0c;MySQL会保留修改前的数据&#xff08;u…...

【通关函数的递归】--递归思想的形成与应用

目录 一.递归的概念与思想 1.定义 2.递归的思想 3.递归的限制条件 二.递归举例 1.求n的阶乘 2.顺序打印一个整数的每一位 三.递归与迭代 前言:上篇博文分享了扫雷游戏的实现&#xff0c;这篇文章将会继续分享函数的递归相关知识点&#xff0c;让大家了解并掌握递归的思…...

Python爬虫实战:移动端逆向工具Fiddler经典案例

一、引言 在移动互联网迅猛发展的当下,移动端应用产生了海量的数据。对于开发者而言,获取这些数据对于市场调研、竞品分析、数据挖掘等工作具有重要意义。Fiddler 作为一款功能强大的 Web 调试代理工具,能够有效捕获、分析和修改移动端的网络请求,为开发者深入了解移动端网…...

从平台工程视角出发,重塑云原生后端的工程体系

📝个人主页🌹:慌ZHANG-CSDN博客 🌹🌹期待您的关注 🌹🌹 一、引言:从 DevOps 到平台工程,云原生后端的演进逻辑 云原生的广泛应用,使得后端系统的开发、部署与运维逐渐从“编写业务代码”演进为“构建工程平台”。过去,后端开发者通常将注意力集中于 API 编写…...

【Hive入门】Hive分区与分桶深度解析:优化查询性能的关键技术

引言 在大数据领域&#xff0c;Apache Hive作为构建在Hadoop之上的数据仓库工具&#xff0c;因其类SQL的查询语言(HiveQL)和良好的扩展性而广受欢迎。然而&#xff0c;随着数据量的增长&#xff0c;查询性能往往成为瓶颈。本文将深入探讨Hive中两种关键的数据组织技术——分区(…...

Pytorch中的Dataset和DataLoader

1. PyTorch数据处理的核心概念 在PyTorch中,数据处理主要依赖两个核心组件: torch.utils.data.Dataset:定义如何访问数据集(单个样本的数据和标签)。torch.utils.data.DataLoader:负责批量加载数据、打乱数据、并行加载等。1.1 为什么需要Dataset和DataLoader? 问题:深…...

中介者模式:解耦对象间复杂交互的设计模式

中介者模式&#xff1a;解耦对象间复杂交互的设计模式 一、模式核心&#xff1a;用中介者统一管理对象交互&#xff0c;避免两两直接依赖 当系统中多个对象之间存在复杂的网状交互时&#xff08;如 GUI 界面中按钮、文本框、下拉框的联动&#xff09;&#xff0c;对象间直接调…...

IEEE综述 | 车道拓扑推理20年演进:从程序化建模到车载传感器

导读 车道拓扑推理对于高精建图和自动驾驶应用至关重要&#xff0c;从早期的程序化建模方法发展到基于车载传感器的方法&#xff0c;但是很少有工作对车道拓扑推理技术进行全面概述。为此&#xff0c;本文系统性地调研了车道拓扑推理技术&#xff0c;同时确定了未来研究的挑战和…...

手撕C++STL list:深入理解双向链表的实现

目录 1. 引言 3. list 类的实现 (1) 基本结构 (2) 初始化与清理 (3) 插入与删除 (4) 常用接口 (4) 常用接口 4. 测试代码 5. 总结 1. 引言 在C STL中&#xff0c;list是一个基于双向链表的容器&#xff0c;支持高效的头尾插入/删除操作&#xff08;O(1)时间复杂度&…...

QMT学习课程Day1

我们先从交易的最基础&#xff0c;如何进行下单&#xff0c;最为简答的下单&#xff0c;帮助大家建立自信心。 首先导入相关函数&#xff1a; #encoding:gbk import pandas as pd import numpy as np import datetime import pandas as pd import numpy as np import talib i…...

【Rust结构体】Rust结构体详解:从基础到高级应用

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…...

Java面试实战:音视频场景下的微服务架构与缓存技术剖析

面试场景描述 谢飞机&#xff0c;一位自称“全栈工程师”的程序员&#xff0c;来到一家互联网大厂参加Java开发岗位的面试。面试官是一位严肃的技术专家&#xff0c;他希望通过一系列问题考察谢飞机的实际技术水平。 第一轮提问&#xff08;基础问题&#xff09; 面试官&…...

Vue 3 的核心组合式 API 函数及其完整示例、使用场景和总结表格

以下是 Vue 3 的核心组合式 API 函数及其完整示例、使用场景和总结表格&#xff1a; 1. ref 作用 创建一个响应式引用值&#xff0c;用于管理基本类型或单个值的响应式状态。 示例 <template><div><p>Count: {{ count }}</p><button click&quo…...

Kotlin学习基础知识大全(上)

文章目录 Kotlin基础知识全面解析第一章&#xff1a;Kotlin语言概述1.1 Kotlin的发展历程1.2 Kotlin的设计目标1.3 Kotlin的应用领域1.4 Kotlin与Java的比较 第二章&#xff1a;Kotlin基础语法2.1 变量与常量2.2 基本数据类型数字类型示例&#xff1a;字符和字符串示例&#xf…...