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

Linux系统编程——系统内核中的信号

目录

一、前言

二、系统内核中的信号

三、sigset_t

四、信号集操作

1、sigpending();

2、sigemptyset();

3、sigfillset(sigset_t *set);

4、int sigaddset ()和sigdelset()

​编辑

5、sigismember()

 6、sigprocmask()

五、信号集操作代码演示

六、深入理解进程的信号处理

1、进程的内核态与用户态


一、前言

在信号这一篇我们已经了解了什么是信号,和信号的产生方式及信号的捕捉,但是那些都是信号在用户层的理解,同时也产生了几个问题:

  1. 之前讲到的所有进程信号的产生都需要OS来执行,为什么?
  2. 我们提到进程在接收到信号之后通常有着三种处理方式,那么针对这三种处理方式,进程是立即处理的吗?如果不是立即处理,那么信号是否需要暂时被进程记录下来?记录下来放在哪里呢?
  3. 一个进程在没有收到信号的时候,怎么知道自己应该对合法信号作何处理呢?
  4. 怎么理解OS向进程发送信号?是怎么发送的?具体情况是什么?

接下来我们将从系统内核层面着重讨论和理解进程信号产生之后进程处理信号的详细操作以及进程信号的产生到进程接收之间内核做了哪些事情。

首先我们还得知道几个概念:

  1. 信号递达:进程对信号的实际处理动作。
  2. 信号未决(pending):信号从产生到递达之间的状态,即信号接收到了但是还没有处理的状态。
  3. 进程可以选择阻塞(Block)某个信号,即进程接收到了信号,但是阻塞信号递达,就是不做处理。
  4. 当信号被阻塞时,该信号将保持未决状态,知道进程解除对此信号的阻塞,此时信号才会递达。
  5. 注意 信号阻塞信号忽略 不同,信号忽略是对信号的处理动作,即信号已经递达了。而阻塞是信号抵达之前的状态。

二、系统内核中的信号

在上篇文章中,我们简单提到过,进程信号是以位图的方式存储在进程的PCB中的,通常每个信号对应位图中的一个特定位置,即一个比特位,如果该比特位设置为1,表示对应信号已经收到但是尚未处理;若为0.则表示没有收到该信号。那么具体是什么样子的呢?

事实上,在PCB中描述着两个有关进程的位图和一个有关进程信号的指针数组如下

  • pending位图:pending表示信号未决,所以它是未决位图,用来表示进程收到了信号,对应位置即为对应编号的信号,当该位图中的某个位置设置为1时,即表示此位的信号在进程中处于未决状态,即接收到了信号但是还未处理。
  • handler指针数组:显而易见,存储的是信号处理方法的数组,每位对应一个处理方法。
  • block位图:阻塞位图,表示对应位置的进程信号是否阻塞,当指定位置为1时,即表示此位置的信号会被阻塞。 

分析上图:

1、SIGHUP(1) 信号, 进程对此信号的处理方法是 SIG_DFL(默认处理动作), 进程并没有收到此信号(pending为0), 也没有阻塞此信号递达(block为0),所以当该信号递达时执行默认处理动作。
2、SIGINT(2) 信号, 进程对此信号的处理方法是 SIG_IGN(忽略), 进程收到了此信号(pending为1), 但是进程会阻塞此信号递达(block为1), 即 进程收到的信号会一直处于未决状态(pending一直为1). 除非阻塞解除。但是在解除对这个信号的阻塞前仍然不能忽略这个信号,因为进程仍有机会改变处理动作之后在接触阻塞。
3、SIGQUIT(3) 信号, 此进程对此信号的处理方法是自定义的 sighandler(), 进程没有收到此信号(pending为0), 但是进程会阻塞此信号递达(block为1), 也就是说 即使进程收到了此信号, 此信号也会一直处于未决状态, 除非阻塞解除

三、sigset_t

 从上面来看,pending位图和block位图所表示的信息能力都是有限的,其每一位的0 1都只能表示进程信号是否存在或者阻塞并不能表示有多少信号产生并发送给了进程。

所以,对于普通信号来说,当进程阻塞了该信号时,表明该信号已经处于未决状态了,即使再多次的向进程发送此信号,当阻塞解除时,进程最终也只会处理一次信号(如果不存在阻塞的话,如果向进程一直发送信号,进程则会一直处理)

然而事实上,在Linux操作系统中,pending和block并不是以整型来表示位图的,而是以一个结构体的形式:sigset_t

