本文共 1872 字,大约阅读时间需要 6 分钟。
在进行系统调用时发生signal的情况下改怎么办呢? 从kernel中信号量的处理函数do_signal中可以可以看到,通过in_syscall(regs)来判断发生signal的时候是否正在进行系统调用,如果是的话,则暂时忽略掉系统调用,等处理完信号量后再进行系统调用的过程static void do_signal(struct pt_regs *regs){ unsigned long continue_addr = 0, restart_addr = 0; int retval = 0; struct ksignal ksig; /* * If we were from a system call, check for system call restarting... */#处于系统调用的过程中 if (in_syscall(regs)) { continue_addr = regs->pc; restart_addr = continue_addr - (compat_thumb_mode(regs) ? 2 : 4); retval = regs->regs[0]; /* * Avoid additional syscall restarting via ret_to_user. */#暂时忘掉系统调用 forget_syscall(regs); /* * Prepare for system call restart. We do this here so that a * debugger will see the already changed PC. */ switch (retval) { case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: case -ERESTART_RESTARTBLOCK: regs->regs[0] = regs->orig_x0; regs->pc = restart_addr; break; } } /* * Get the signal to deliver. When running under ptrace, at this point * the debugger may change all of our registers. */ if (get_signal(&ksig)) { /* * Depending on the signal settings, we may need to revert the * decision to restart the system call, but skip this if a * debugger has chosen to restart at a different PC. */ if (regs->pc == restart_addr && (retval == -ERESTARTNOHAND || retval == -ERESTART_RESTARTBLOCK || (retval == -ERESTARTSYS && !(ksig.ka.sa.sa_flags & SA_RESTART)))) { regs->regs[0] = -EINTR; regs->pc = continue_addr; }#处理信号量 handle_signal(&ksig, regs); return; } /* * Handle restarting a different system call. As above, if a debugger * has chosen to restart at a different PC, ignore the restart. */#回复系统调用 if (in_syscall(regs) && regs->pc == restart_addr) { if (retval == -ERESTART_RESTARTBLOCK) setup_restart_syscall(regs); user_rewind_single_step(current); } restore_saved_sigmask();}
转载地址:http://ginmi.baihongyu.com/