Linux 进程信号篇

news2024/7/2 21:32:01

文章目录

  • 1. 生活中的信号
  • 2. 信号的概念
  • 3. 信号的产生
    • 3.1 系统调用
    • 3.2 软件条件
    • 3.2 异常
    • 3.3 `Core`和`Term`的区别
  • 4. 信号的保存
  • 5. 信号的处理
    • 5.1 地址空间的进一步理解
    • 5.2 键盘输入数据的过程
    • 5.3 理解OS如何正常运行
      • 5.3.1 OS如何运行
      • 5.3.2 如何理解系统调用
    • 5.4 内核态和用户态
  • 6. 可重入函数
  • 7. volatile关键字
  • 8. `SIGCHLD`信号

在这里插入图片描述

1. 生活中的信号


日常生活中,等红绿灯、上课铃响…其实都是在给我们发送信号,绿灯亮了给我们发送可以通行的信号,我们才能通行;红灯亮了,给我们发送禁止通行的信号,我们就要停下来。而有时会有特殊情况,临近吃中饭,你正在做作业,爸妈喊了你一声,你就知道要去吃饭了,但手里头就差一点作业就完成了,于是你暂时不管爸妈叫你吃中饭的信号,完成手里的作业再去吃中饭

我们对上述信号粗犷的理解:

  1. 信号可以随时产生
  2. 我们认识信号
  3. 我们知道信号的处理方式
  4. 我们可能正在处理要紧的事情,把到来的信号暂不处理

2. 信号的概念


信号是Linux系统提供的一种向进程发送特定事件的方式,需要进程识别和处理

Linux系统中,总共有64个信号,其中34~64称为实时信号,不作为本篇文章的重点

在这里插入图片描述

根据信号的定义,进程需要对信号进行处理,进程处理信号有三种方式:

  1. 默认动作
  2. 忽略动作
  3. 自定义捕捉

对于默认动作,让进程根据OS规定好的处理方式去处理,通常是终止进程,也有忽略信号的

其中终止进程有两种行为,CoreTerm,现在我们就认为它们都是终止进程,后面会将它们区分

在这里插入图片描述

忽略动作就是不管信号,很简单

自定义捕捉:我们自己设计好对应信号的处理方式(参数为int,返回值为void的函数),使用signal捕捉信号,当进程收到指定的信号时,会去调用我们自定义的方法

在这里插入图片描述

我们拿2号信号举例,它的默认动作是终止进程,相当于键盘上的ctrl+c

在这里插入图片描述

3. 信号的产生


信号的产生总共有5种方式

  1. 使用kill命令向指定进程发送信号
  2. 键盘输入,比如ctrl+\,相当于3号信号
  3. 系统调用
  4. 软件条件
  5. 异常

3.1 系统调用

这里介绍几个系统调用函数

kill是命令,同时也是一个函数,可以向指定进程发送指定信号

raise函数向自身进程发送指定信号

abort函数向自身进程发送6号信号

在这里插入图片描述

可以看到,abort函数向自身发送了6号信号的同时,还强制终止了当前进程

注:既然我们可以使用signal函数捕捉信号,能不能把所有信号都捕捉了?

如果把所有信号都捕捉了,会导致什么结果?可能会发生进程永远无法退出的情况,OS考虑到了这点;经过测试,我们发现9号信号(SIGKILL)和19号信号(SIGSTOP)无法被捕捉

在这里插入图片描述

3.2 软件条件

在进程间通信篇中,我们谈管道的4种情况时说到,当管道的读端关闭了,写端还在继续写,OS就会认为写的数据没意义,直接终止进程;这其实是OS向进程发送了13号信号(SIGPIPE)

在这里插入图片描述

针对软件条件,再介绍一个函数:alarm,可以把它理解为一个闹钟,设定好时间,它就会在未来向进程发送14号信号(SIGALRM)

在这里插入图片描述