sigset_t 是一个 typedef 出来的类型, 实际上是一个结构体 __sigset_t, 不过这个结构体内部只有一个 unsigned long int 类型的数组 ,也就是说pending和block位图其实是以数组的形式表现出来的。

而其中, 实际以 sigset_t 形式表现的 pending位图, 被称为 未决信号集; 同样以 sigset_t 形式表现的 block位图, 被称为 阻塞信号集, 也叫 信号屏蔽字

四、信号集操作

由于信号集实际上是以数组来表示位图的,且由于数组大小是一个宏定义的,所以大小是变化的,所以我们不能通过 直接访问数组来对信号集进行操作 ,但是系统为用户提供了相关的系统调用接口:

int sigpending(sigset_t *set);
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset (sigset_t *set, int signo);
int sigdelset(sigset_t *set, int signo);
int sigismember(const sigset_t *set, int signo);

1、sigpending();

该接口的作用是检查未决信号集,即获取进程的未决信号集。其参数是一个输出型参数,获取的未决信号集的內容会存储在传入的变量中,但是我们并不能通过修改获取到的该进程的未决信号集的內容想要一次来修改进程当前的未决信号集。成功则返回0,错误返回-1.

2、sigemptyset();


调用此接口会将传入的信号集初始化为空, 即所有信号、阻塞会被消除, 信号集的所有位设置为0,成功返回0, 错误返回-1

3、sigfillset(sigset_t *set);

调用此函数, 会将传入的信号集所有位设置为1.成功返回0, 错误返回-1

4、int sigaddset ()和sigdelset()

 前者的作用是, 给指定信号集中添加指定信号, 即 将指定信号集中的指定位置设置为1

后者的作用是, 删除指定信号集中的指定信号, 即 将指定信号集中的指定位置设置为0

着两个函数, 都是成功返回0, 失败返回-1.

5、sigismember()

调用此函数, 可以判断 信号集中是否有某信号.判断信号集的某位是否为1

如果 信号在信号集中 返回1, 如果不在 返回0, 如果出现错误 则返回-1

 6、sigprocmask()

 这个接口的作用是:获取 修改 信号屏蔽字(阻塞信号集)

1、首先是第二个参数

第二个参数需要传入一个信号集,此信号集是 修改进程的信号屏蔽字 用的,此参数需要根据第一个参数的不同来传入不同意义的信号集

2、然后是第三个参数

该参数也是需要传入一个信号集,不过传入被全部置为0的信号集。此参数是一个输出型参数,用于获取 没做修改的信号屏蔽字,即该函数接口执行完毕后,此参数里存放的是没有执行此函数的原始的信号屏蔽字。

3、第一个参数

该参数是一个整型参数,需要传入的是系统提供的宏,不同宏的选择此函数会有不同的功能, 就需要传入不同意义的 set(第二个参数)

即如果想要为指定位置添加阻塞

为指定位置解除阻塞

 

直接设置阻塞 

五、信号集操作代码演示

接下来我们演示,先对该进程的信号屏蔽字(阻塞集)做修改,将信号屏蔽字置为0,即将所有的普通信号都进行阻塞。

接着该进程的未决信号集都置为0,表示此时没有产生任何信号。

接着我们通过命令行 kill 的方式不断给该进程发送信号。

通过程序内的打印进程的未决信号集的一个函数我们就可以看到该进程的当前的未决信号集。

#include <iostream>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
using std::cout;
using std::cerr;
using std::endl;int cnt = 0;
void handler(int signo) {cout << "我是进程, pid: " << getpid() << ", 我捕捉到一个信号:" << signo << ", count: " << cnt++ << endl;
}// 打印信号集的函数
void showSignals(sigset_t *signals) {// 使用 sigismember() 接口判断 31个普通信号是否在信号集中存在// 存在的信号输出1, 否则输出0for(int sig = 1; sig <= 31; sig++) {if(sigismember(signals, sig)) {cout << "1";}else {cout << "0";}}cout << endl;
}int main() {// 先输出进程的 pidcout << "pid: " << getpid() << endl;// 定义sigsetmask()需要使用的 set 和 oldset, 并初始化sigset_t sigset, osigset;sigemptyset(&sigset);sigemptyset(&osigset);// 将进程的 所有普通信号屏蔽for(int sig = 1; sig <= 31; sig++) {sigaddset(&sigset, sig);signal(sig, handler);}sigprocmask(SIG_BLOCK, &sigset, &osigset);// 获取并打印进程的未决信号集sigset_t pendings;while(true) {sigemptyset(&pendings);sigpending(&pendings);showSignals(&pendings);sleep(1);}return 0;
}

 运行结果,可以看到结果符合预期实验,也同时验证了9号信号的特殊之处(不能被捕获、忽略或阻塞)。

