标签:
因为在下能力相当有限,有不当之处。还望大家批评指正^_^
一、 信号概念
每一个经程。通过pthread_sigmask设置自己要堵塞的信号。
问题是,这种话,信号来了,详细由哪个线程谁处理呢???
/* * Now find a thread we can wake up to take the signal off the queue. * * If the main thread wants the signal, it gets first crack. * Probably the least surprising to the average bear. */ if (wants_signal(sig, p)) t = p; else if (!group || thread_group_empty(p)) /* * There is just one thread and it does not need to be woken. * It will dequeue unblocked signals before it runs again. */ return; else { /* * Otherwise try to find a suitable thread. */ t = signal->curr_target; while (!wants_signal(sig, t)) { t = next_thread(t); if (t == signal->curr_target) /* * No thread needs to be woken. * Any eligible threads will see * the signal in the queue soon. */ return; } signal->curr_target = t; }
同一时候,信号又可以得到妥善的处理。一种解决方法是:全部线程均堵塞全部process-directed信号。由一个线程轮询接收处理这些信号。
任务通常会由于中断、系统调用、指令异常这几个原因,进入内核态。但无论是哪一种,在返回用户态之前,内核都会做信号方面的检查与处理。这个流程是一样的。
以i386为例,其代码在例如以下文件里。
arch\x86\kernel\entry_32.S
见arch\x86\include\asm\unistd_64.h
ioctl的C库函数汇编代码例如以下:
000000000040af30 <__ioctl>:
40af30: b8 10 00 00 00 mov $0x10,%eax
40af35: 0f 05 syscall
40af37: 48 3d 01 f0 ff ff cmp $0xfffffffffffff001,%rax
40af3d: 0f 83 ad 23 00 00 jae 40d2f0 <__syscall_error>
40af43: c3 retq
40af44: 90 nop
40af45: 90 nop
handle_signal中的代码片断例如以下:
case -ERESTARTSYS:
if (!(ka->sa.sa_flags & SA_RESTART)) {
regs->ax = -EINTR;
break;
}
/* fallthrough */
case -ERESTARTNOINTR:
regs->ax = regs->orig_ax;
regs->ip -= 2; //等于回到__ioctl中调用syscall之前的地方了
break;
而是回到用户设置的信号处理函数的地址处開始运行。就好像线程当初进入内核前正要运行信号处理函数一样。
以x86_32,传统信号处理方式为例。
代码在ia32_setup_frame中
内核在ia32_setup_frame中为返回做好了准备
用户态信号处理函数的栈帧中。返回地址被内核赋了相应的值。即用户态信号处理函数在返回时。会返回到内核事先安排好的地方继续运行。事实上就是调用__NR_ia32_sigreturn,相应sys_sigreturn。
他从栈里面取出现场环境数据,进行恢复。
这些栈里面的数据,则是前面在ia32_setup_frame 处理中。通过调用函数ia32_setup_sigcontext进行保存的。
标签:
原文地址:http://www.cnblogs.com/mengfanrong/p/5340785.html