借助alarm函数,我们进一步理解I/O很慢这个的观点,之前我们总说输入输出是很费时的做法,那到底有多费时,通过比较下面的两份代码,就知道有输入输出和没输入输出,它们的效率相差之大了

在这里插入图片描述

对于alarm函数,它是进程设置的闹钟,而进程在OS中是有多个的,也就意味着闹钟在OS中也有多个;哪个闹钟属于哪个进程,OS需要将它们管理好;因此,闹钟在OS中也有自己的结构体,并以小根堆的结构组织起来

一个进程只能设定一个闹钟;alarm函数的返回值表示上一个闹钟还剩多少时间;alarm(0)表示取消闹钟

在这里插入图片描述

3.2 异常

进程异常我们在进程等待时提到过,进程退出有三种情况,进程正常退出,结果正确/错误,进程异常退出

今天,我们从信号的角度,从三个问题,进一步理解进程的异常

  1. 程序为什么会崩溃?
  2. 崩溃了为什么会退出?
  3. 程序崩溃了能不能不退出?

以我们现在的知识,理解上面的问题十分容易,程序崩溃是因为我们进行了非法的访问或操作,OS向进程发送了信号,该信号的默认动作是终止进程,因此我们的程序直接退出了,最典型的有Floating-point exception(SIGFPE)、Invalid memory reference(SIGSEGV)

我们能使用signal函数捕捉信号,因此程序崩溃了可以不退出,但肯定是不推荐的,具体是为什么,下面会讲

在这里插入图片描述

可以看到,不管是除0收到的SIGFPE信号,还是野指针收到的SIGSEGV信号,它们的默认动作是终止进程,但我们进行了捕捉,程序没有退出;但是,为什么运行结果是一直在执行handler方法,不应该是执行一次handler方法,然后死循环执行主函数后面的代码吗?这就关系到CPU了,两种情况,我们分别解释

我们知道,代码最总是交给CPU去执行的,CPU的运算工作主要分两种,算数运算和逻辑运算,而在CPU的内部,有着各种各样的寄存器,有保存数据的,指向一段代码的…其中有个名为eflag的寄存器,它包含多个位,这些位的值为1/0,有个位叫做溢出标志位,用来表示当前的运算结果是否溢出

当我们的代码执行到10/0时,将10和0分别放到CPU的寄存器中进行计算,我们知道,10/0是不合法的,CPU也知道,因此将eflag寄存器中的溢出标志位置为1,而OS作为CPU的管理者,CPU运算时出了问题,它当然得知道并处理这个问题,于是它读到eflag寄存器的溢出标志位为1,就明白当前的运算结果不合法,给进程发送了信号;此时,该进程的时间片到了,要进行进程切换,我们知道进程切换最重要的就是寄存器需要保存和恢复进程的上下文数据,它也照常这样做,将10和0保存好,下次调度时再恢复,这时大家就应该明白了,下次调度时,运算的还是10/0,溢出标记位置1,OS向进程发送信号,如此往复,就出现了死循环打印handler方法

在这里插入图片描述

对于野指针的问题,也类似,但也有不同;首先介绍三个寄存器,MMU、CR2、CR3

在这里插入图片描述

虚拟地址到物理地址的转换过程中需要MMU的参与,将空指针转换成物理内存时,CPU产生异常,同时将异常地址放在CR2中,OS检测到CPU的异常,给进程发信号,然后进行进程切换,又是对空指针的转换…

在这里插入图片描述

到这里我们也就知道,为什么程序崩溃时推荐直接终止,所谓终止,其实就是释放掉寄存器中的错误数据,终止CPU的异常

关于异常,就说到这

3.3 CoreTerm的区别

进程异常,采用默认动作终止进程时,有两种类别,TermCoreTerm就是终止进程,而Core在终止进程的同时,还会在进程的当前工作路劲下生成一个以进程pid为后缀的core文件(Ubuntu的版本不同,生成的core文件格式可能不同,这里以Ubuntu22.04为例),记录了程序的崩溃信息