接下来我们设置一段时间以后放开一些信号的阻塞,看看结果

六、深入理解进程的信号处理

 在文章开篇的时候我们提到过几个问题,第二个问题是当进程收到信号之后会立即处理吗?答案是不会,进程会在合适的时候处理信号,那么这个合适的时间是什么时候呢?

合适的时候,即当进程从内核态转换为用户态的时候,进程会进行信号的检测与处理,所以什么是内核态?什么又是用户态呢?

1、进程的内核态与用户态

我们知道对于系统中的每一个进程其都有自己的一份独立的程序地址空间

且进程地址空间与物理内存是通过页表映射的。但是之前讲到的只是 用户空间部分与物理内存之间的相互映射。 

事实上 ,对于1GB的内核空间,也存在着一张页表,用于内核空间和物理内存之间的相互映射,称为内核级页表

且与用户级的页表不同,内核级的页表整个操作系统只有一张,即在整个操作系统中,所有的进程共用一张内核级页表。

如上图所示,所有的进程都用着同一张内核级页表,也就是说每个进程的内核空间的内容是一样的,也就是说物理内存中只加载着一份有关于进程内核空间内容的数据代码。

想象一下,如果每个进程都可以访问及随意修改内核空间中的数据代码,这是一件很恐怖的事情,毕竟操作系统做了那么多工作,提供了那么多系统调用封装了那么多系统接口,就是为了不让用户直接操作系统内核。

所以为了保护这部分数据代码,进程会分为两种状态: 内核态 和 用户态

当进程 需要访问、调用、执行 内核数据 或 代码(中断、陷阱、系统调用等)时, 就会 陷入内核, 转化为内核态, 因为只有 进程处于内核态时, 才有权限访问内核级页表, 即有权限访问内核数据与代码。

当进程不需要访问、调用、执行 内核数据 或 代码, 或进程时间片结束时, 就会 返回用户, 转化为 用户态 , 此时 进程将不具备访问内核级页表的权限, 只能访问用户级页表

       也就是在进程从内核态转换为用户态时,系统才会检测进程的信号并处理。 那么系统如何分清当前的进程处于哪一种状态下呢?

事实上,在CPU内部存在着一个 状态寄存器CR3,此寄存器内有比特标识位标识当前进程的状态。

  1. 若标识位 表示0, 则表明进程此时处于内核态
  2. 若标识位 表示3, 则表明进程此时处于用户态

       在操作系统中,当进程处于运行时,它会有两种状态,用户态和内核态,且在进程的整个周期内会发生着无数次的状态转换。因为我们使用的语言大部分情况下是 没有资格直接访问系统的软硬件资源的 ,本质上我们都是通过调用系统所提供的接口,通过系统去访问这些资源,这样的情况下,进程需要访问硬件资源地时候,就会无数次地陷入内核(切换状态、切换页表),再访问内核代码数据, 然后完成访问,再将结果返回给用户(切换状态,切换页表),最终用户得到结果。

       还有一种情况,在用户不调用任何函数的时候,这时候还会发生进程状态的转换吗?答案是会的。因为只要是进程, 那么他就有一定的时间片. 即使是一个什么都不执行的死循环, 只要时间片用完了, 那么就需要将此进程从CPU上剥离下来, 而剥离操作一定是操作系统做的, 那么也就是说将 进程从CPU上剥离下来也是需要陷入内核执行内核代码的. 将进程从CPU上剥离下来的时候, 需要维护一下进程的上下文, 以便下次接着执行进程的代码.剥离下来之后, 操作系统执行调度算法, 将下一个需要运行的进程的上下文加载到CPU中, 然后新进程从内核态转换为用户态, CPU再执行新进程的代码.

进程被剥离下来, 进程会进入内核态维护起来. 等待下次运行时, 又会回到用户态执行代码.


下面我们举个例子详细分析一下在进程切换状态的时候,信号在什么时候处理。

