流程如何处理信号?

时间:2016-05-06 17:28:27

标签: linux error-handling linux-kernel kernel signals

当一个程序发出一个INT命令时,操作系统接管并处理请求权限。我不明白这个问题的相反方式,即当信号被发送和操作时控制如何从操作系统转移到进程。好的操作系统会将信号发送给进程。究竟是怎么做到的?当谈到数据包和套接字时,我可以理解控制流。我假设发送信号位实际上是向寄存器写入内容并将程序计数器设置为某个点并将机器状态移回保护模式。我读了一些关于如何向操作系统和其他东西注册错误处理程序的内容。这确实有道理。当出现错误时,只需要求OS将程序计数器移动到用户空间代码中的某个点,这将是错误处理例程。但是很多它对我来说仍然很朦胧。信号的作用是什么?该过程如何知道信号已经到达?

有人可以在信号发送和处理过程中解释低水平的控制流程吗?

2 个答案:

答案 0 :(得分:1)

这完全不是它的工作原理。

int 0x80(等)是一种旧方法,在amd64上没有使用(有一条专用指令'系统调用')。这与问题没有关系。

简而言之,线程始终遍历内核< - >用户空间边界(系统调用,异常(例如页面错误)或仅仅是通过调度输出)。当线程返回用户空间时,它只是检查是否有任何待处理的信号。

所谓的信号传递只是将信息存储在某个信号待处理位置并唤醒目标线程来处理它。醒来的线程返回到用户空间边界,它执行上述操作。

调用信号处理程序并在之后进行清理所需的实际机制更为复杂,我只建议您阅读有关操作系统的书籍。

答案 1 :(得分:1)

  

信号的作用是什么?

为了让您知道具有足够权限的系统上的某些内容已向您发送信号,每个信号都有一个disposition,即默认操作,除非捕获将执行某些操作,即在许多情况下终止您的进程或生成核心转储等。

  

好的操作系统会将信号发送给进程。究竟是怎么做到的?

操作系统可以做任何想做的事情。如果需要,我可以在你的程序中调用任意函数,在信号的情况下,它会检查你是否有一个信号处理程序集,如果有,它会用信号编号调用它。如果不是,它会执行该系统的默认设置。

  

该过程如何知道信号已经到达?

您可以设置一个处理程序,让您知道它何时到达。如果您没有设置处理程序,则会发生默认操作。

在下面的代码中编译并运行它然后使用CTRL-c来终止它或使用kill向它发送各种信号。这证明了捕捉信号。

CAVEAT。以下代码已经在Mac和Linux上运行,如果信号有很多关于整数值的假设,它肯定不是可移植的,它就是如何使用信号来设置signal_handler函数的例子。

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>

extern char *taunts[];
int taunt();

void sig_handler(int signo) {
  switch(signo) {
    case SIGHUP: printf("\t%s %d\n", taunts[taunt()], SIGHUP);break;
    case SIGINT: printf("\t%s %d\n", taunts[taunt()], SIGINT);break;
    case SIGQUIT: printf("\t%s %d\n", taunts[taunt()], SIGQUIT);break;
    case SIGILL: printf("\t%s %d\n", taunts[taunt()], SIGILL);break;
    case SIGTRAP: printf("\t%s %d\n", taunts[taunt()], SIGTRAP);break;
    case SIGABRT: printf("\t%s %d\n", taunts[taunt()], SIGABRT);break;
    case SIGFPE: printf("\t%s %d\n", taunts[taunt()], SIGFPE);break;
    case SIGKILL: printf("\t%s %d\n", taunts[taunt()], SIGKILL);break;
    case SIGBUS: printf("\t%s %d\n", taunts[taunt()], SIGBUS);break;
    case SIGSEGV: printf("\t%s %d\n", taunts[taunt()], SIGSEGV);break;
    case SIGSYS: printf("\t%s %d\n", taunts[taunt()], SIGSYS);break;
    case SIGPIPE: printf("\t%s %d\n", taunts[taunt()], SIGPIPE);break;
    case SIGALRM: printf("\t%s %d\n", taunts[taunt()], SIGALRM);break;
    case SIGTERM: printf("\t%s %d\n", taunts[taunt()], SIGTERM);break;
    default: printf("\tMerde\n");
  }
#ifdef __linux__
  if (signal(signo, sig_handler) == SIG_ERR) {
    printf("Merde: %d\n", signo);
  }
#endif
}

int main(void) {
  srand(time(NULL));
  int i = 0;
  for(i = 0; i < 15; i ++) {
    if (signal(i, sig_handler) == SIG_ERR) {
      printf("Merde: %d\n", i); 
    }   
  }
  while(1) {
    sleep(10);
  }
  return 0;
}

int taunt() {
  return rand() % 12; 
}

char *taunts[13] = { 
"\n No, now go away or I shall taunt you a second time! With youri\n rubbish signal... ",
"\n You don't frighten us, English pig dogs with your daft signal... ",
"\n Go and boil your bottoms, you sons of a silly person and your\n \
  nincompoop signal... ",
"\n I blow my nose at you, so-called \"Arthur King,\" you and all\n \
  your silly English K-nig-hts. With your silly signal... ",
"\n I'm French. Why do you think I have this outrageous accent, you\n \
  silly king? With your silly signal... ",
"\n Mind your own business With your ludicrous signal... ",
"\n You don't frighten us with your silly knees-bent running around\n \
  advancing behavior! With your silly signal... ",
"\n How you English say, I one more time-a unclog my nose in your\n" 
  " direction, sons of a window-dresser! With your weak signal... ",
"\n No chance, English bedwetting types. With your outrageous signal... ",
"\n Yes, depart a lot at this time and cut the approaching any more\n \
  or we fire arrows at the tops of your heads and make castanets\n \
  out of your testiclesi already! With your stupido signal.."
"\n And now remain gone illegitimate faced buggerfolk! and your farty\n signal... ",
"\n And, if you think you got nasty taunting this time, you ain't\n heard nothing yet! I signal in your general direction... ",
"\n Daffy English kniggets! Thpppt!... ",
};