在云服务器下,默认是不允许生成core文件,使用ulimit -c size命令允许生成core文件

在这里插入图片描述

此时运行程序,如果程序异常退出,则会生成core文件

在这里插入图片描述

注:如果显示的错误信息后有core dumped,表明core文件已经形成,但在当前目录下没有core文件,表明默认core文件的生成路径不在进程的工作目录下,使用下面的命令即可

sudo bash -c "echo core > /proc/sys/kernel/core-pattern"

上面的部分,我们还有些问题需要解决

  1. 为什么默认关闭生成core文件?
  2. core文件有什么用?

core文件记录下了程序的崩溃信息,在哪一行崩溃,崩溃的原因、上下文等等,导致文件大小比较大,如果一个程序崩溃了就重新运行,这样下去,磁盘空间很容易就被core文件占满,因此一般Linux都是默认关闭生成core文件

当程序崩溃时,使用gdb调试,都是一行一行进行,有了core文件,使用core-file core.pid命令就能直接定位到崩溃的那一行了,方便我们调试了;这种调试方式我们称为事后调试

在这里插入图片描述

进程崩溃退出时生成debug文件,这种技术我们叫做核心转储,该debug文件是进程退出时的镜像文件

关于core,在进程等待中提到过,进程退出会留下退出码和退出信号,其中异常退出时有一个标记位用来表示是否生成了core文件

在这里插入图片描述

在这里插入图片描述

有时进程在做要紧的事,对到来的信号暂不处理,但会在合适的时候处理,这里合适的时候具体是什么时候,会在后面会详谈,现在我们要知道,要处理的前提是记得这个信号,也就是进程得保存信号

4. 信号的保存


初步理解信号的保存:

信号在进程中用位图的方式保存,比如给一个整型,最高位不用,第131位分别代表131号的信号;一个进程是否收到信号,由bit位的内容决定,1表示收到,0表示没有;因此,发送信号就是将信号位图由0变为1,而该位图在内核当中,只有OS能改变该位图的内容;发送信号的本质是OS发给进程信号,也可以叫做写信号

在正式说信号的保存之前,先给出几个概念:

  1. 执行信号的处理动作叫做信号递达
  2. 信号从产生到递达之前的状态叫做信号未决
  3. 进程可以选择阻塞(被阻塞的信号将永不递达,直到解除阻塞状态)某个信号
  4. 阻塞和忽略不同,忽略是处理信号的一种动作,而信号一旦被阻塞,永不被处理

进一步理解信号的保存:

在进程的pcb中,有一条属性指向了三张表,分别是block、pending、handler表,其中block和pending表都是位图的结构,bit位的位置代表几号信号,bit位的内容表示进程是否收到/阻塞该信号;而handler表是一张函数指针数组表,数组的下标代表几号信号,数组的元素指向handler方法

在这里插入图片描述

未来进程处理信号时,从pending表的1号信号开始,检查信号bit位是否为1,如果为1,横向向左检查该信号是否被阻塞,如果没有,就去调用handler方法;依次往下,直到处理完所有信号

讲完理论,下面用代码加深理解:

先介绍一种类型和几个函数

sigset_t,它是Linux提供给用户的一种类型,实际是位图的封装

在这里插入图片描述

在这里插入图片描述

上述代码结果:最开始屏蔽2号信号,当给进程发送2号信号时,2号信号确实没有递达,一直处在未决的状态,过了10秒,我们解除对2号信号的屏蔽,进程立即处理了2号信号并将pending表的2号位置0

通过代码结果,得出结论:

  1. 当信号的屏蔽被解除,进程会立即处理解除屏蔽的信号
  2. 在执行handler方法(递达)之前,就会将pending位置0

5. 信号的处理