如图所示:

  1.  代码在运行到需要执行系统调用open()接口的时候,此时进程就需要陷入内核态执行open()代码
  2. 陷入内核并执行完open()代码后, 需要将open()结果返回给用户, 需要转换回用户态
  3. 在转换回用户态之前, 需要先在进程PCB中检测进程的未决信号集
  4. 在未决信号集中, 检测到1和2信号未决, 并且均未被屏蔽(阻塞). 就需要在handler数组中寻找指定的处理方法
  5. 1信号默认处理, 需要执行内核中的默认处理方法(一般为进程终止); 2信号忽略处理, 直接将未决信号集中2信号改为0
  6. 处理完信号, 再将open()结果返回给用户, 这个过程需要转换为用户态

上面的信号的处理方式都是默认或者是忽略,但是如果我们捕捉了一个信号并且让它按照自定义的方式处理,这时候在最后一步怎么办?

       实际上进程就会先去 执行自定义的信号处理动作,然后再将open()的结果返回给用户。且自定义函数是用户实现的,所以进程需要先切回用户态执行完信号的自定义处理动作函数。

        接着进程原本是因为需要执行内核代码才陷入内核的, 只是在执行完毕之后需要先处理一下信号才暂时回到了用户态。此时进程是无法返回到进程原本代码的执行位置的。因为进程执行内核代码之后的返回信息还在内核中,以用户态的身份是无法访问并返回给用户的。

        所以, 进程在以用户态的身份执行过信号的用户处理方法之后, 还需要再次陷入内核, 然后根据内核中的返回信息使用特定的返回调用 返回到用户.

图示如下:

可以看到, 如果处理信号需要执行用户自定义的处理方法时, 那么 从调用内核代码到返回用户 的整个过程一共需要 经历4次状态转换

而, 如果处理信号不需要执行用户自定义处理方法时, 那么 从调用内核代码到返回用户 的整个过程 就只需要 经历2次状态转换

 下面是简化版

需要注意的是

进程执行完用户自定义信号处理方法 返回内核之后, 之后的执行流程与PCB信号集有一个交点.

此交点表示, 此时 还会进行 信号集的检测.

如果此时又有信号未决, 并且时间片充足, 那么就会再次处理.

进程处理信号时, 如果操作系统还向进程发送相同的信号, 进程时不会处理的. 因为pending信号集中 只能表示信号是否存在, 而不能记录信号被发送过来的次数. 也就是说, 信号未决时, 依旧有相同的信号发送过来, 进程不会处理后续的信号.

相关文章:

Linux系统编程——系统内核中的信号

目录 一、前言 二、系统内核中的信号 三、sigset_t 四、信号集操作 1、sigpending(); 2、sigemptyset(); 3、sigfillset(sigset_t *set); 4、int sigaddset ()和sigdelset() ​编辑 5、sigismember() 6、sigprocmask() 五、信号集操作代码演示 六、深入理解进程的信…...

Mapbox-GL 中 `token` 的使用

Mapbox-GL 是一个开源的 JavaScript 库&#xff0c;允许开发者在网页上渲染交互式地图。token 在 Mapbox 中主要是指 access token&#xff0c;它用于身份验证和授权&#xff0c;确保应用程序能够访问 Mapbox 的地图服务。 下面详细解析 Mapbox GL 中 token 的使用&#xff0c…...

PostgreSQL标识符长度限制不能超过63字节

文章目录 问题&#xff1a;标识符太长会被截断分析相关源码可以尝试以下案例 问题&#xff1a;标识符太长会被截断 在创建表时&#xff0c;发现表名太长会自动被截断&#xff0c;导致查询表时报错了。 分析 参考&#xff1a;https://www.postgresql.org/docs/current/limits…...

【Token】校验、会话技术、登录请求、拦截器【期末实训】实战项目学生和班级管理系统\Day15-后端Web实战(登录认证)\讲义

登录认证 在前面的课程中&#xff0c;我们已经实现了部门管理、员工管理的基本功能&#xff0c;但是大家会发现&#xff0c;我们并没有登录&#xff0c;就直接访问到了Tlias智能学习辅助系统的后台。 这是不安全的&#xff0c;所以我们今天的主题就是登录认证。 最终我们要实现…...

电机相关内容

文章目录 电枢电阻电动机电动势系数负载转矩直流电动机的角速度和速度关系 电枢电阻 电枢电阻的计算公式‌如下&#xff1a; 基于欧姆定律的公式‌&#xff1a; R a V a − V b I a R_a \frac{V_a - V_b}{I_a} Ra​Ia​Va​−Vb​​ 其中&#xff0c; ( V a ) (V_a) (Va​…...

电商环境下的财务ERP系统架构

