信号

信号提供了一种处理 异步事件 的方法,产生信号的时间对进程而言是随机出现的。

signal函数

void (*signal (int signo, void (*func)(int))(int);:signal的参数列表为一个信号值signo,一个 void (*)(int)型的函数指针,返回值为 void (*)(int) 型的

  • func的取值:
-   常数 SIG_IGN:忽略信号(SIGKILL和SIGSTOP是不能忽略的)
-   常数 SIG_DEF:采用系统默认动作
-   当接到此信号后要调用的函数的地址
  • signal 函数相当于一个注册作用,它让进程可以告诉内核,当指定的信号到来时,应该采取什么操作。

进程创建和启动

  • 进程调用 fork 时,子进程继承父进程的信号处理方式
  • exec时,原先设置为要捕捉的信号都改为系统默认动作,其他信号不变
-   例如 shell 处理后台作业的中断和退出信号,shell自动将后台作业中对中断和退出信号的处理方式设置为忽略。这样在按中断键,后台作业就不会受到影响

中断的系统调用:

  • 如果在进程执行一个低速的系统调用而阻塞,期间捕捉到一个信号,则该系统调用就被中断不再继续
  • 被中断的系统调用的自动再启动:被中断时,自动重新启动

可重入函数:

  • 可以被中断的函数,在函数的任何执行时刻中断它,OS转而去执行其他代码,而返回该函数时不会发生什么错误
  • 不可重入的函数:由于使用了一些系统资源,比如全局变量区,中断向量表等,如果被中断的话,会出现问题

信号相关的函数:

  • kill:int kill(pid_t pid, int signo);
-   pid > 0:把信号发给ID为pid的进程
-   pid == 0:把信号发送给与发送进程同一进程组,且发送进程有权向其发送信号的进程
-   pid < 0:发送给进程组ID等于pid绝对值,且发送进程有权向其发送
  • raise:int raise(int signo);:向自身发送信号
  • alarm:unsigned int alarm(unsigned int seconds);:设置一个时钟值,当超时时产生一个SIGALRM信号
  • pause:使进程挂起,直到捕捉到一个信号

信号阻塞:

  • 让系统暂时保留信号,待以后发送,信号会在解除阻塞后继续传递
  • 使用 sigprocmask() 阻塞信号的传递。一般在要操作一些全局变量前,用 sigprocmask 阻塞信号,在操作结束后恢复信号的传递。
  • 信号集:sigset_t
    • 初始化: sigemptyset、sigfillset,成功返回0,失败返回 -1
      • int sigemptyset(sigset_t * set);:不包含任何信号的信号集
      • int sigfillset(sigset_t * set);:包含所有信号的信号集
    • 增删信号:sigaddset、sigdelset,成功返回0,失败返回 -1
      • int sigaddset(sigset_t * set, int signo);
      • int sigdelset(sigset_t * set, int signo);
    • 判断是否存在:int sigismember(const sigset_t * set, int signo);,是则返回1,否则返回0

你可能感兴趣的:(信号)