前面我们已经使用过signal捕捉信号,处理动作有三种,SIG_DEL/SIG_IGN/handler;同时,我们还提到过,进程可能正在忙,会保存到来的信号,在合适的时候进行处理,所谓合适的时候,就是进程从内核态切换为用户态的时候处理

其中,内核态和用户态是什么?首先给大家描述一个轮廓:进程在执行主函数的某条语句时,遇到了中断、异常或系统调用(后面就拿系统调用举例),而进入内核;执行完系统调用后,再返回到用户前,进行信号的检测,如果信号的默认处理动作是忽略或终止,那很简单,直接返回或终止进程,但如果是自定义捕捉,就要先切换为用户,执行完handler方法后,再返回内核,最后返回到主函数,继续往下执行

在这里插入图片描述

  1. 为什么执行系统调用要进入内核?

    系统调用的函数是OS提供的,都是OS的代码,必须由OS亲自执行

  2. OS能不能直接去调用用户的handler方法?

    不能,OS不相信任何人,不清楚handler方法写的是什么内容,万一是访问用户没有权限访问的内容,不就通过OS访问到了;因此,用户的代码只能有用户自己执行

  3. 为什么要返回到内核再返回到主函数,能不能执行完handler后直接返回到主函数?

    不能,执行handler方法的是不同于主函数的流程,并不知道应该返回到主函数的哪个位置

在这里插入图片描述

简单描述一番,在详谈用户态和内核态前,先讲几个相关知识

5.1 地址空间的进一步理解

我们以32位机器为例,物理内存总共4G,OS分配给每个进程4G的地址空间,其中1G属于内核空间,3G属于用户空间;我们自己的代码通过页表映射到物理内存,这个我们能理解,但使用的各种系统调用都是系统的代码,进程是怎么找到系统的代码的?

当电脑开机时,OS是第一个启动的软件,加载到了物理内存;同动态库的加载类似,OS的代码会加载到每个进程地址空间中,只不过OS的代码是加载到进程的内核空间中,同时会有一张内核级页表,构建了内核空间与物理内存的映射关系;也就是说,系统的代码在进程的地址空间上;执行我们自己的代码,是在用户空间上来回跳转,通过用户级页表找到内存中的代码;执行系统的代码,是在内核空间上来回跳转,通过内核级页表找到内存中的内核代码

每个进程都是自己的用户级页表,但所有进程公用一张内核级页表

在这里插入图片描述

总结上述内容:

  1. OS本身就在进程的地址空间中
  2. 无论进程如何切换,我们总能找到OS
  3. 访问OS,本质是在进程的地址空间上进行的
  4. 访问内核空间,就能找到OS的代码和数据,但OS不相信任何人,访问会收到约束,这里的约束就是我们只能通过系统调用访问内核空间

5.2 键盘输入数据的过程

当进程在运行时,按下ctrl+c,OS会向进程发送信号,进程收到后直接终止,这里的问题是,OS怎么直到我们按下了ctrl+c,它是怎么收到我们按下的信息的?

OS在启动时,会优先向内存中加载一批操作硬件的方法,比如读磁盘、读键盘…存放在函数指针数组中,我们把这个函数指针数组叫做中断向量表;电脑中的每个硬件都有自身的中断号(同时对应着中断向量表的下标),当我们按下键盘时,会触发的硬件中断,向CPU发送中断信号,CPU接受该信号,并在内部存放该硬件的中断号,CPU根据中断号,去执行内存中对应的方法,OS就拿到了键盘的数据

在这里插入图片描述

看到这里,想想信号的发送、处理过程,当进程出现异常,OS给进程发送指定信号,进程根据handler表处理,是不是跟硬件中断有点类似,实际上,信号是模拟实现软件版的硬件中断

5.3 理解OS如何正常运行

5.3.1 OS如何运行

