考虑以下场景:
三种信号a,b,c,优先级为c<a<b(<指优先于)
当前在处理a信号,a信号的sa_mask把c信号ban了,没有ban b信号,此时先后收到了c信号和b信号,c信号进入等待队列,此时是直接去处理b信号还是把b信号也放入等待队列?
按我的理解是直接去处理b信号的,那么如果b信号的sa_mask没有把c信号ban了,处理完b信号后,应该处理a信号还是c信号?
还有一个问题就是,blocked和pending的信息感觉要放在struct Env里?要在Env里include signal.h感觉很怪,但是直接写两个uint32_t感觉也很怪?
以及对某个信号没有设置处理动作的时候,是不是就按默认处理动作来实现?
最后修改于:
最后回复于:
回复主题帖
前两个问题可以参考这里
个人意见,信号处理是遵循
保存上下文->进入处理函数->屏蔽sa_mask
->处理->解除屏蔽->恢复上下文
的顺序的。在处理A信号时如果跳转去处理B信号,B信号处理完毕返回时,A信号对C信号的屏蔽还未解除,我觉得应该继续处理A信号,待A信号解除屏蔽后再处理C信号。
👀
—————更新——————
搓了一个测试程序(已丢失)
2024.06.13:更新了测试程序
最后修改于:2024-06-13 18:15:05
为什么你的sigint会比sigchld晚处理?
最后修改于:2024-06-04 12:21:45
看一下代码。
我复刻了楼主描述的场景,让sigsegv屏蔽了sigint。
最后修改于:2024-06-05 10:12:19
之前看了,想知道你是怎么处理sigchld和sigint的顺序的
最后修改于:2024-06-10 21:29:27
sigpending & !mask
之后 0-31 遍历,
先遍历到SIGINT
因为mask对应位是1所以跳过,往后处理SIGCHLD
,等SIGSEGV
处理完,移除SIGINT
的mask再处理SIGINT
最后修改于:2024-06-10 23:16:41
SIGSEGV
的优先级高于 SIGCHLD
,所以在函数
void sigsegv_handler(int sig)
执行完之前(即SIGSEGV signal handler returns.
被打印出来之前),是不是不应该去处理
SIGCHLD
?
最后修改于:2024-06-11 09:10:43
我觉得应该处理SIGCHLD
根据这里
Execution of signal handlers Whenever there is a transition from kernel-mode to user-mode execution (e.g., on return from a system call or scheduling of a thread onto the CPU), the kernel checks whether there is a pending unblocked signal for which the process has established a signal handler. If there is such a pending signal, the following steps occur: (1) The kernel performs the necessary preparatory steps for execution of the signal handler: (1.1) The signal is removed from the set of pending signals. ... (2) The kernel constructs a frame for the signal handler on the stack. The kernel sets the program counter for the thread to point to the first instruction of the signal handler function, and configures the return address for that function to point to a piece of user-space code known as the signal trampoline (described in sigreturn(2)). ... From the kernel's point of view, execution of the signal handler code is exactly the same as the execution of any other user-space code.
进入SIGSEGV
的handler时对应信号相当于已经移除了,重新调度时当前是否在处理SIGSEGV
信号对内核来说没有区别,我认为会处理新的信号,即使新的信号优先级更低。
而且让高优先级信号屏蔽低优先级信号在用户态就可以实现,可以让每个信号把其后的信号都mask掉
不过你的说法确实有道理,也许应该请助教澄清一下。
(唉其实我不做这个挑战性任务的)
最后修改于:2024-06-11 14:02:41
我认为上面提到的“移除该信号”的作用是防止再次处理该信号
比如说,执行该信号的处理函数的过程中遇到时钟中断,如果之前没有移除该信号,会再次调用该处理函数
可能上面说的是这个意思。
另外,信号的优先级我理解的是处理该信号的优先级,执行完毕一个信号的处理函数或者默认动作才算处理完成
助教回复了,石伊聪的观点是对的
最后修改于:2024-06-12 15:40:49
SIGSEGV 的优先级确实高于 SIGCHLD,但是优先级的作用是
当有两个不同的信号需要处理时,需要先处理编号较小的信号
而现在是在SIGSEGV的handler执行过程中收到了SIGCHLD,不是在两个未处理的信号中选择,因此我觉得此时应该处理SIGCHLD的handler。
可以设想这样的场景,高优先级的信号A的处理过程中,需要低优先级信号B的处理函数来辅助其处理,如果这时候把优先级低于A的所有信号都屏蔽了,那A的处理有可能也无法推进
最后修改于:2024-06-12 16:20:18
你的观点是正确的,在我发布的帖子中助教回答了这一问题
你设想的场景确实有道理,谢谢
最后修改于:2024-06-12 17:07:07
SIGSEGV
编号是 11
, 把样例中
SIGCHLD
相关代码改为发送信号 10
或者其他合适信号,就能复现你的打印顺序了。
最后修改于:2024-06-11 09:24:38
回复主题帖
楼上那位同学给出的文档中,在处理a信号时,a信号是会被自动屏蔽的,但是在指导书中我似乎并没有看到这个表述,请问助教这个的要求是什么?
文档:
When the handler for a particular signal is invoked, that signal is automatically blocked until the handler returns.
最后修改于:2024-06-02 19:04:34
楼上那位同学给出的文档中,在处理a信号时,a信号是会被自动屏蔽的,但是在指导书中我似乎并没有看到这个表述,请问助教这个的要求是什么?
这里请参考指导书(在具体需要实现的信号那一部分):
注: 不同普通信号优先级不同,编号更小的信号拥有更高的优先级,即当有两个不同的信号需要处理时,需要先处理编号较小的信号;同一普通信号在进程中最多只存在一个,也即如果有多个同样编号信号发送至某一进程,只取其中一个。 并且对于SIGSEGV信号,在原MOS中会进行panic,你需要取消该设置,改为发送SIGSEGV信号,如果存在疑问可在讨论区提出。
指导书中指出需要实现的信号为[1,32]
的普通信号,普通信号不排队且具有优先级。不排队的意思说的是任意时间段对于一个普通来说,一个进程至多只会存在一个实例。也就是说在某一信号发送到一个进程这一时刻到进程执行完该信号的处理函数前,需要在这期间屏蔽该信号。所以在该任务中,相比”等待队列“,“等待队列集”似乎更好。
当前在处理a信号,a信号的sa_mask把c信号ban了,没有ban b信号,此时先后收到了c信号和b信号,c信号进入等待队列,此时是直接去处理b信号还是把b信号也放入等待队列?
这里的话应该是先处理b信号。
按我的理解是直接去处理b信号的,那么如果b信号的sa_mask没有把c信号ban了,处理完b信号后,应该处理a信号还是c信号?
信号处理函数在执行时会将该信号的屏蔽集中需要屏蔽的信号添加入进程的信号屏蔽集中,而非直接覆盖,因为之前在处理a时已经屏蔽c信号,所以在执行b信号时也不会解除对c信号的屏蔽(除非在处理函数中有代码解除屏蔽),在执行完b信号后,会将进程的屏蔽集恢复到执行b信号前的状态,此时还是屏蔽c信号的,所以会继续执行a信号处理函数(即使不屏蔽c也还是继续执行a函数)。
blocked和pending的信息感觉要放在struct Env里?要在Env里include signal.h感觉很怪,但是直接写两个uint32_t感觉也很怪?
指导书中“请将所有实现函数的声明与结构体定义存放在位于MOS根目录的./user/include/signal.h
中”的描述可以通过在signal.h
中引入专门存放结构体的头文件,比如sigset.h
,这样env.h
中只会引用sigset.h
。
以及对某个信号没有设置处理动作的时候,是不是就按默认处理动作来实现?
如果某一信号没有设置处理动作,就会执行默认处理动作,具体的默认处理动作请参考指导书。
如果有其他问题欢迎提出。
最后修改于:2024-06-02 20:19:09
也就是说在某一信号发送到一个进程这一时刻到进程执行完该信号的处理函数前,需要在这期间屏蔽该信号。
我没有完全理解这里“屏蔽”的含义。如果进程在处理A信号时又收到了另外的一个A信号,那么在当前A信号处理完毕后它是直接回到正常控制流还是再次进入A信号处理动作?
最后修改于:2024-06-02 20:33:00
当一个信号被执行时,会添加对该类型信号的屏蔽,在结束执行后在恢复之前的屏蔽集。
那么在当前A信号处理完毕后它是直接回到正常控制流还是再次进入A信号处理动作?
这里应该是回到之前的控制流中。
最后修改于:2024-06-13 17:53:59
请问不同进程对同一个signal会注册不同的handler吗?
最后修改于:2024-06-03 22:00:15
是的,不同进程可以对同一个signal注册不同的handler。
最后修改于:2024-06-03 22:06:16
请问执行到非法指令时,之前lab的do_reserved是否还会执行?是否需要对这个函数做改动?
最后修改于:2024-06-03 23:38:03
补充一下
SIGCHLD
,SIGILL
,SIGSYS
,SIGSEGV
都需要改动原有实现才能保证内核发出相应信号,要改吗?
最后修改于:2024-06-04 10:33:37
我认为要改,这是任务的一部分
不改的话,内核现在是发不出这些信号的,关于这几个信号的测试样例也过不了
最后修改于:2024-06-04 10:43:12
助教,能不能帮忙看下这个帖子下,我今天上午9点之后和石伊聪的对话记录?
最后修改于:2024-06-11 13:58:06
请问“需要先处理编号较小的信号;同一普通信号在进程中最多只存在一个,也即如果有多个同样编号信号发送至某一进程,只取其中一个。”这句话是什么意思,是一个进程在一个时刻只能处理一个信号吗,还是可以并行的处理?如果是可以并行的处理,那么“先处理”该如何体现呢?
最后修改于:2024-06-11 10:08:13
同一普通信号在进程中最多只存在一个,也即如果有多个同样编号信号发送至某一进程,只取其中一个。
就是说当一个信号在被处理时(也就是在执行对应的处理函数时),其他发往该进程的同类型信号都应该在这期间被屏蔽掉。
“先处理”的意思是指,当进程到了需要处理信号的时候,如果此时待处理信号集中,同时存在多个信号待处理,就会先去执行优先级最高的信号。
最后修改于:2024-06-11 15:39:34
对一个进程fork的时候是否需要将sigaction的配置复制到fork出来的子进程中?以及屏蔽集需要复制吗?
我的理解是,sigaction需要复制,屏蔽集不需要复制。
文档中的相关描述:
A child created via fork(2) inherits a copy of its parent's signal dispositions. During an execve(2), the dispositions of handled signals are reset to the default; the dispositions of ignored signals are left unchanged.
https://man7.org/linux/man-pages/man7/signal.7.html
最后修改于:2024-06-12 21:31:57
对于fork来说sigaction的配置和屏蔽集都是需要复制的,对于execve有点不同。
最后修改于:2024-06-12 22:03:31
对应SIGSYS信号的默认操作是忽略,请问是否需要将epc+4以跳过有问题的syscall,防止进入死循环?
最后修改于:2024-06-13 14:14:04
需要epc + 4 的,指导书可能和POSIX的标准不太相同。
最后修改于:2024-06-13 16:14:08
想问一下是对于所有的系统调用错误都要epc加4,还是只针对默认忽略的情况?还有需要保留regs[2]=-E_NO_SYS吗?我没有epc加4的时候可以过14个点,但加了epc+4(对于所有的系统调用错误)就只能过12个了。
最后修改于:2024-06-14 11:28:00
需要实现 execve
时信号量的配置吗?
最后修改于:2024-06-14 00:06:15
助教你好,我想问一下如果此时正在处理a,此时又来了一个a信号,此时新来的a到底是消失还是进等待集啊,你之前说的是消失,但是后面又说即屏蔽,屏蔽和直接消失好像不太一样吧
最后修改于:2024-06-13 17:18:37
不好意思,我之前说的不太清楚,当一个信号被处理时,需要阻塞同类型的信号,也就是将其添加到待处理信号集,已修改之前的描述,感谢指出。
最后修改于:2024-06-13 17:54:20
请问老师,按照添加到待处理信号集的含义
下面的测试程序应该能退出不会卡死?TT
1 | #include <lib.h> |
最后修改于:2024-06-13 18:45:54
这样应该是不会被卡死的,输出0-5之后就会结束。
最后修改于:2024-06-13 18:58:17
请问sigaction的测试会涉及到shell和管道吗
最后修改于:2024-06-13 21:49:42
abc信号,同时来ab,先处理a,处理a的过程中来了c,去处理c,c把b ban了,这个时候调用sigpending,b应该算在被屏蔽的信号里吗
最后修改于:2024-06-14 19:39:42
助教您好,对于int sigprocmask(int __how, const sigset_t * __set, sigset_t * __oset);
请问是否会使用oset进行测评?也就是能否根据需要对进程存储的sigaction需要屏蔽的信号集进行修改,比如给进程注册sigaction时直接让所有的sigaction无法屏蔽SIGKILL,以及所有的sigaction都屏蔽同类信号?
最后修改于:2024-06-14 23:14:26
然而测试点4(16/18)与这类数据无关TT,谢谢助教和同学
最后修改于:2024-06-13 19:44:03