先介绍一下自己的工作经历&#xff0c;2002年开始进入ERP实施行业&#xff0c;专注于O记EBS系统&#xff0c;正好赶上中国经济和信息化高度发展的阶段&#xff0c;先后实施过很多大国企和民企的大型ERP项目&#xff0c;在实施过程中逐渐对ERP系统的架构、模块设计有更深入的认识…...

Gitlab 数据备份全攻略:命令、方法与注意事项

文章目录 1、备份命令2、备份目录名称说明3、手工备份配置文件3.1 备份配置文件3.2 备份ssh文件 4、备份注意事项4.1 停止puma和sicdekiq组件4.2 copy策略需要更多磁盘空间 5、数据备份方法5.1 docker命令备份5.2 kubectl命令备份5.3 参数说明5.4、选择性备份5.5、非tar备份5.6…...

基于单片机的视力保护及身姿矫正器设计(论文+源码)

1. 系统设计 在本次设计中&#xff0c;其系统整个框图如图2-1所示。其主要的核心控制模块由超声波模块&#xff0c;光敏电阻&#xff0c;按键模块&#xff0c;复位电路&#xff0c;红外模块&#xff0c;LCD显示等组成。其包括自动模式&#xff0c;手动模式。自动模式&#xff…...

设计模式之【观察者模式】

观察者模式&#xff1a; 应用于发布-订阅消息模型中&#xff0c;订阅者订阅一个主题后&#xff0c;当有新消息到达时&#xff0c;所有订阅者都会收到通知。 主要关注的是对象之间的通信。是一种对象之间的一对多关系&#xff0c;多个对象依赖于一个对象&#xff0c;当被依赖的…...

杂七杂八的网络安全知识

一、信息安全概述 1.信息与信息安全 信息与信息技术 信息奠基人&#xff1a;香农&#xff1a;信息是用来消除随机不确定性的东西 信息的定义&#xff1a;信息是有意义的数据&#xff0c;是一种要适当保护的资产。数据经过加工处理之后&#xff0c;就成为信息。而信息需要经…...

【落羽的落羽 C语言篇】数据存储简介

文章目录 一、整型提升1. 概念2. 规则 二、大小端字节序1. 概念2. 练习练习1练习2 三、浮点数在内存中的存储1. 规则2. 练习 一、整型提升 1. 概念 C语言中&#xff0c;整型算术运算至少是以“缺省整型类型”&#xff08;int&#xff09;的精度来进行的。为了达到这个精度&am…...

linux----文件访问(c语言)

linux文件访问相关函数 打开文件函数 - open 函数原型&#xff1a;int open(const char *pathname, int flags, mode_t mode);参数说明&#xff1a; pathname&#xff1a;这是要打开的文件的路径名&#xff0c;可以是绝对路径或者相对路径。例如&#xff0c;"/home/user/…...

垂起固定翼无人机大面积森林草原巡检技术详解

垂起固定翼无人机大面积森林草原巡检技术是一种高效、精准的监测手段&#xff0c;以下是对该技术的详细解析&#xff1a; 一、垂起固定翼无人机技术特点 垂起固定翼无人机结合了多旋翼和固定翼无人机的优点&#xff0c;具备垂直起降、飞行距离长、速度快、高度高等特点。这种无…...

汽车电子零部件(15):AVM全景影像系统

概述: 使用ADAS全景监控(AVM)精确停车和操纵。这项先进技术采用多个摄像头,提供车辆周围环境的鸟瞰图。 360度全景监控系统: 360 AVM系统可以帮助驾驶员360度查看车辆周围的情况,避免发生碰撞。360 AVM系统由一个电子控制单元(ECU)和四个摄像头组成。ECU将处理四个摄…...

G口带宽服务器与1G独享带宽服务器:深度剖析其差异

在数据洪流涌动的数字化时代&#xff0c;服务器作为数据处理的核心&#xff0c;其性能表现直接关系到业务的流畅度和用户体验的优劣。随着技术的飞速发展&#xff0c;G口带宽服务器与1G独享带宽服务器已成为众多企业的优选方案。然而&#xff0c;这两者之间究竟有何细微差别&am…...

鸿蒙项目云捐助第十一讲鸿蒙App应用的捐助成功自定义对话框组件实现

在生活中&#xff0c;用户做了一个好事后&#xff0c;很多场合都会收到一份感谢。在捐助的行业也是一样的&#xff0c;用户捐出了一片爱心&#xff0c;就会收获一份温情。这里的温情是通过自定义对话框实现的。 一、通过自定义对话框组件实现捐款成功的信息页 这里用户捐款成…...

Elasticsearch-分词器详解