在上面硬件中断的基础上,理解OS如何运行就非常容易;在CPU外部,会有一个时钟,每隔几毫秒向CPU发送中断,CPU内部寄存器就会存放执行调度方法的中断号,进而去调用中断向量表中的调度方法,如此一直循环;OS的本质就是死循环时钟中断,不断调度系统任务

在这里插入图片描述

5.3.2 如何理解系统调用

在内核中,有一张函数指针数组表,存放着所有系统调用的内核函数,内核函数对应的下标我们叫做系统调用号,未来只要拿到系统调用号,就能进行系统调用了

上面时钟中断属于外部中断的方式,CPU内部寄存器也可以自己形成中断号,我们把CPU自身形成中断号的方式叫做内部中断,或者陷阱/缺陷,时钟中断的方式叫做外部中断;不论是内部中断还是外部中断,其目的都是让CPU内部的寄存器形成一个中断数字

我们用的系统调用其实是内核函数的封装,系统调用内部提供了该内核函数的系统调用号;当有系统调用时,触发CPU内部中断,CPU去执行内存中的系统调用方法,OS拿到系统调用号和系统调用函数指针数组,就能完成系统调用

在这里插入图片描述

5.4 内核态和用户态

在CPU内,有个名为code segment的寄存器,记录代码区的范围,其中有两个bit位,可以表示0或3;当值为0时,表示内核态,当值为3时,表示用户态

结论十分简单,但问题是,前面我们说用户是无法直接访问内核空间的,怎么做到不让用户访问内核空间?进程访问地址空间时,必然要通过CPU去执行,如果访问的是内核空间,CPU检查cs寄存器,看是否处于内核态,如果不是,CPU就直接拦截;因此,系统调用函数内部肯定会将用户态设置为内核态

6. 可重入函数


之前我们学过链表的增删查改,以下图的插入函数为例,在插入过程中,执行完第一条语句,此时该进程的时间片到了,进行进程的切换,从用户态变为内核态;在变回用户态前,进行信号的检测,检测到信号并执行handler方法,但如果handler方法也是链表的插入,处理完后,该链表结构为图2;再返回到语句2,执行完链表结构为图3,此时p2节点就找不到了,导致了内存泄漏的问题

在这里插入图片描述

在这种情况下,我们把insert函数称为不可重入函数;大部分情况下,涉及到全局变量/数据修改的函数都是不可重入函数;可重入函数的概念与之相反

7. volatile关键字


在这里插入图片描述

上述代码,编译器优化和不优化出现两种结果,这是为何?

CPU负责代码中的逻辑/算数运算,如果不进行优化,CPU将内存中的flag变量的值先存放到寄存器中,再进行判断;也就是说寄存器的值随着flag的变化而变化

如果进行优化,寄存器第一次读到flag的值后,不再读取内存中的flag值,CPU往后都是直接判断,所以即使我们修改了内存中的flag值,寄存器的值始终不变化,也就是说寄存器隐藏了内存中的真实值

在这里插入图片描述

要解决这种情况,就要使用volatile关键字,对flag变量进行volatile修饰,表示保持该变量在物理内存可见性;这样,不管编译器如何优化,都是先读内存中的flag值到寄存器,再判断

在这里插入图片描述

8. SIGCHLD信号


子进程在退出时,会留下自己的退出码和退出信息,同时,他还会给父进程发送SIGCHLD信号;如果我们不管子进程的退出码和退出信息,同时不想自己处理子进程的僵尸问题,在捕捉信号时使用SIG_IGN,这样进程退出不会有僵尸问题

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1880344.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

YOLO-V1

一、YOLO-V1整体思想与网络架构 1.1 YOLO算法整体思路解读 YOLO-V1: 经典的one-stage方法 把检测问题转化成回归问题,一个CNN就搞定了! 可以对视频进行实时检测,应用领域非常广! 核心思想: 1、预测一张图像中有哪些物…

AI大模型的崛起:第四次工业革命的前奏?

