我们下面要学的这个,信号,它呢就挺好玩的,虽然它也有一点点难,那么尤其是这里要进入第二阶段的进程地质空间的分享。
第一阶段,是当时在讲进程概念时,学了个进程地址空间,当时知道了地址空间页表,还有我们物理虚拟地理到物理地理之间的映射。那么今天,我们在信号部分呢,大家再渗透,那么地址空间的第二层理解,第二层的理解就叫做用户态,内核态以及充分理解进程间切换的本质啊,在信号这里都会说。当然呢,就这一个难点,剩下的都好理解啊,下面呢讨论的东西叫做信号,那么在讲信号之前呢啊,当然首先要回答两个问题来,那么第一个。我虽然不知道信号是什么啊,但是我觉得这个货是不是跟信号量有点像,对不对?
那信号,是信号量吗?那这个信号跟信号量有关系吗?信号和信号量的关系,就跟老婆和老婆饼一样,那么是没有任何关系,所以呢,我们接下来讲的信号,和我们的信号量没有任何关系,不敢混了啊,这是第一个。
我们把概念区分一下啊,毫无关系啊,那么第二点呢,那么我们要来谈一谈信号部分,下面这是我们对应的一个时间轴。
那么信号,它是针对于进程发送我们某种那么信号就绪的,或者某种信号到来的一种机制让我们信号呢,能够被进行所处理,那么其中信号呢,一共会有三个大阶段,第一个阶段呢,叫做信号产生。第二个阶段叫做信号保存,第三个阶段叫做信号处理。
我们要讲整个信号的全部处理的生命周期,也就是整个。信号的生命周期也就是这,就是我们要学习到的信号,其实信号并不陌生,比如进程kill命令,当时我们说过通过kill呢,向目标进程呢,发送对应的信号。没有重点说,所以这次呢,我们就要来谈一谈,那么它了好把一些具备知识给大家一交代,所以我们面临的第一个话题?是信号产生这货吗?不是,我们还有一个前置的工作叫做预备。
那我们来进入第一个叫做那信号该如何预备呢,首先第一点儿啊,在谈信号的时候呢,先来给各位介绍一下,我们要学习哪些信号啊?来那么在linux当中,如果你想看你当前进程,你的系统支持的信号呢?命令:kill -l。下面它是我们Linux系统目前所支持的相关的信号的大全,一共有这么多。
然后呢?那么我们呢?其中仔细看一下我们信号呢?都有自己的名字,前面的数字呢?就是信号的编号。那么这个名字呢?那么其实本质就是红这个名字本质就是宏的话呢?那么这个数字呢?就相当于信号的编号。未来,我们在使用信号时,既可以使用这个名称,又可以使用前面的数字,这是其一,其二呢,如果大家仔细观察的话,我们发现一没有0号信号。第二没有32,33那么它只有1~31和34~64。
我们把前面的1~31的信号,叫做普通信号。那么我们把叫做34到64,叫实时信号,我们编程这里我们重点讲普通信号。实时信号,我们不聊。
我实在是想象不到那么一个数字是怎么去给进程发的,我我不太理解啊。那么,我们先不着急,先给大家通过生活的角度呢,来帮助大家先来提炼出关于生活当中的信号的一些基本结论来,那么你们平时在生活当中,你觉得哪些东西都属于信号的范畴?哪些场景都相当于我们那么叫做发信号呢。
例如生活中:发令枪、闹钟、红绿灯、消息提醒、老师上课瞪你......。
生活当中呢,那么我们对应的充满了大量的这种发信号的方式啊,我来问一个问题,用红绿灯为例啊,那么第一个问题,各位,你是能够识别红绿灯的,应该没问题吧?
人是能够识别红绿灯的,这句话对不对?那么你肯定是能识别它的,那么下面呢?我们来给这个识别下一个定义,什么东西叫做识别信号呢?那么,第一个叫做你认识它,就是你有概念,你知道那个那个红灯,它是红颜色的,那它代表红灯。绿色的黄色的这些颜色,你能识别出来,这是认识的。这是第一个。第二个啊,那么你单单能认识它吗?然后不管什么颜色的灯你都走,你亮不亮都是你的事。这能叫识别这个红绿灯吗?答案是不能,除了他能看到这红灯亮了,他还要有一个行为,我们给识别这两个字,下个定义就叫做人能够识别红绿灯,它是有两个要素的。第一个他能够知道你这个红绿灯是什么,就是认识它,第二个呢,就是跟这个红绿灯匹配的一套,那么我们就是必须得有对应的行为,这才叫做你识别这个红绿灯。
那么下面我要问大家的第一个问题,这个问题有点奇怪啊,大家不要。比较尽量不要感觉到奇怪啊,就说你为什么能识别信号呢?这应该说,你为什么能够识别红绿灯呢?好,就有人会说,怎么全是废话,我为什么能识别红绿灯?我好像我好像也不清楚啊,我好像发现我也不知道啊,很简单啊,对应的有人教育过你。各位,
那么你再想一想啊,比如说我们有一个老奶奶。一直出生的时候就在深山老林里,然后这一辈子呢,因为那么经济的问题呢,经济很赘据她连县城去都没去过。一直在大山里度过了一生,那么你说她八九十岁走到大马路上的时候,她认不认识红绿灯啊?她能认识红色。
它能认识这是个灯,但她是不认识,这是个红绿灯,更别谈那么红灯亮的是什么意思?绿灯亮什么意思?因为他没有接受过这样的教育,对吧?所以你为什么能够识别红绿灯呢?是因为有人教育过你,可是有人教育过你也不是本质,那么,你为什么能认识这个红绿灯呢?因为有人教育过你,那么通过教育你,这样的手段来达到了一个目的,让你在大脑中啊在。大脑中记住了,红绿灯属性或者叫做行为啊,匹配的行为是因为你自己天然就有人教过你,然后你记住了。所以同学们啊,喜欢闯红灯的呢,一般都是小朋友或者老人啊,因为小朋友呢,他可能太小了,他没有接受过这个教育。老人呢?那么可能,比如年纪大了,眼睛不好,没识别出来,或者呢,就是以前那么可能,就是啊,就是周围条件不好,没有怎么用过见过红绿灯。所以他没有这样的人生经历好,所以你为什么能认识红绿灯呢?是你的大脑的当中是记录它,这是第一个问题。
第二个问题,比如说你今天点了个外卖。点了外卖之后,然后你把这个手机就拿过来,然后就开始玩你的游戏了。然后呢你心理预估?在未来的一个时间段内呢?就有人敲我的门。敲我们,一天到晚没人找我对吧?那大概率就是我们的外卖小哥,他会敲我门儿。所以当我们的外卖到了的时候,就相当于那么就知道外卖小哥来了,然后我呢?就直接可以把门一开,把外卖拿进来,那么我就可以开始吃饭了。
换言之,外卖小哥敲门儿的这个过程其实就相当于在给我发信号。但是各位,当我们已经能够识别这个信号的前提条件下,当信号到来时。或者当外卖小哥敲门儿时,我是不是立马就放下手机,立马就去那么从门口把我的饭拿下来?那么,大部分情况下确实是这样。但是呢,有没有一种情况呢?那么外卖小哥敲门儿了啊,或者在楼下喊你,那给你打电话啊,说你取外卖,那么你外卖到了,然后你呢?现在正在跟你的朋友在打游戏。,别人正在推你们的高地,或者你在推别人的高地,你当前正在做着更重要的事情。即便是外卖小哥给你打电话了,那么你现在可能也没有办法立即去处理这个我们的外卖小哥到来的这个消息。那么比如说绿灯亮了,可是当前,你在马路的这边儿和你的另一个朋友告别。绿灯虽然亮了,但你当前有更重要的事情,就是跟你的朋友告别。你可能也并不是立马过这个马路,所以我想大家想介绍的是,当信号到来的时候。我们不一定啊,立马处理这个信号,原因是什么呢?因为信号可以随时产生。
比如你妈叫你起床,你听到了吗?你听到了,听到之后你立马处理了吗?没有,你可能把你妈的话当耳旁风,继续睡。啊,所以你当前可能有更重要的事情在做啊,因为信号呢,它可能随时产生。可能它随时产生的时候,你当前可能做的更重要的事情,所以你,不一定立马处理它。
而其中信号呢,在进行产生和你当前正在做的事情,我们称之为异步的啊。比如说呢?嗯,外卖小哥在送外卖,他得一家一家的送外卖,那么你在楼上在打游戏,你忙你的,外卖小哥我忙的,你们两个的这种动作呢,就叫做异步的。
比如说你在学习上课,有一天请假了,那么老师不管你,你请假是你的事,我上我的课,所以这叫异步。或者你的老师,在你请假的时候也不上课,大家自习,等你回来才上课,那么这个过程,我们称之为同步,而信号在产生,它是随时随地都在产生。红绿灯,随时随地都能亮,所以信号的处理,它不是立即处理。
那么如果信号的处理呢?它不是立即处理的,那么这里就有问题。假设我是一个有严重失忆症的一个病人。我现在,坐在房间里打着游戏,然后呢,刚点完外卖,点完外卖之后呢,然后外卖到了,然后外卖小哥说啊。你的外卖到了,你下楼取一下吧,然后呢,我说行啊,稍微等我几分钟啊,然后我把电话一挂挂完之后呢,我紧接着立马就去打我对应的游戏。那么,如果我记性不好,那最终我是不是就忘了这个外卖小哥曾经给我打过电话,那我既既然都忘了,你说我会不会下去?是不是我就不会处理它了,那么既然当信号到来时,你不一定立马处理这句话的意思就是说。当信号到来的时候,我在未来一定要处理,所以在信号到的时候,和信号被处理,这里是不是一定有一个时间窗口?
比如说我在打游戏啊,那么外卖小哥打过电话了,我给他说等一等,然后呢,我把游戏打完十分钟过去了。在这十分钟以内,那么这个时间窗口以内,我是不是必须得记住这个信号?是不是?外卖小哥给我打个电话,然后呢?我失忆很严重,刚挂完电话,我说唉,那个谁刚打的电话,什么事?我咋忘了那么继续?还是玩我的游戏吧。
所以如果我忘性特别大,那对不起,那最后这个信号就没办法处理了,对不对?所以呢,信号到来呢,那么我们再到这个信号被处理,一定有个时间窗口,你的说法叫做未来处理,不是立即处理,那说法就是。对应的是不是未来要处理它,那既然是未来要处理这个信号,那是不是在产生到被处理之间就一定存在个时间窗口?那在这个时间窗口之内,就必须得记住这个信号。是不是?
那么再来啊。然后呢,我开始处理这个信号儿了,红绿灯。我们通常有几种处理,比如说我现在处理这个红绿灯了,那绿灯亮了,我是不是马路,那么过马路是所有人的行为。那么大部分人的常规行为,对于对应的红绿灯信号呢,我们所有人都做的这大部分动作呢,我们一般可以称之为默认动作啊,也就是说呢,我们处理信号的时候采用的叫做默认动作啊,默认动作对应的就是我们要过马路,对不对?
那绿灯亮了,那你的妈妈自小给你教的就是当绿灯亮的时候啊,那么你得先在马路边跳一个舞。跳一个舞之后呢,然后再过马路,那么其中呢,别人绿灯一亮,别人都执行默认动作,开始过马路了,而你呢,那么是不是做的动作跟别人就不一样了?那么这个不一样的动作呢,你妈在你小时候给你设置的,对于红绿灯处理的方法和别人不一样,我们这个动作呢,我们叫做自定义动作啊。那么还有一种情况呢就是。,我看到绿灯亮了。我知道可以走了,但是我可以选择不走吗?可以啊,选择不走,那我就站在旁边,什么都不做啊,那么这就叫做忽略动作啊,那么,对于一个信号,你有权利选择忽略吗?
答案是可以啊,比如闹钟响了,闹钟响了的时候呢,正常同默认动作是不是相当于就要起床了?对吧?那么还有一部分人呢?闹钟响了之后,然后呢?他直接。忽略这个闹钟,你响你的,我睡我的,我们两个各自把自己的工作做好,彼此不影响,这就叫做忽略。那么这就是我们处理信号的常见的三种方式。
如下是我们刚刚根据生活来帮助同学们提炼出来的。四大结论分别叫做,你为什么能认识红绿灯,第二个你什么时候处理它,那么不是立即处理。第三,当到来的时候呢,那么你那么必须有能力先把这个信号得记住,然后再合适的时候再处理它,第四,处理的时候呢,那么我们可以采用默认动作来。
上面的产出的理论,我们再挑两个,然后反向的再看看上面的套一套这些东西。它到底是不是信号啊?比如说我们挑一个发令枪。
各位,发令枪响的时候,就是第一个,你怎么辨别你自己是能识别发令枪的呢?答案是,第一个你认识。你知道发令枪响的时候是什么样子?你也知道什么场合下啊,它是什么样的作用?比如说你在操场。你在参加运动会,那枪响了,如果你走在美国的大街上,那不一定是发令枪。
第二个,就是当你在操场的时候,你认识啊,你知道这个老师在给我进行那么发令枪啊,让我开始跑了,第二个那么当发令枪响的时候,你干什么呢?那么你是不是就可以进行奔跑了?这叫做什么?这就叫做行为对吧?那么问题就是你,那么你怎么知道这个发令枪响了之后,你应该干什么呢?很简单呀,因为你以前见过啊,那么比如说你以前小时候参加过各种运动会啊,你们的体育老师给你们教过啊,那么第二个呢,那么当信号到来的时候,那你是不是立即处理这个信号呢?当然,不一定大部分情况下发令枪响,我们立马就不好,但总比发令枪响的时候呢,可能有优先级更高的事情。比如发动枪响的时候,你突然接了个电话啊,你们的老师问你在哪呢?你怎么逃课去了?我要告诉你的爸爸。你爸爸天天揍你,那你这个时候就特别害怕,所以当那么发动枪响的时候呢,那么你可能并不立即跑啊,比如跑个五千米或者一万米。反正你实力很强,你说让让你们500米,先打个电话先,然后我再继续跑啊,这就叫做我们不一定立马处理啊。
再下来呢,那么信号到来时到信号被处理,那同学们发令枪一响,是不是你大脑里面立马就跑呢?那也不一定啊,那么每一个人反应反射弧也有长短。那么,当信号到来的时候呢?可能有一些优先级更高的事情,所以我必须得把我们对应的叫做。把我们对应的相关的这个信号呢,也要能够暂时保存起来,合适的时候再处理,最后呢,那么还有默认动作、自定义和忽略啊。
下面我们来如何把上面的概念,叫做迁移到信号,或者叫迁移到进程中呢?
然后呢,我们站在进程的角度,然后再理解一下它啊,再把上面的概念,用计算机语言呢。那么,站在进程的角度,帮助大家去理解一下啊。
那么下面,我们要做的第二个工作就是把生活经验搬到我们的计算机当中,那么理解它,就非常easy了啊。那么怎么理解呢?各位,首先第一个共识,我们得有啊,叫做共识啊,那么信号是给进程发的好,这是第一个共识。你凭什么这么说呢?因为之前说过,比如kill -9 1234对应的就是进程的PID。那么请问,人是如何识别红绿灯的呢?它需要两个东西,一个认识,一个行为的产生
那好,进程是如何识别信号的好?它第一个它要认识,第二个它要有对应的动作。好,那么我们现在呢?确实对信号不太了解啊,但常识告诉我,上面说了我们为什么能够识别红绿灯呢?是因为有人教育过我,对吧?好,那么换句话说呢,
那么进程如何识别信号呢?首先认识和对应的动作。
那么原因是进程是被操作系统管理的单元,那么在它进程那么或者叫做进程本身是被叫做程序员编写的属性和那么逻辑的集合,是程序员写的。所以换句话说,我现在不知道他咋做的,但是呢,我知道他一定要做。而且呢,那么是通过编码来完成的,所以简称程序员编码完成。
那么具体它是怎么编码?它是就是它设计了什么样的数据结构吗?还是他写了什么样的逻辑?那么我们现在不懂啊,反正我知道你肯定是程序员编码完成的啊。这是第一个,第二个呢?那么我们再来看,当信号到来的时候,那么我们不一定处理这个呃事件或者信号。那么而是呢,
我们当前可能有更重要的事情,所以第二个结论呢,就是那么当我们的当进程收到信号的时候呢?那么进程可能正在执行更重要的代码。那么所以呢,信号不那么不一定会啊,会被立即处理。这是我们的结论啊,来那么,第三个那么再下来呢,叫做我们的信号,到来的时候呢,因为进程呢,它无法立即处理这个信号。
竟然无法立即这个信号,那么其中呢,这里就有问题,信号不会被立即处理,但是信号已经来了呀。那么,作为一个进程来讲,已经来了,但是你现在不立即处理,而是要过段时间处理,那是不是就代表着这个进程在信号到来之后?信号被处理之前的这一段儿时间之内,进那么进程本身必须要有对于信号的叫做保存能力,是不是我们对应的进程,它必须得先想办法把我们对应的叫做信号保存起来,是不是,这是第三个。第四个,那么当未来信号想处理的时候呢?那么它在处理的时候,进程也一样,在处理信号的时候,一般有三种动作,第一个默认动作,第二个自定义,第三个忽略信号。而其中呢,我们有个专业的名词。我们进程处理信号呢?我们称之为信号被捕捉。经过上面的那些共识性的认识呢,我们现在也已经产出了另一批结论。是什么呢?就是我们未来理解信号的基础知识。那么下面呢?我们有了这部分共识呢,然后想重点给大家。把它拆开,拆开之后,找其中一个知识点作为切入点。然后呢,帮助大家再进一步把这些概念再理解一下啊,那么其中呢,这些供足那么概念当中呢?
上面图片这东西我们现在确实还没办法理解,这个捕捉动作处理呢,更没办法理解啊,但是有一个知识点呢,我们其实可以试着理解一下啊,叫做进程本身要对信号具有保存能力。那么,下一个问题就是如果一个信号啊,是发给进程的,而进程要保存。保存那么应该保存在哪里?那么如果一个信号,它要发给进程,那么如果进程要保存的话,你说它保存到哪里比较好呢,但是我知道一个进程呢,那么操作系统为了管理它是给它创建了对应的PCB的,那PCB里包括了进程的所有属性,包括这个进程当前是否收到信号和收到了哪些信号对不对?所以呢,我们猜都能猜出来,叫做保存在进程的task_struct结构体当中。
好,那么下面下一个问题,那么第二个问题就来了,应该被保存哪里呢?叫做这个数据结构里面啊,那因为这是个结构体,将来我们创建个进程。那么,操作系统就根据test struct为该进程创建对应的结构体对象,那么它就相当于进行了实际化,
就给我们对应的进程创建了结构体对象对应的内存。那那么它里面有很多属性,其中就可以有一个属性用来记录信号,这个没问题,下面呢?衍生出来的下一个问题就是那该。如何保存呢啊?你说保存到哪?我知道了。那么第二个问题就是如何保存呢?好,如果让我们进行我们对应的设计这种方案的话来,什么作为切入点呢?刚刚我故意给大家先把信号列表给大家看了啊。其中呢,我们知道信号呢,有1到31个普通信号,我们实时信号不考虑啊。一到31,然后呢?那么我们当前进程呢?它要保存的就是否收到了指定的信号。而信号呢,根据上面讲的一到31,那么所以你觉得我们应该如何保存对应的信号呢?
进程是否收到信号,那么是不是直接用两态表示它是否收到信号了,那是不是在我们内核的task_struct里包含了很多的属性。
这一堆属性我们不看,但是它里面要存在一个unsigened int signal。那么所以呢,我们是不是就可以使用32个比特位,那么我们全0。
其中呢,那么我们假设从右向左啊。那么,我们最右侧呢?就是叫做第一个比特位,第二个比特位,第三个比特位依次类推。所以,我们是不是就可以用我们对应的比特位的位置。代表信号编号信号。
你不是1到31吗?所以我这儿从1开始,代表第一个信号。第二个位置,代表第二个信号,第三个信号......,然后,比特位的位置,代表信号编号,比特位要么1/0。那比特位的内容代表是否收到该信号,0表示没有,1表示有。
那么所以呢,我们在进程的PCB当中,是不是只要存在一个对应的位图结构,然后呢,当我们收到信号时,只需要将位图结构由0变1,代表我们已经完成了这个信号的发送,并且让进行暂时把这个信号保存起来了。下图,第二个比特位由0变1了,代表收到了二号信号。
你们可能猜不出来啊,事实上它就是这么干的啊。就是我现在知道了一个进程的信号是会被暂时保存到它的这个位图结构当中。
那么现在怎么理解,信号是怎么发送的。
信号,其实在PCB里它就是位图结构。那个信号到了,我们就直接去修改对应的位置就可以,就让它保存起来了,对不对?
所以你如何理解PC的发送信号呢?其实很多的linux或unix相关的教材,它都喜欢用发送信号这个词。就程序员,他设计出来的这些技术,他往往就喜欢给它起一些他自己觉得很形象的名字。但是往往就就是就是其实辨识度并不高。
所以呢,发送信号的本质啊,其实根本就不是发送。一旦说发送,大家就会觉得相当于把一个东西从a点搬到b点,其实并不是啊,发送信号的本质其实就是修改PCB中的信号位图。
你说我发一个信号,哪有那么复杂,比如你发一个9号信号,那我就把第九个比特位由0变1,这就叫做信号发送。就这么简单啊。
好那么然后从这个结论里又能得出继续推导一些结论。其实发送的过程,它就是修改位图啊。
再继续,我问一下大家,PCB这个结构是不是操作系统为了管理进程创建的对象,是不是属于内核操作系统维护的数据结构对象?是不是操作系统定义的?因为之前说过进程等于内核数据结构+进程所对应的代码和数据。
所以当一个进程被加载的时候,那么进程操作系统给它维护的相关的task_struct结构体,对不对,所以pcb,它的管理者是操作系统啊。所以谁有权利修改我们的PCB?既然我们是要去修改进程的PCB。进程的PCB这个数据结构可是内核的数据结构啊,就是操作系统内的数据,只有谁能有权利修改?答案是只有操作系统啊,只有操作系统有这个权利啊。
那么换句话说,只有操作系统有权利的话。所以,就再得出一个最终结论,叫无论未来我们学习多少种。发送信号的方式。那么本质就是通过操作系统,向我们对应的目标进程发送的信号。
我们就除了kill,我都没见过其他的,但是不要紧。我们现在一个我们信号发送的方式都没见过,但是我们最终就能得出这样的结论,无论你的信号发送方式有多少种?都是必须本质都是让操作系统向目标进行发信号的,因为任何人都没有权利直接去修改操作系统内的数据结构。
只有操作系统本身能做修改对吧?那未来,操作系统要能够让用户也能发信号,是不是就要求操作系统它必须要提供发送信号,处理信号的相关系统调。那操作系统要不要提供啊?要提供。
所以我们现在信号的接口也一个都没学,但我心里很清楚,操作系统为了让我们能够更好的去进行我们对应的信号发送,你必须得给我提供系统调用,要不然没办法,因为只有你操作系统修改。就像你去银行存钱或者取钱,都是通过那个小窗口完成的(系统调用),不可能让你自己把钱放到银行的保险库里面,或者让你自己去保险库拿钱是一样的道理。
所以,即便是我们也没有学过,那么包括我们之前只是用了一下kill命令,我们现在基本就可以推测出来这个kill命令,它的底层一定调用了对应的系统调用。
这就是用我们现有的知识,一个知识都没学,但我们就能得出这样的结论了,应该可以理解了,这是什么?这是认知的提升。
我们基本认识储备就完成了,我们信号部分的第一个工作预备工作搞定了。
那接下来学什么呢?叫做信号是如何产生的
先来一段小代码看看。
我然后让它跑起来,各位此时它就变成进程了,对不对?
按ctrl c,会发现进程终止了。
所以先来讲第一种发送信号的常见方式,我们叫做ctrl c 热键,以前的作用不是文本的ctrl c 和ctrl v,粘贴,但是也叫做热键。
现在的它,可以用来终止前台进程啊,也就是你的代码呢?如果出现了疯狂刷屏的情况,你可以ctrl c终止它。那么今天我们就告诉大家,凭什么你能终止它呢?本质是ctrl+c叫做是一个组合键。它呢,是被我们对应的,因为它是硬件,是被操作系统先识别,操作系统识别到之后,操作系统会将我们对应的ctrl+c,解释成为叫做二号信号,那么二号信号是谁呢?用kill -查看一下
那么就相当于是ctrl c,最终变成了二号信号,而我们现在呢?一旦收到了个信号,我们刚刚讲过收到信号的时候,那么就是在PCB里第二个位图里,那么由0变1信号就发完了,那么信号呢?它不会立即处理这个信号。
它会在合适的时候去处理啊,那么在未来什么时候我们不确定,但是他一定是后续会处理,如果不会立即处理,可是我ctrl c的时候,它立马就终止了,对吧?各位,不要用你的感知能力去感知CPU。虽然我们一直说它在后续时候在处理,不是说十秒之后20秒,而是说它可能很快几毫秒之后才处理。所以呢,感受不到啊。
所以呢,反正我知道它要处理,那么现在的问题是那么对二号信号处理,应该怎么处理呢?上面我们还谈过对信号的处理有三种方法,默认、自定义和忽略,刚刚代码,对二号信号没有做任何的处理动作,默认就应该是二号信号它的处理动作,
所以怎么去查二号信号的默认处理动作呢?命令:man 7 signal,那么查一下我们对应的七号详细手册那么往下翻。
就有我们对应的信号的value编号,action就是动作、comment表示描述。
所以我们看二号信号,二号信号的值是二,那么动作呢?叫做term?term那么terminal是终止的那个单词的前四个字母。那么它呢?直接呢?默认的行为呢??翻译过来呢,就是那么通过键盘呢,终止进程的执行,它这个单词默认这个单词呢,
它就是一个叫做终止或结束的意思。所以对二号信号的默认处理动作呢,它就是终止进程,所以当我们ctrl c的时候,该进程也就直接进入到了一个结束的状态,对不对?好,那你怎么证明呢?那么,为了更好的去证明这点呢,我们再认识一个接口,今天的第一个信号接口,signal
这个sigal函数呢,第一个参数呢?叫做信号编号,第二个参数,这个signlhand_t。那么它上面呢?就是这种类型,标注一的位置是什么东西?这叫做函数指针对不对?
函数指针呢。就相当于你如果调用signal函数,那么就相当于,对。指定的信号。设置一个默设置一个自定义动作好,上面是不是给大家讲过信号的处理动作,它有三种类别,默认自定义和忽略。
而如果我们想自定义捕捉一个动作,比如说你碰到红绿灯时,别人都过马路,你在那跳舞。那么,这叫做自定义动作,那么其中呢?对于我们的自定义动作呢?那么怎么做呢?所以我们其实呢?就可以通过我们的signal函数,那么设置一个回调函数。
那么,当收到这个信号时,自动会调用你曾经设置好的叫做回调函数,然后呢,这个回调函数呢,返回值是void,参数就是整数。代表的是,当执行该回调时,对应的信号编号是谁,那么下面呢?给大家把代码加起来,大家就懂了啊。
我们对二号信号进行捕捉。捕捉的方法呢?我们自定义叫做hander,一会儿我来重点介绍一下这个hander啊,
返回是void函数名hander,这个函数名随便去写。参数是被捕捉信号的编号。
先让它跑起来
会不会有疑问,上面不是写了两个函数吗,只看到标志1的这个函数一直在跑。
标记2的这个为什么没有执行?
各位,这里叫注册一个函数要记住了记住了。那么这里是siganl函数的调用。啊,并不是handle的调用。这里呢,那么仅仅是设置了对二号信号的捕捉方法。并不代表那么该方法被调用了好。一般。这个方法不会执行,除非。收到对应的信号。
所以这只是注册了一个方法啊。
就好比你现在调皮捣蛋。你妈呢?给你说,如果你在,如果你再调皮捣蛋,这叫做信号。你让我看到了你调皮捣蛋这个信号。那么我下次就用那么啊扫帚打你,这叫什么?这叫做你妈给你脑海里注册了一个回调方法。那么是不是说啊?你刚听到这句话,你就特别害怕你跟你妈说,
你说啊,你不要打我,你不要用骚手打我,我现在觉得好疼呀你。我现在很害怕,不是的,当你妈说这句话的时候呢,那你首先想到的就是她不会现在打我。能理解吧,而是等我下次调皮捣蛋的时候他再打我啊,所以这就叫做hander方法注册的含义啊,好当我们明白这点的时候呢,那么现在就知道为什么这个方法不被调用呢,是因为当前没收到信号。
我们两种做法,kill -2 给5979发。ctrl c。
回车此时呢,我们就可以不断的给他发二号,一发对方立马识别到,哎,那么我收到二号了。并且我们刚说了键盘当中,我们通过键盘在进行我们对应的ctrl c的时候。就是发二号信号
如果我们当前呢,再进行我们对应的ctrl c,它自然而然的就会给我们把键盘ctrl c解释成二号信号,向我们进行发送,我们就能处理这个信号了。
现在有两问题了,这次键盘ctrl c的时候它没办法终止进程呢?原因是因为我们现在把它的默认动作。改成了自定义动作,那么它的自定义动作不再是终止进程,而是捕捉了。
如果你想让它终止,你可以直接在代码这里exit终止这个进程就行了啊。这是第一个
第二,那么就是有人说那我现在键盘杀不掉它了,杀不掉它没关系,你还有大杀器,九号。kill -9 6010。
你照样可以删掉他。好同学们,那么如上就是我们这篇信号1卷,关于信号部分的一个初始内容,最后的一个结论就是。
我们的键盘组合键是发送信号的一种方式好。当然,有人肯定会说,那我现在要是把九号捕捉了呢,你不是只有31个信号吗?我把你30个信号全给你捕捉了,然后我不退出,那我是个进程是不是?金刚不坏呢,永远没有人杀掉我了,对不对?如果这个进程是一个恶意程序,是一个病毒程序,谁都干不掉我?自己可以用电脑试试
如果大家感觉到有所收获的话,在评论区帮我扣一个666。
代码在github:xyt08 (github.com)