什么是分词器 1、分词器介绍 对文本进行分析处理的一种手段&#xff0c;基本处理逻辑为按照预先制定的分词规则&#xff0c;把原始文档分割成若干更小粒度的词项&#xff0c;粒度大小取决于分词器规则。 常用的中文分词器有ik按照切词的粒度粗细又分为:ik_max_word和ik_smart&…...

Android笔试面试题AI答之Android基础(3)

文章目录 1.谈一谈 Android 的安全机制一、系统架构层面的安全设计二、核心安全机制三、其他安全机制与措施 2.Android 的四大组件是哪四大&#xff1f;3.Android 的四大组件都需要在清单文件中注册吗&#xff1f;4.介绍几个常用的Linux命令一、文件和目录管理二、用户和权限管…...

酷黑金色配色 影片素材不过时 色彩丰富 电影主题html

本套大作业共计8个HTML页面&#xff0c;网页中包含&#xff1a;DIVCSS、下拉菜单栏、banner轮播图、图片放大效果、鼠标滑过效果、视频、小图标及按钮设计、登录注册页等&#xff0c;同时设计了logo&#xff1b;本作品花费大量时间去整理素材&#xff0c;大部分素材均使用Photo…...

《Go 语言变量》

《Go 语言变量》 介绍 Go 语言是一种静态类型、编译型的编程语言&#xff0c;由 Google 开发。它以其简洁的语法、高效的并发处理和强大的标准库而闻名。在 Go 语言中&#xff0c;变量是存储数据的基本单位&#xff0c;它们可以是各种数据类型&#xff0c;如整数、浮点数、布…...

Tool之Excalidraw:Excalidraw(开源的虚拟手绘风格白板)的简介、安装和使用方法、艾米莉应用之详细攻略

Tool之Excalidraw&#xff1a;Excalidraw(开源的虚拟手绘风格白板)的简介、安装和使用方法、艾米莉应用之详细攻略 目录 Excalidraw 简介 1、Excalidraw 的主要特点&#xff1a; Excalidraw 安装和使用方法 1、Excalidraw的安装 T1、使用 npm 安装&#xff1a; T2、使用 …...

Llama 3 模型系列解析(一)

目录 1. 引言 1.1 Llama 3 的简介 1.2 性能评估 1.3 开源计划 1.4 多模态扩展 ps 1. 缩放法则 2. 超额训练&#xff08;Over-training&#xff09; 3. 计算训练预算 4. 如何逐步估算和确定最优模型&#xff1f; 2. 概述 2.1 Llama 3 语言模型开发两个主要阶段 2.2…...

重拾设计模式--观察者模式

文章目录 观察者模式&#xff08;Observer Pattern&#xff09;概述观察者模式UML图作用&#xff1a;实现对象间的解耦支持一对多的依赖关系易于维护和扩展 观察者模式的结构抽象主题&#xff08;Subject&#xff09;&#xff1a;具体主题&#xff08;Concrete Subject&#xf…...

3-Gin 渲染 --[Gin 框架入门精讲与实战案例]

在 Gin 框架中&#xff0c;渲染指的是将数据传递给模板&#xff0c;并生成 HTML 或其他格式的响应内容。Gin 支持多种类型的渲染&#xff0c;包括 String HTML、JSON、XML 等。 String 渲染 在 Gin 框架中&#xff0c;String 渲染方法允许你直接返回一个字符串作为 HTTP 响应…...

回溯---java---黑马

回溯 概念 程序在运行过程中分成了多个阶段 通过某些手段&#xff0c;将数据恢复到某一阶段&#xff0c;称之为回溯 手段包括&#xff1a;方法栈、自定义栈 使用基本数据类型n public class Backtracking{public static void main(String[] args) {rec(1);}public void r…...

【数据结构】排序(附测试源码)

【数据结构】排序&#xff08;附测试源码&#xff09; 本节是数据结构排序版&#xff08;不完整版&#xff0c;没有C语言版的哈希表&#xff09; 1.排序概念&#xff1a; 1.1所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增…...

【翻译】大型 Transformer 模型推理优化

翻译原文&#xff1a;Large Transformer Model Inference Optimization | LilLog 原文作者&#xff1a;Lilian Weng 目录 方法概述蒸馏 Distillation量化 Quantization Transformer 量化的挑战训练后量化 (PTQ) 混合精度量化 Mixed-precision quantization细粒度量化量化的二…...

RabbitMQ概述

