Linux信号
目录
1. 信号的概念搞定(输出结论,支撑我们的理解)
补充知识
2.信号的产生
补充知识
3.信号的保存
4.阻塞信号
1. 信号其他相关常见概念
2. 在内核中的表示
3. sigset_t
4. 信号集操作函数
sigprocmask
sigpending
5. 信号的处理
1.什么时候被处理的
补充内容 重谈地址空间 3
6.信号捕捉
1. 内核如何实现信号的捕捉
2. sigaction
知识补充 可重入函数
知识补充 volatile
SIGCHLD信号
1. 信号的概念搞定(输出结论,支撑我们的理解)
我们日常生活中遇到的信号:信号弹 上下课铃声 红绿灯 闹钟等等
a.我们怎么认识这些信号? 有人教->然后我们记住
什么叫认识? 我们需要识别信号并且知道信号的处理办法
b.即使现在没有信号产生 我也知道信号产生之后我干什么
c.信号产生了 我们可能并不立即处理这个信号,而是在合适的时候处理。因为我们可能在做更加重要的事情
所以信号产生--------时间窗口------信号处理 (信号的处理方式1.默认动作2.忽略3.自定义动作 ,也被称为信号的捕捉)
所以在这个时间窗口之内,我们必须记住信号的到来
上面所有的我和我们,在Linux下就是进程,因此进程
1.进程必须可以 识别+处理 信号-------即使信号没有产生,也要具备处理信号的能力------信号的处理能力属于进程内置功能的一部分
2.进程即使是没有收到信号,也知道哪些信号该如何处理
3.当进程真的收到了一个具体信号的时候,进程可能并不会立即处理这个信号,而是在合适的时候处理
4.信号产生到信号开始处理会有时间窗口。进程具有临时保存哪些信号已经发生了的能力
ctrl + c 为什么能杀掉我们的前台进程呢?------>键盘输入首先是被前台进程收到的
Linux中,依次登陆中,一个终端,一般会配上一个bash,每一个登录只允许一个进程是前台进程,但是可以允许多个进程是后台进程
ctrl+c本质是被进程解释成为收到了2号信号
1-31属于普通信号
34-64属于实时信号需要立即处理,本文暂且不作讨论
下面进行一个实验
1.处理信号时,默认,忽略,自定义 这三种行为都是并列的,一次只执行一种
2.signal 的方法只需要设置一次,往后就一直有效。
但是是在条件发生的时候才会生效,即收到了对应信号时
补充知识
我们操作系统是如何知道硬件上有数据输入呢?并不是轮换地去遍历,而是通过硬件中断的机制来进行处理的。
例如键盘,如果键盘上有数据,那么键盘会发送一个中断信号(假设为10),这个信号是电信号,由中断单元发送,中断单元连接到cpu众多针脚中的一个,同时让cpu中的某个寄存器中存下10。在发送时,在硬件上信号由0(放电)1(充电)这样的充放电来控制,在软件上我们只需要通过对应的类型转换即可转换成数字。
操作系统中有一个中断向量表(一个数组),里面不同下标中存的就是访问不同硬件的内置访问方法。
我们的信号系统和这个没有关系,不过却是在软件层面对硬件中断的一种模仿
2.信号的产生
1.键盘组合键:
ctrl + c
ctrl + \
2.kill 命令
kill -signo pid
3.系统调用
kill,给任何进程发任何信号
raise 给本进程发任何信号
abort 给本进程发6号信号,发完后再退出
4. 异常(硬件层面异常)
a.除0错误
简单来说,出现除0错误时,cpu里面的状态寄存器中的溢出标志位会改变。
cpu出现问题了,那么操作系统作为硬件的管理者,也理应管理进行处理,操作系统会给对应进程发信号。是否停止发信号取决于状态寄存器,也即进程的上下文,若是进程并未退出,那么进程的上下文也不会切换走,此时操作系统就会不断地向进程发信号。
这种异常虽然是在cpu中,但是其实只影响一个进程。如果某个问题进程被切换掉了,那么它的上下文不管是否出现异常,这个上下文也会被切换。
b.段错误
其实也类似,即虚拟到物理内存转化失败。cpu中也有对应的寄存器存储
实际上,MMU是集成在cpu中的,页表中的地址也是存在cpu中的,转化失败的地址也会存储在cpu中。
每种异常的默认处理方式都是退出。 异常的处理涉及得更多,其中也会包含信号的处理。
其实,操作系统让我们捕捉信号并不是让我们进行操作去解决这些异常,而是让我们异常出现得更明白,像我们可以保存日志再退出,等等。
我们在各种语言比如c++c语言,语言中也有自己的异常的概念,上层是怎么识别对应异常的呢?这时候我们就应该知道是底层的信号起了作用,不同的信号代表了不同的异常。
5.软件条件
异常只会由硬件产生吗?并不是
例如我们之前 学习到的管道,如果我们写端一直再写,而读端则被关闭。那么写端也会被直接关闭,并且操作系统会给进程发一个13号的SIGPIPE的信号
不过操作系统对于一些问题的处理也有区别,比如下面这种
(这里也可以是写)这里并不会直接报错,出现异常,而是以返回值的形式来告诉我们。
软件上不仅仅会出异常,也可以出一些特殊事件,比如:闹钟(不过闹钟也有他的类别,这里我们只介绍普通闹钟)
闹钟就是一段时间后向进程发一个信号,返回值是闹钟响的时候距离预定时间的相隔秒数,例如我设置闹钟5秒后响,但是闹钟第三秒就响了,那么返回值就是2.
下面是利用闹钟每隔五秒进行一个打印,闹钟设置后会直接返回,因此会不断执行while里面的代码
补充知识
core dump
在我们之前的学习中,我们知道进程有正常终止和被信号所杀两种,其中我们没讲到的是,如果进程被信号所杀,退出码中会有一位作为core dump标志。
不过默认云服务器中的core dump功能是被关闭的,这个稍后再讲。
我们可以如上方式提取。
正常状态下core dump功能被关闭,如下。
不过我们可以打开 (同时编译时要-g,debug模式)
打开之后我们进行实验
我们发现,在我们打开core dump功能之后,一旦进程出现异常,操作系统会将进程在内存中的运行信息给我们转存到进程当前目录(磁盘),形成core.pid文件。
我们要查看,进到gdb调试里面之后再输入相关内容即可。会直接复现问题之后直接定位到出错行,先运行,再core dump,事后调试
但是我们会发现core.pid文件的大小还是挺大的,由于大多数时候我们服务挂了要立刻重启,(后面才是基于日志等进行修正),若是某个服务出现了问题,一重启就立刻挂了,那么就会不断形成core.pid文件,对操作系统产生危害。
3.信号的保存
a.什么是信号的发送
比特位的内容是0还是1表明是否收到
比特位的位置 标识信号的编号
所谓的发信号,本质是操作系统去修改task_struct 的信号位图对应的比特位。
操作系统是进程的管理者,只有它才有资格修改task_struct的内部属性!
b为什么要保存信号
进程收到信号之后,可能不会立即处理这个信号。信号不会被处理,就会有一个时间窗口
4.阻塞信号
1. 信号其他相关常见概念
1.实际执行信号的处理动作称为信号递达(Delivery)
2.信号从产生到递达之间的状态,称为信号未决(Pending)。
3.进程可以选择阻塞 (Block )某个信号。
4.被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作.
5.注意,阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。
2. 在内核中的表示
信号在内核中的表示示意图
1. 每个信号都有两个标志位分别表示阻塞(block)和未决(pending),还有一个函数指针表示处理动作。信号产生时,内核在进程控制块中设置该信号的未决标志,直到信号递达才清除该标志。在上图的例子中,SIGHUP信号未阻塞也未产生过,当它递达时执行默认处理动作。
2.SIGINT信号产生过,但正在被阻塞,所以暂时不能递达。虽然它的处理动作是忽略,但在没有解除阻塞之前不能忽略这个信号,因为进程仍有机会改变处理动作之后再解除阻塞。
3.SIGQUIT信号未产生过,一旦产生SIGQUIT信号将被阻塞,它的处理动作是用户自定义函数sighandler。如果在进程解除对某信号的阻塞之前这种信号产生过多次,将如何处理?POSIX.1允许系统递送该信号一次或多次。Linux是这样实现的:常规信号在递达之前产生多次只计一次,而实时信号在递达之前产生多次可以依次放在一个队列里。本章不讨论实时信号。
3. sigset_t
从上图来看,每个信号只有一个bit的未决标志,非0即1,不记录该信号产生了多少次,阻塞标志也是这样表示的。
因此,未决和阻塞标志可以用相同的数据类型sigset_t来存储,sigset_t称为信号集,这个类型可以表示每个信号的“有效”或“无效”状态,在阻塞信号集中“有效”和“无效”的含义是该信号是否被阻塞,而在未决信号集中“有效”和“无效”的含义是该信号是否处于未决状态。
下一节将详细介绍信号集的各种操作。 阻塞信号集也叫做当前进程的信号屏蔽字(Signal Mask),这里的“屏蔽”应该理解为阻塞而不是忽略。
sigset_t 定义的类型在外部可以视为一个位图,我们不需要关心它的内部是怎么样的,但是我们必须通过系统调用接口来进行操作,见4
4. 信号集操作函数
sigset_t类型对于每种信号用一个bit表示“有效”或“无效”状态,至于这个类型内部如何存储这些bit则依赖于系统实现,从使用者的角度是不必关心的,使用者只能调用以下函数来操作sigset_ t变量,而不应该对它的内部数据做任何解释,比如用printf直接打印sigset_t变量是没有意义的
#include <signal.h>
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);
函数sigemptyset初始化set所指向的信号集,使其中所有信号的对应bit清零,表示该信号集不包含 任何有效信号。
函数sigfillset初始化set所指向的信号集,使其中所有信号的对应bit置位,表示 该信号集的有效信号包括系统支持的所有信号。
注意,在使用sigset_ t类型的变量之前,一定要调 用sigemptyset或sigfillset做初始化,使信号集处于确定的状态。初始化sigset_t变量之后就可以在调用sigaddset和sigdelset在该信号集中添加或删除某种有效信号。
这四个函数都是成功返回0,出错返回-1。
sigismember是一个布尔函数,用于判断一个信号集的有效信号中是否包含某种 信号,若包含则返回1,不包含则返回0,出错返回-1。
sigprocmask
调用函数sigprocmask可以读取或更改进程的信号屏蔽字(阻塞信号集)。
#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oset);
返回值:若成功则为0,若出错则为-1
如果oset是非空指针,则读取进程的当前信号屏蔽字通过oset参数传出。如果set是非空指针,则 更改进程的信号屏蔽字,参数how指示如何更改。
如果oset和set都是非空指针,则先将原来的信号 屏蔽字备份到oset里,然后根据set和how参数更改信号屏蔽字。假设当前的信号屏蔽字为mask,下表说明了how参数的可选值。
如果调用sigprocmask解除了对当前若干个未决信号的阻塞,则在sigprocmask返回前,至少将其中一个信号递达。
sigpending
#include <signal.h>
sigpending()
读取当前进程的未决信号集,通过set参数传出。调用成功则返回0,出错则返回-1。 下面用刚学的几个函数做个实验。程序如下:
里面的set参数是一个输出型参数
程序运行时,每秒钟把各信号的未决状态打印一遍,由于我们阻塞了SIGINT信号,按Ctrl-C将会 使SIGINT信号处于未决状态,
按Ctrl-\仍然可以终止程序,因为SIGQUIT信号没有阻塞。
5. 信号的处理
1.什么时候被处理的
当我们的进程从内核态返回到用户态的时候,进行信号的检测和处理。
调用系统调用时------操作系统是自动会做“身份”切换的,用户身份变成内核身份。或者反着来
int 80 就是一个从用户态陷入内核态的汇编语句
内核态:允许访问操作系统的代码和数据
用户态:只能访问用户自己的代码和数据
以下这张图可以简要介绍
当进行系统调用的时候进入内核态
进入内核态后先调用方法处理,然后进行信号的处理,如果是默认或者忽略,那么直接返回用户态,回到主函数中相应位置。
如果用户捕捉,那么虽然同样需要返回用户态,但是需要进入用户写的信号处理函数。
(关于为什么要返回用户态再执行信号处理函数,那是因为操作系统不相信用户,因此也不愿意执行用户写的代码)
信号处理函数返回时先要重新进入内核态,因为只有操作系统知道我们上回处理的代码是在主函数的哪个部分。
(系统调用并不只我们代码中主动调用的,像进程通过时间片不断轮换调度,切换等等操作都是需要进行系统调用的,那么进入内核态的机会就有很多)
补充内容 重谈地址空间 3
内核空间也有自己的内核级页表
对于用户页表,有几个进程就有几份用户级页表 -----因为进程具有独立性
对于内核页表,它只有一份
因此每一个进程看到的3-4GB的东西都是一样的,整个系统中,进程再怎么切换,3-4GB的空间的内容是不变的(里面是一些系统调用等等)
进程视角:我们调用系统中的方法,就是再我自己的地址空间中进行执行的
操作系统视角:因为任何一个时候都有进程执行,因为每个进程看到的内核空间都是一样的,那么只要我想执行操作系统的代码,就可以随时去执行
操作系统的本质: 基于时钟中断的一个死循环
计算机硬件中,有一个时钟芯片,每隔一个很短的时间向计算机发送时钟中断,然后操作系统收到中断后就去调度进程。这种模式可以理解成抽陀螺,抽一鞭子转一下。
内核态和用户态的切换还与cpu有关,cpu中有一个ecs寄存器,里面的低两位用于表明内核态和用户态用户态为11,内核态为00.
6.信号捕捉
1. 内核如何实现信号的捕捉
如果信号的处理动作是用户自定义函数,在信号递达时就调用这个函数,这称为捕捉信号。由于信号处理函数的代码是在用户空间的,处理过程比较复杂,举例如下: 用户程序注册了SIGQUIT信号的处理函数sighandler。 当前正在执行main函数,这时发生中断或异常切换到内核态。 在中断处理完毕后要返回用户态的main函数之前检查到有信号SIGQUIT递达。 内核决定返回用户态后不是恢复main函数的上下文继续执行,而是执行sighandler函 数,sighandler和main函数使用不同的堆栈空间,它们之间不存在调用和被调用的关系,是 两个独立的控制流程。 sighandler函数返
回后自动执行特殊的系统调用sigreturn再次进入内核态。 如果没有新的信号要递达,这次再返回用户态就是恢复main函数的上下文继续执行了。
2. sigaction
#include <signal.h>
int sigaction(int signo, const struct sigaction *act, struct sigaction *oact);
sigaction函数可以读取和修改与指定信号相关联的处理动作 。调用成功则返回0, 出错则返回 - 1。signo是指定信号的编号。若act指针非空,则根据act修改该信号的处理动作。若oact指针非 空,则通过oact传出该信号原来的处理动作。act和oact指向sigaction结构体
我们看一下这个 struct sigaction 结构体,里面另外三个成员我们先不看,只看第一个和第三个。第一个成员是一个函数指针,指向信号的捕捉方法。
将sa_handler赋值为常数SIG_IGN传给sigaction 表示忽略信号,赋值为常数SIG_DFL表示执行系统默认动作,赋值为一个函数指针表示用自定义函数捕捉信号,或者说向内核注册了一个信号处理函 数,该函数返回值为void,可以带一个int参数,通过参数可以得知当前信号的编号,这样就可以用同一个函数处理多种信号。显然,这也是一个回调函数,不是被main函数调用,而是被系统所调用。
当某个信号的处理函数被调用时,内核自动将当前信号加入进程的信号屏蔽字,当信号处理函数返回时自动恢复原来的信号屏蔽字,这样就保证了在处理某个信号时,如果这种信号再次产生,那么 它会被阻塞到当前处理结束为止。 如果在调用信号处理函数时,除了当前信号被自动屏蔽之外,还希望自动屏蔽另外一些信号,则用sa_mask字段说明这些需要额外屏蔽的信号,当信号处理函数返回时自动恢复原来的信号屏蔽字。 sa_flags字段包含一些选项,本章的代码都把sa_flags设为0,sa_sigaction是实时信号的处理函数。
我们的pending位图里面的值 从1->0 是在调用捕捉方法之前。
下面是一点代码示例
知识补充 可重入函数
main函数调用insert函数向一个链表head中插入节点node1,插入操作分为两步,刚做完第一步的 时候,因为硬件中断使进程切换到内核,再次回用户态之前检查到有信号待处理,于是切换 到sighandler函数,sighandler也调用insert函数向同一个链表head中插入节点node2,插入操作的 两步都做完之后从sighandler返回内核态,再次回到用户态就从main函数调用的insert函数中继续 往下执行,先前做第一步之后被打断,现在继续做完第二步。结果是,main函数和sighandler先后 向链表中插入两个节点,而最后只有一个节点真正插入链表中了。
像上例这样,insert函数被不同的控制流程调用,有可能在第一次调用还没返回时就再次进入该函数,这称为重入,insert函数访问一个全局链表,有可能因为重入而造成错乱,像这样的函数称为 不可重入函数,反之,如果一个函数只访问自己的局部变量或参数,则称为可重入(Reentrant) 函数。
如果一个函数符合以下条件之一则是不可重入的:
调用了malloc或free,因为malloc也是用全局链表来管理堆的。
调用了标准I/O库函数。标准I/O库的很多实现都以不可重入的方式使用全局数据结构。
知识补充 volatile
gcc 编译有自己的优化程度, -O1 到 -O3是从低到高的三种优化程度
-O0是不进行优化(gcc/g++默认不优化)
我们如图书写一段代码进行测试
在不进行优化的时候,我们ctrl+c可以使程序正常结束,但是如果进行了高等级的优化那么ctrl+c就无法使程序跳出while循环。
具体原因如下
我们进行了优化之后,内存仍然会开辟,但是编译器发现我们在main函数中并没有对flag进行修改(handler是另一个执行流),因此将flag的值放到寄存器之后,每次判断都从cpu中拿,不往内存里拿(这样子执行速度会更快,因此起到优化作用),因此即使我们ctrl + c后修改了全局中flag的值,在内存中改变了flag的值,但是并没有影响到cpu中的flag的值。这种情况称为内存不可见。
我们只需要在flag前添加volatile关键字即可
volatile关键字可以防止编译器过度优化,保持内存的可见性。
我们还可以联想到register关键字,这是一个可视化优化,表示变量如果能放到寄存器里就放到寄存器里(即把变量的内容放在寄存器里,但是仍然是需要开辟内存的)
SIGCHLD信号
进程一章讲过用wait和waitpid函数清理僵尸进程,父进程可以阻塞等待子进程结束,也可以非阻 塞地查询是否有子进程结束等待清理(也就是轮询的方式)。采用第一种方式,父进程阻塞了就不 能处理自己的工作了;采用第二种方式,父进程在处理自己的工作的同时还要记得时不时地轮询一 下,程序实现复杂。
其实,子进程在终止时会给父进程发SIGCHLD信号,该信号的默认处理动作是忽略,(即默认,忽略,捕捉,三种方式中的默认,但是处理的具体方法是忽略)父进程可以自 定义SIGCHLD信号的处理函数,这样父进程只需专心处理自己的工作,不必关心子进程了,子进程 终止时会通知父进程,父进程在信号处理函数中调用wait清理子进程即可。如果有很多个子进程一起退那么就采用while循环一直wait,如果一次只退出一半出现阻塞,那么就更改waitpid的第三个参数,把它改成WNOHANG非阻塞。
事实上,由于UNIX 的历史原因,要想不产生僵尸进程还有另外一种办法:父进程调 用sigaction将SIGCHLD的处理动作置为SIG_IGN,(即默认,忽略,捕捉中的忽略)这样fork出来的子进程在终止时会自动清理掉,不 会产生僵尸进程,也不会通知父进程。系统默认的忽略动作和用户用sigaction函数自定义的忽略 通常是没有区别的,但这是一个特例。此方法对于Linux可用,但不保证在其它UNIX系统上都可 用。请编写程序验证这样做不会产生僵尸进程。
相关文章:
Linux信号
目录 1. 信号的概念搞定(输出结论,支撑我们的理解) 补充知识 2.信号的产生 补充知识 3.信号的保存 4.阻塞信号 1. 信号其他相关常见概念 2. 在内核中的表示 3. sigset_t 4. 信号集操作函数 sigprocmask sigpending 5. 信号的…...
git,bash - 从一个远端git库只下载一个文件的方法
文章目录 git,bash - 从一个远端git库只下载一个文件的方法概述笔记写一个bash脚本来自动下载get_github_raw_file_from_url.shreanme_file.shfind_key_value.sh执行命令 END git,bash - 从一个远端git库只下载一个文件的方法 概述 github上有很多大佬上传了电子书库…...
深度学习(5)-卷积神经网络
我们将深入理解卷积神经网络的原理,以及它为什么在计算机视觉任务上如此成功。我们先来看一个简单的卷积神经网络示例,它用干对 MNIST数字进行分类。这个任务在第2章用密集连接网络做过,当时的测试精度约为 97.8%。虽然这个卷积神经网络很简单…...
flex布局自定义一行几栏,靠左对齐===grid布局
模板 <div class"content"><div class"item">1222</div><div class"item">1222</div><div class"item">1222</div><div class"item">1222</div><div class"…...
(五)趣学设计模式 之 建造者模式!
目录 一、 啥是建造者模式?二、 为什么要用建造者模式?三、 建造者模式怎么实现?四、 建造者模式的应用场景五、 建造者模式的优点和缺点六、 总结 🌟我的其他文章也讲解的比较有趣😁,如果喜欢博主的讲解方…...
【CentOS7】安装MinIO
下载rpm包 wget https://dl.min.io/server/minio/release/linux-amd64/archive/minio-20230809233022.0.0.x86_64.rpm 安装 rpm -ivh minio-20230809233022.0.0.x86_64.rpm 运行 server 后面跟着的使minio 的数据目录;console-address 后面跟着的是minio 的管理…...
vLLM学习1
调用方式 一、vLLM 提供的两种调用方式 1. Offline Batched Inference(离线批处理) 调用特点:一次性传入一批(batch)的请求,等待所有请求都处理完毕后,一次性返回推理结果。对用户而言&#x…...
ABC 385
目录 C. Illuminate Buildings D. Santa Claus E. Snowflake Tree C. Illuminate Buildings dp[ i ][ j ]:选择的 i 个建筑,间隔为 j。这样只需要两层循环就可以了,o(n^2) 其实本质只是个一维 dp,但我还需…...
綫性與非綫性泛函分析與應用_1.例題(下)-半母本
第1章 實分析與函數論:快速回顧(下) 五、基數;有限集和無限集相關例題 例題1:集合基數的判斷 判斷集合和集合B=\{a,b,c,d,e\}的基數關係。 解析: 可以構造一個雙射,例如,,,,。 所以,兩個集合具有相同的基數。 例題2:可數集的證明 證明整數集是可數集。 解析: …...
49 set与map的模拟实现
目录 一、源码及框架分析 二、模拟实现map和set (一)复用红黑树的框架,并支持insert (二)支持迭代器的实现 (三)map支持 [ ] (四)整体代码实现 一、源码及框架分析…...
鸿蒙NEXT应用App测试-通用测试
注意:大家记得学完通用测试记得再学鸿蒙专项测试 https://blog.csdn.net/weixin_51166786/article/details/145768653 注意:博主有个鸿蒙专栏,里面从上到下有关于鸿蒙next的教学文档,大家感兴趣可以学习下 如果大家觉得博主文章…...
LangChain 技术入门指南:探索语言模型的无限可能
在当今的技术领域,LangChain 正逐渐崭露头角,成为开发语言模型应用的强大工具。如果你渴望深入了解并掌握这一技术,那么就跟随本文一起开启 LangChain 的入门之旅吧! (后续将持续输出关于LangChain的技术文章,有兴趣的同学可以关注…...
UE5销毁Actor,移动Actor,简单的空气墙的制作
1.销毁Actor 1.Actor中存在Destory()函数和Destoryed()函数 Destory()函数是成员函数,它会立即标记 Actor 为销毁状态,并且会从场景中移除该 Actor。它会触发生命周期中的销毁过程,调用 Destroy() 后,Actor 立即进入销毁过程。具体…...
STM32基础篇(二)------GPIO
GPIO简介 GPIO(General Purpose Input Output)通用输入输出口 可配置为8种输入输出模式 引脚电平:0V~3.3V,部分引脚可容忍5V 输出模式下可控制端口输出高低电平,用以驱动LED、控制蜂鸣器、模拟通信协议输出时序等 输入…...
亲测Win11电脑可以安装LabVIEW的版本,及2015、2018、2020版本直接的区别
下面是我电脑的信息 设备名称 DESKTOP-04HHS8S 处理器 13th Gen Intel(R) Core(TM) i5-13500H 2.60 GHz 机带 RAM 16.0 GB (15.7 GB 可用) 设备 ID 82798104-C565-4167-A21E-5EB5DEFAA541 产品 ID 00331-20300-00000-AA678 系统类型 64 位操作系统, 基于 …...
Idea2024中搭建JavaFX开发环境并创建运行项目
Idea2024中搭建JavaFX开发环境并创建运行项目 本文以Java语言为例演示如何创建JavaFX开发项目和部署开发环境,读者可以根据个人实际灵活选择相关参数。 一、项目创建与环境搭建步骤 新建JavaFX项目,选择适合项目实际的语言、系统和JDK。 项目设置-设置…...
认知重构 | 自我分化 | 苏格拉底式提问
注:本文为 “认知重构 | 自我分化” 相关文章合辑。 心理学上有一个词叫:认知重构(改变 “非黑即白,一分为二” 的思维方式) 原创 心理师威叔 心理自救 2024 年 10 月 26 日 19:08 广东 你有没有过这样的时候&#x…...
MFC开发:如何创建第一个MFC应用程序
文章目录 一、概述二、MFC 的主要组件三、创建一个MFC窗口四、控件绑定消息函数 一、概述 MFC 是微软提供的一个 C 类库,用于简化 Windows 应用程序的开发。它封装了 Windows API,提供面向对象的接口,帮助开发者更高效地创建图形用户界面&am…...
nodejs:vue 3 + vite 作为前端,将 html 填入<iframe>,在线查询英汉词典
向 doubao.com/chat/ 提问: node.js js-mdict 作为后端,vue 3 vite 作为前端,编写在线查询英汉词典 后端部分(express js-mdict ) 详见上一篇:nodejs:express js-mdict 作为后端ÿ…...
基于 Python Django 的校园互助平台(附源码,文档)
博主介绍:✌Java徐师兄、7年大厂程序员经历。全网粉丝13w、csdn博客专家、掘金/华为云等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇🏻 不…...
玩转 Java 与 Python 交互,JEP 库来助力
文章目录 玩转 Java 与 Python 交互,JEP 库来助力一、背景介绍二、JEP 库是什么?三、如何安装 JEP 库?四、JEP 库的简单使用方法五、JEP 库的实际应用场景场景 1:数据处理场景 2:机器学习场景 3:科学计算场…...
【Linux】基于UDP/TCP服务器与客户端的实现
目录 一、UDP (一)Server.hpp (二)Server.cpp (三)Client.hpp (四)Client.cpp (五)User.hpp 二、TCP (一)多进程版本的服务器与…...
Unity for Python —— 强大的 Python 脚本支持提升 Unity 编辑器效率
内容将会持续更新,有错误的地方欢迎指正,谢谢! Unity for Python —— 强大的 Python 脚本支持提升 Unity 编辑器效率 TechX 坚持将创新的科技带给世界! 拥有更好的学习体验 —— 不断努力,不断进步,不断探索 Tec…...
【Dubbo+Zookeeper】——SpringBoot+Dubbo+Zookeeper知识整合
🎼个人主页:【Y小夜】 😎作者简介:一位双非学校的大二学生,编程爱好者, 专注于基础和实战分享,欢迎私信咨询! 🎆入门专栏:🎇【MySQL࿰…...
家用路由器的WAN口和LAN口有什么区别
今时今日,移动终端盛行的时代,WIFI可以说是家家户户都有使用到的网络接入方式。那么路由器当然也就是家家户户都不可或缺的设备了。而路由器上的两个实现网络连接的基础接口 ——WAN 口和 LAN 口,到底有什么区别?它们的功能和作用…...
Python--函数入门
1. 函数基础概念 1.1 什么是函数 定义:函数是一段可重复调用的代码块,用于封装特定功能。 核心作用: 代码重用:减少重复代码的编写。增强可读性:通过命名和模块化让代码逻辑更清晰。 1.2 函数的定义与调用 def 函…...
EasyRTC低延迟通信与智能处理:论嵌入式WebRTC与AI大模型的技术融合
在当今数字化时代,实时通信的需求日益增长,视频通话作为一种高效、直观的沟通方式,广泛应用于各个领域。WebRTC技术的出现,为实现浏览器之间的实时音视频通信提供了便捷的解决方案。而基于WebRTC技术的EasyRTC视频通话SDK…...
《操作系统 - 清华大学》 8 -6:进程管理:进程状态变化模型
进程状态及其转换全解析 在操作系统中,进程有着特定的生命周期和多种状态变化。不考虑进程结束时,进程主要有三个基本状态。 运行态:即进程正在占用CPU执行任务。总结:运行态表示进程当前正在使用CPU。就绪状态:进程…...
大语言模型中的 Token如何理解?
在大语言模型中,Token 是文本处理的基本单元,类似于“文字块”,模型通过将文本分割成Token来理解和生成内容。举一个形象一点的例子,可以理解为 AI 处理文字时的“最小积木块”。就像搭乐高时,每块积木是基础单位一样&…...
信息学奥赛一本通 1522:网络 | OpenJudge 百练 1144:Network
【题目链接】 ybt 1522:网络 OpenJudge 百练 1144:Network 【题目考点】 1. 图论:割点 【解题思路】 每个交换机是一个顶点,如果两地点之间有电话线连接,那么两顶点之间有一条无向边,该图是无向图。 初始时任何地…...
3分钟快速本地部署deepseek
DeepSeek简介 DeepSeek 是杭州深度求索人工智能基础技术研究有限公司开发的一系列大语言模型,背后是知名量化资管巨头幻方量化3。它专注于开发先进的大语言模型和相关技术,拥有多个版本的模型,如 DeepSeek-LLM、DeepSeek-V2、DeepSeek-V3 等…...
Linux系统管理与编程01:准备工作
0 准备工作 0.1 安装VMWare Workstation pro17 到百度搜一下,到处都是。安装好VMWare Workstation pro17(以下简称VW)。 图0- 1 安装过程略。 0.2下载CentOS7.6 图0- 2 选择minimal版本。 0.3下载yum库文件 下载阿里云yum库文件https:…...
常用的几种编码方式
常见的编码方式有多种,每种编码方式都有其特定的用途和特点。以下是几种常见的编码方式: ASCII(美国信息交换标准代码) 用途:主要用于表示英文字符及控制字符。特点:使用7位二进制数表示字符,能…...
WebXR教学 03 项目1 旋转彩色方块
一、项目结构 webgl-cube/ ├── index.html ├── main.js ├── package.json └── vite.config.js二、详细实现步骤 初始化项目 npm init -y npm install three vite --save-devindex.html <!DOCTYPE html> <html lang"en"> <head><…...
从零开始的网站搭建(以照片/文本/视频信息通信网站为例)
本文面向已经有一些编程基础(会至少一门编程语言,比如python),但是没有搭建过web应用的人群,会写得尽量细致。重点介绍流程和部署云端的步骤,具体javascript代码怎么写之类的,这里不会涉及。 搭…...
netcore 启用gzip压缩及缓存
public void ConfigureServices(IServiceCollection services) {....// 配置gzip 与 br的压缩等级为最优services.Configure<BrotliCompressionProviderOptions>(options > {options.Level CompressionLevel.Optimal;});services.Configure<GzipCompressionProvid…...
c++入门-------命名空间、缺省参数、函数重载
C系列 文章目录 C系列前言一、命名空间二、缺省参数2.1、缺省参数概念2.2、 缺省参数分类2.2.1、全缺省参数2.2.2、半缺省参数 2.3、缺省参数的特点 三、函数重载3.1、函数重载概念3.2、构成函数重载的条件3.2.1、参数类型不同3.2.2、参数个数不同3.2.3、参数类型顺序不同 前言…...
elf_loader:一个使用Rust编写的ELF加载器
本文介绍一个使用Rust实现的ELF加载器。 下面是elf_loader的仓库链接: github: https://github.com/weizhiao/elf_loaderhttps://github.com/weizhiao/elf_loader crates.io: https://crates.io/crates/elf_loaderhttps://crates.io/cra…...
postman调用ollama的api
按照如下设置,不需要设置key 保持长会话的方法 # 首次请求 curl http://localhost:11434/api/generate -d {"model": "deepseek-r1:32b","prompt": "请永久记住:110,1-12,之后所有数学计算必…...
鸿蒙5.0实战案例:基于ArkUI的验证码实现
往期推文全新看点(文中附带全新鸿蒙5.0全栈学习笔录) ✏️ 鸿蒙(HarmonyOS)北向开发知识点记录~ ✏️ 鸿蒙(OpenHarmony)南向开发保姆级知识点汇总~ ✏️ 鸿蒙应用开发与鸿蒙系统开发哪个更有前景&#…...
通俗理解什么是云原生?
by deepseek。 一、核心理念:云原生到底是什么? 1. 一句话定义 云原生(Cloud Native) 是一种构建和运行应用程序的方法论,它利用云计算的优势(弹性、分布式、自动化),让软件从设计…...
基于PSO粒子群优化的BiLSTM双向长短期记忆网络序列预测算法matlab仿真,对比BiLSTM和LSTM
目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 2.算法运行软件版本 matlab2022a/matlab2024b 3.部分核心程序 (完整版代码包含详细中文注释和操作步骤视频…...
什么是完全前向保密(PFS)?
在当今数字化时代,信息安全至关重要。而密码学中的完全前向保密(Perfect Forward Secrecy,简称PFS)技术,已经成为保障信息安全的关键一环。如果没有完全前向保密,一旦长期密钥被泄露,攻击者就可…...
Oracle备库srvctl start丢失某个原有的service_names的案例
最近在测试主备环境中使用srvctl添加新的service之后,srvctl start发现其中一个原本用于主备同步的service丢失了。 原始的参数文件中的service_names参数值如下(数据库中service_names的值也一样,省略查看步骤): [oraclesmartdbstb01 202502…...
重学SpringBoot3-怎样优雅停机
更多SpringBoot3内容请关注我的专栏:《SpringBoot3》 期待您的点赞??收藏评论 重学SpringBoot3-怎样优雅停机 1. 什么是优雅停机?2. Spring Boot 3 优雅停机的配置3. Tomcat 和 Reactor Netty 的优雅停机机制 3.1 Tomcat 优雅停机3.2 Reactor Netty 优…...
SkyWalking集成Kafka实现日志异步采集经验总结
SkyWalking日志异步采集架构 【重点知识】 1、【Agent】kafka-reporter-plugin-x.x.x.jar包放plugins目录后必走kafka(kafka没有正确配置就会报错) 2、【Agent】异步如不开启数据压缩,日志数据较大,pod多、业务大时容易造成网络…...
图论 之 BFS
文章目录 3243.新增道路查询后的最短距离1311.获取你好友已观看的视频 BFS:广度优先搜索(BFS) 是一种常用的算法,通常用于解决图或树的遍历问题,尤其是寻找最短路径或层级遍历的场景。BFS 的核心思想是使用队列(FIFO 数…...
rust学习笔记5-所有权机制
rust核心就是所有权机制,是其内存管理的核心特性,旨在消除内存安全问题(如空指针、悬垂指针、内存泄漏等)而无需依赖垃圾回收(GC) 1.首先看一下语义模型 当声明一个变量 let a "32";它的语义模…...
网站快速收录:如何优化网站404页面?
优化网站404页面是提升用户体验和SEO效果的重要一环。以下是一些优化404页面的建议: 一、设计友好的404页面 简洁明了的提示信息:使用清晰的语言告诉用户该页面不存在或已被删除,避免使用过于技术化的术语。 提供导航链接:在40…...
关于order by的sql注入实验
实验描述 本实验基于sqli-lab的第46关进行测试 本关的sql 语句为$sql "SELECT * FROM users ORDER BY $id" 利用sort进行sql注入,我们可以利用报错注入,延时注入来爆出数据 1.报错注入 1.手工测试 爆出数据库 ?sort(extractvalue(1, c…...