在当今这个信息爆炸的时代,人工智能(AI)大模型的崛起引起了广泛的关注和讨论。有人将其视为第四次工业革命的前奏,然而,这真的可能吗?本文将探讨这一问题,并对中国AI大模型的发展进行简要分析。…

鸿蒙开发Ability Kit(程序框架服务):【向用户申请授权】

向用户申请授权 当应用需要访问用户的隐私信息或使用系统能力时,例如获取位置信息、访问日历、使用相机拍摄照片或录制视频等,应该向用户请求授权,这部分权限是user_grant权限。 当应用申请user_grant权限时,需要完成以下步骤&a…

推荐系统三十六式学习笔记:原理篇.模型融合14|一网打尽协同过滤、矩阵分解和线性模型

目录 从特征组合说起FM模型1.原理2.模型训练3.预测阶段4.一网打尽其他模型5.FFM 总结 在上一篇文章中,我们讲到了使用逻辑回归和梯度提升决策树组合的模型融合办法,用于CTR预估,给这个组合起了个名字,叫“辑度组合”。这对组合中&…

鸿蒙开发设备管理:【@ohos.multimodalInput.inputEventClient (注入按键)】

注入按键 InputEventClient模块提供了注入按键能力。 说明: 本模块首批接口从API version 8开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。本模块接口均为系统接口,三方应用不支持调用。 导入模块 import inputEventCli…

小白学webgl合集-绘制有透视颜色不一样的立方体

