进程间通信——信号

来源:互联网 发布:macos mysql 安装 编辑:程序博客网 时间:2024/05/29 04:05

信号是进程间通信机制中唯一的异步通信机制

信号处理办法

  • 忽略            SIGKIL与SIGSTOP无法忽略。用于超级用户对进程的强制管理
  • 系统默认
  • 用户定义

早期不可靠信号(小于SIGRTMIN的信号  非实时信号)

  • 每次处理完信号后会回复到默认处理(需重新装载处理函数)
  • 对每种信号只记录一次,可能导致丢信号
  • 由signal安装(posix标准下的实现不会回复到默认处理,除信号处理函数无法带参数外与sigaction一样)
可靠信号(位于SIGRTMINSIGRTMAX之间的信号 实时信号)

  • sigaction安装。对于目前linux的两个信号安装函数:signal()sigaction()来说,它们都不能把SIGRTMIN以前的信号变成可靠信号(都不支持排队,仍有可能丢失,仍然是不可靠信号),而且对SIGRTMIN以后的信号都支持排队。这两个函数的最大区别在于,经过sigaction安装的信号都能传递信息给信号处理函数(对所有信号这一点都成立),而经过signal安装的信号却不能向信号处理函数传递信息。
信号的发送

pid > 0  进程ID为pid的进程

pid = 0  发送进程同进程组的进程

pid < 0 pid != -1 进程组ID为 -pid的所有进程

pid = -1 除发送进程自身外,所有进程ID大于1的进程

  • int kill(pid_t pid, int signo)  (#include <sys/types.h>  #include <signal.h>)

Signo是信号值,当为0时(即空信号),实际不发送任何信号,但照常进行错误检查,因此,可用于检查目标进程是否存在,以及当前进程是否具有向目标发送信号的权限。调用成功返回 0;否则,返回 -1。

  • int raise(int signo)   (#include <signal.h> )  == kill(getpid(), signo)
  • int sigqueue(pid_t pid, int sig, const union sigval val)   (#include <sys/types.h>  #include <signal.h>)

支持信号带有参数但只能向一个进程发送信号,与sigaction配合使用

  • unsigned int alarm(unsigned int seconds)   (#include <unistd.h>)

seconds秒后,向本进程发送SIGALRM信号。进程调用alarm后,任何以前的alarm()调用都将无效。
seconds=0时,那么进程内将不再包含任何闹钟时间(立即超时且之前的定时都无效)
如果调用alarm()前,进程中已经设置了闹钟时间,则返回上一个闹钟时间的剩余时间,否则返回0

  • int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue));     (#include <sys/time.h> )

which支持3种类型的定时器:

ITIMER_REAL 设定绝对时间;超时后,内核将发送SIGALRM信号给本进程
ITIMER_VIRTUAL 设定程序执行时间
ITIMER_PROF  设定进程执行以及内核因本进程而消耗的时间和

value 指定超时时间
ovalue 返回上一次定时时间

  • void abort(void);     (#include <stdlib.h> )

向本进程发送SIGABORT信号,默认情况下进程会异常退出
可定义自己的信号处理函数。但不可设置为阻塞!

信号的安装
  • void (*signal(int signum, void (*handler))(int)))(int);      (#include <signal.h> )

返回最后一次为安装信号signum而调用signal()时的handler值;失败则返回SIG_ERR
handler可指定为SIG_IGN(忽略)  SIG_DFL(默认)
signum不能是SIGKILLSIGSTOP

  • int sigaction(int signum,const struct sigaction *act,struct sigaction *oldact));  (#include <signal.h> )

第二个参数包含了对指定信号的处理、信号所传递的信息、信号处理函数执行过程中应屏蔽掉哪些函数等信息

sa_mask指定在信号处理程序执行过程中,被阻塞的信号。
缺省情况下当前信号本身被阻塞,以防信号的嵌套发送,除非指定SA_NODEFER或者SA_NOMASK标志位。

sa_flags中包含了标志位

SA_NODEFERSA_NOMASK标志 允许同一信号嵌套

SA_SIGINFO 三参数信号处理函数能否得到参数的开关。不置位而3参数信号处理访问数据则产生段错误


struct sigaction

{

    union

    {

        __sighandler_t _sa_handler;

        void (*_sa_sigaction)(int,struct siginfo *, void *); /*3参数信号处理函数*/

    }_u

    sigset_t sa_mask;

    unsigned long sa_flags;

    void (*sa_restorer)(void); /*弃用*/

}


typedef struct 

{

     int si_signo;

     int si_errno;                 

     int si_code;           

     union sigval

     { 

          int sival_int;         

         void *sival_ptr; 

      } si_value; 

} siginfo_t;

信号集操作
  • #include <signal.h> 
  • int sigemptyset(sigset_t *set);     初始化由set指定的信号集,信号集里面的所有信号被清空;
  • int sigfillset(sigset_t *set);     调用该函数后,set指向的信号集中将包含linux支持的64种信号;
  • int sigaddset(sigset_t *set, int signum);     在set指向的信号集中加入signum信号;
  • int sigdelset(sigset_t *set, int signum);     在set指向的信号集中删除signum信号;
  • int sigismember(const sigset_t *set, int signum);     判定信号signum是否在set指向的信号集中。
信号阻塞与信号未决

  • #include <signal.h>
  • int sigprocmask(int  how,  const  sigset_t *set, sigset_t *oldset));

参数how

SIG_BLOCK 在进程当前阻塞信号集中添加set指向信号集中的信号

SIG_UNBLOCK 如果进程阻塞信号集中包含set指向信号集中的信号,则解除对该信号的阻塞

SIG_SETMASK 更新进程阻塞信号集为set指向的信号集 

  • int sigpending(sigset_t *set));

获得当前已递送到进程,却被阻塞的所有信号,在set指向的信号集中返回结果

  • int sigsuspend(const sigset_t *mask));

用于在接收到某个信号之前临时用mask替换进程的信号掩码并暂停进程执行,直到收到信号为止。sigsuspend 返回后将恢复调用之前的信号掩码。信号处理函数完成后,进程将继续执行。该系统调用始终返回-1,并将errno设置为EINTR





#include <signal.h> 


更新进程阻塞信号集为set指向的信号集

0 0