目录 RabbitMQ概述 前言 MQ MQ的作用 为什么选择RabbitMQ RabbitMQ的介绍 RabbitMQ概述 前言 Rabbit, 兔⼦的意思 互联⽹⾏业很多公司, 都喜欢⽤动物命名产品, 或者作为公司的logo, 吉祥物. ⽐如: 腾讯的企鹅, 京东的狗, 美团的袋⿏, 携程的海豚,阿⾥就更多了, 蚂蚁, ⻜…...

《PCI密码卡技术规范》题目

单选1 在《PCI密码卡技术规范》中,下列哪项不属于PCI密码卡的功能()。 A.密码运算功能 B.密钥管理功能 C.物理随机数产生功能 D.随主计算机可信检测功能 正确答案:D. <font style="color:#DF2A3F;">解析:</font> 单选 2 在《PCI密码卡技术规…...

AI开发:使用支持向量机(SVM)进行文本情感分析训练 - Python

支持向量机是AI开发中最常见的一种算法。之前我们已经一起初步了解了它的概念和应用&#xff0c;今天我们用它来进行一次文本情感分析训练。 一、概念温习 支持向量机&#xff08;SVM&#xff09;是一种监督学习算法&#xff0c;广泛用于分类和回归问题。 它的核心思想是通过…...

ECharts柱状图-柱图42,附视频讲解与代码下载

引言&#xff1a; 在数据可视化的世界里&#xff0c;ECharts凭借其丰富的图表类型和强大的配置能力&#xff0c;成为了众多开发者的首选。今天&#xff0c;我将带大家一起实现一个柱状图图表&#xff0c;通过该图表我们可以直观地展示和分析数据。此外&#xff0c;我还将提供…...

呼入机器人:24小时客户服务的未来趋势

呼入机器人&#xff1a;24小时客户服务的未来趋势 作者&#xff1a;开源大模型智能呼叫中心系统FreeAICC&#xff0c;Github&#xff1a;https://github.com/FreeIPCC/FreeAICC 在当今快节奏的商业环境中&#xff0c;客户服务已成为企业竞争的核心要素之一。随着人工智能技术…...

FFmpeg 安装教程(Windows 系统)

1. 前言 FFmpeg 是一个用于处理视频、音频等多媒体文件的开源工具包。它支持几乎所有的多媒体格式转换、剪辑和编辑&#xff0c;是开发者和多媒体工作者必备的工具。本文详细讲解如何在 Windows 系统上安装 FFmpeg 并进行基本配置。 2. 下载 FFmpeg 安装包 打开 Dpwnload FFmp…...

左神算法基础巩固--1

文章目录 时间复杂度常数时间的操作时间复杂度的定义时间复杂度的作用剖析递归行为和递归行为时间复杂度的估算 排序选择排序冒泡排序插入排序归并排序小和问题问题描述解题思路 快速排序荷兰国旗问题问题描述 堆排序堆结构大根堆小根堆 桶排序 二分二分搜索 ^的运用不用额外空…...

基于鲲鹏服务器的打砖块小游戏部署

案例介绍 鲲鹏服务器是基于鲲鹏处理器的新一代数据中心服务器&#xff0c;适用于大数据、分布式存储、高性能计算和数据库等应用。鲲鹏服务器具有高性能、低功耗、灵活的扩展能力&#xff0c;适合大数据分析、软件定义存储、Web等应用场景。 本案例将指导开发者如何在鲲鹏服务…...

STM32F407寄存器点灯

背景描述&#xff1a; 最近用32开发遇到问题不得不看寄存器了&#xff0c;就回顾了一下寄存器手册的查看方式和寄存器的使用方法&#xff1b; 上一次这么细致的记录还是在刚学习STM32的时候&#xff0c;之前觉得看寄存器手册以及配置寄存器是有点难度的事情&#xff0c;现在回头…...

电子电气架构 --- 队列刷写场景及刷写上位机浅析

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所谓鸡汤,要么蛊惑你认命,要么怂恿你拼命,但都是回避问题的根源,以现象替代逻辑,以情绪代替思考,把消极接受现实的懦弱,伪装成乐观面对不幸的…...

kubernates实战

使用k8s来部署tomcat 1、创建一个部署&#xff0c;并指定镜像地址 kubectl create deployment tomcat6 --imagetomcat:6.0.53-jre82、查看部署pod状态 kubectl get pods # 获取default名称空间下的pods kubectl get pods --all-namespaces # 获取所有名称空间下的pods kubect…...

换工作,如何退出微软账户???(删除注册表数据)