效果 原理 结合透视矩阵和视觉矩阵进行绘制 知识点 01透视矩阵 透视矩阵将视图空间中的坐标转换为裁剪空间中的坐标,使得更远的物体看起来更小。 function perspectiveMatrix(fov, aspect, near, far) {const f 1.0 / Math.tan(fov / 2);const nf 1 / (near …

C++旋转点坐标计算

/// 获取A点绕B点旋转P度后的新坐标/// </summary>/// <param name"Angle">角度</param>/// <param name"CirPoint">圆心坐标</param>/// <param name"MovePoint">移动点的坐标</param>/// <param…

(单机架设教程)3D剑踪

前言 今天给大家带来一款单机游戏的架设&#xff1a;3D剑踪 如今市面上的资源参差不齐&#xff0c;大部分的都不能运行&#xff0c;本人亲自测试&#xff0c;运行视频如下&#xff1a; 3D剑踪 搭建教程 此游戏架设不需要虚拟机&#xff0c; 我们先解压 “3D剑踪.zip” &…

【ArcGIS AddIn插件】【可用于全国水旱灾害风险普查】全网最强洪水淹没分析插件-基于8邻域种子搜索算法-有源淹没分析算法

最近有很多GIS小伙伴咨询我关于基于8邻域种子搜索算法的有源淹没分析插件的使用方法及原理&#xff0c;咱们通过这篇文章给大家详细介绍下这款插件的运行机制。 一、插件类型及适用版本 本插件属于ArcGIS AddIn工具条插件&#xff0c;基于ArcGIS Engine10.2.2的开发环境开发的&…

某度,网盘免费加速,复活!

哈喽&#xff0c;各位小伙伴们好&#xff0c;我是给大家带来各类黑科技与前沿资讯的小武。 有小伙伴反馈之前如下夸克网盘脚本的加速方法失效&#xff0c;小武今天测试&#xff0c;依旧正常使用&#xff01; 百度/迅雷/夸克&#xff0c;网盘免费加速&#xff0c;已破&#xf…

最强文生图模型Stable Diffusion 3 Medium 正式开源

Stability AI 宣布 Stable Diffusion 3 Medium 现已开源&#xff0c;是 Stable Diffusion 3 系列中最新、最先进的文本生成图像 AI 模型 —— 官方声称是 “迄今为止最先进的开源模型”&#xff0c;其性能甚至超过了 Midjourney 6。 Stable Diffusion 3 Medium 模型规格参数达到…

科普文:八大排序算法(JAVA实现)+ 自制动画 (袁厨的算法小屋)

我将我仓库里的排序算法给大家汇总整理了一下&#xff0c;写的非常非常细&#xff0c;还对每个算法制作了动画&#xff0c;一定能够对大家有所帮助&#xff0c;欢迎大家阅读。另外我也对 leetcode 上面可以用排序算法秒杀的算法题进行了总结&#xff0c;会在后面的文章中进行发…

[知识点篇]《计算机组成原理》之数据信息的表示

1、数据表示的作用 &#xff08;1&#xff09;定义&#xff1a;将数据按照某种方式组织&#xff0c;以便机器硬件能直接识别和使用。现代计算机采用二进制进行数据表示。 &#xff08;2&#xff09;数据表示考虑因素&#xff1a; 数据的类型&#xff1a; 数值/非数值、小数、…

团队任务管理跟踪软件有哪些?分享2024年值得关注的10款

本文将分享2024年值得关注的10款团队任务管理跟踪软件&#xff1a;Worktile、PingCode、Zoho Projects、Wrike、ProofHub、Connecteam、MeisterTask、Nifty、BIGContacts、Hive。 无论是小型初创企业还是庞大的跨国公司&#xff0c;高效的任务管理都能显著提升工作效率&#xf…

Linux_动、静态库

目录 一、静态库 1、静态库的概念 2、制作静态库的指令 3、制作静态库 4、链接静态库 二、动态库 1、动态库的概念 2、制作动态库的指令 3、制作动态库 4、链接动态库 5、动态库的加载 三、静态库与动态库的区别 结语 前言&#xff1a; 在Linux下大部分程序进…

颍川韩氏,来自战国七雄韩国的豪族

颍川是战国七雄韩国故土&#xff0c;韩国被秦国灭国后&#xff0c;王公贵族们除了坚决反秦的被杀了外&#xff0c;大部分都留存了下来。这些人在楚、汉反秦战争中&#xff0c;成为反秦统一战线的重要力量&#xff0c;其中两人先后被封为重新恢复的韩国的国王。 一个是横阳君韩…

240630_昇思学习打卡-Day12-Transformer中的Multiple-Head Attention

240630_昇思学习打卡-Day12-Transformer中的Multiple-Head Attention 以下为观看大佬课程及查阅资料总结所得&#xff0c;附大佬视频链接&#xff1a;Transformer中Self-Attention以及Multi-Head Attention详解_哔哩哔哩_bilibili&#xff0c;强烈建议先去看大佬视频&#xff…

【Linux】IO多路复用——select,poll,epoll的概念和使用,三种模型的特点和优缺点,epoll的工作模式

文章目录 Linux多路复用1. select1.1 select的概念1.2 select的函数使用1.3 select的优缺点 2. poll2.1 poll的概念2.2 poll的函数使用2.3 poll的优缺点 3. epoll3.1 epoll的概念3.2 epoll的函数使用3.3 epoll的优点3.4 epoll工作模式 Linux多路复用 IO多路复用是一种操作系统的…

人工智能导论速成笔记

文章目录 前言考试题型第一章、人工智能导引 (10分 )课后习题第二章、Python基础 (10分 )*文件读写NumPy的使用Python绘图基础第三章、机器学习初步(15分 )逻辑回归分类(Logistic Regression)*,3.5线性回归预测(Linear Regression)*,3.6 、3.7、 3.8聚类 3.9第四章、自然语言…

郑州高校大学智能制造实验室数字孪生可视化系统平台建设项目验收

随着制造业的转型升级&#xff0c;智能化、信息化已成为制造业发展的必然趋势。数字孪生技术作为智能制造领域的关键技术之一&#xff0c;它通过构建与实体系统相对应的虚拟模型&#xff0c;实现对实体系统的实时监测、预测和优化&#xff0c;为制造业的智能化、信息化提供了强…