1.Winr 进入 输入. 2.删除 注意路径. 3.删除 注意路径. 4.效果如下&#xff0c;清空成功...

vscode+编程AI配置、使用说明

文章目录 [toc]1、概述2、github copilot2.1 配置2.2 使用文档2.3 使用说明 3、文心快码&#xff08;Baidu Comate&#xff09;3.1 配置3.2 使用文档3.3 使用说明 4、豆包&#xff08;MarsCode&#xff09;4.1 配置4.2 使用文档4.3 使用说明 5、通义灵码&#xff08;TONGYI Lin…...

60.基于SSM的个人网站的设计与实现(项目 + 论文)

项目介绍 本站是一个B/S模式系统&#xff0c;个人网站是在MySQL中建立数据表保存信息&#xff0c;运用SSMVue框架和Java语言编写。并按照软件设计开发流程进行设计实现充分保证系统的稳定性。系统具有界面清晰、操作简单&#xff0c;功能齐全的特点&#xff0c;使得基于SSM的网…...

myexcel的使用

参考&#xff1a; &#xff08;1&#xff09;api文档&#xff1a;https://www.bookstack.cn/read/MyExcel-2.x/624d8ce73162300b.md &#xff08;2&#xff09;源代码&#xff1a; https://github.com/liaochong/myexcel/issues 我&#xff1a; &#xff08;1&#xff09;m…...

CSDN外链失效3:

参考我之前的博客&#xff1a; 外链失效博客1&#xff1a;随想笔记1&#xff1a;CSDN写博客经常崩溃&#xff0c;遇到外链图片转存失败怎么办_csdn外链图片转存失败-CSDN博客 外链失效博客2&#xff1a;网络随想2&#xff1a;转语雀_md格式转语雀lake格式-CSDN博客 markdown…...

SSM 医院预约挂号系统:Vue 技术驱动下的设计与实现飞跃

3系统分析 3.1可行性分析 通过对本医院预约挂号系统实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本医院预约挂号系统采用SSM框架&#xff0c;JAVA作为开发语…...

如何在centos系统上挂载U盘

在CentOS上挂载NTFS格式的U盘,需要执行一系列步骤,包括识别U盘设备、安装必要的软件、创建挂载点,并最终挂载U盘。以下是在CentOS上挂载NTFS格式U盘的详细步骤: 一、准备工作 确认CentOS版本: 确保你的CentOS系统已经安装并正常运行。不同版本的CentOS在命令和工具方面可能…...

lshw学习——简单介绍

文章目录 简介核心结构扫描设备原理scan_abiscan_burnerscan_cdromscan_cpufreqscan_cpuidscan_cpuinfoscan_device_treescan_diskscan_displayscan_dmiscan_fatscan_fbscan_graphicsscan_idescan_ideraidscan_inputscan_isapnpscan_lvmscan_memoryscan_mmcscan_mountsscan_net…...

UI自动化概念+Web自动化测试框架

1.UI自动化测试概念:我们先明确什么是UI UI&#xff0c;即(User Interface简称UI用户界面)是系统和用户之间进行交互和信息交换的媒介 UI自动化测试:Web自动化测试和移动自动化测试都属于UI自动化测试&#xff0c;UI自动化测试就是借助自动化工具对程序UI层进行自动化的测试 …...

java: 无效的目标发行版: xx

java: 无效的目标发行版: xx 背景java: 无效的目标发行版: xx 在 Intellij 的修复 背景 这里单独针对Intellij开发工具对 “java: 无效的目标发行版: xx”错误的修复。 java: 无效的目标发行版: xx 在 Intellij 的修复 同一台电脑使用多个JDK的时候容易出现在运行程序时容易…...

【QSS样式表 - ③】:QSS常用属性

文章目录 QSS常用属性字体样式QSS示例 边框样式QSS示例 盒子模型背景颜色、背景图片background-QSS示例 border-imageQSS示例1QSS示例2 QObject属性QSS示例 QSS常用属性 字体样式 以上也可以直接写成一行&#xff1a; font: 字体风格 字体粗细 字体大小 字体名称;QSS示例 新…...

WPF Binding 绑定

绑定是 wpf 开发中的精髓&#xff0c;有绑定才有所谓的数据驱动。 1 . 背景 目前 wpf 界面可视化的控件&#xff0c;继承关系如下&#xff0c; 控件的数据绑定&#xff0c;基本上都要借助于 FrameworkElement 的 DataContext 属性。 只有先设置了控件的 DataContext 属性&…...