信号集

一、信号集

在实际的应用中一个应用程序需要对多个信号进行处理,为了方便,linux系统引进了信号集的概念。信号集用多个信号组成的数据类型sigset_t.可用以下的系统调用设置信号集中所包含的数据。

typedef  struct
{
    unsigned long int __val[_SIGSET_NWORDS];
}sigset_t;

  1.   int sigemptyset(sigset_t *set);  
  2.   int sigfillset(sigset_t *set);  
  3.   int sigaddset(sigset_t *set,int setnum);  
  4.   int sigdelset(sigset_t *set,int setnum);  

set表示信号集指针,setnum表示信号。

sigemptyset  用于将set指向的信号集设为空,即不包含任何信号。

sigfillset   用于将set指向的信号集设为满,即包含所有的信号。

sigaddset    用于向信号集中添加信号。即向set指向的信号集中添加signum信号量

sigdelset    用于向信号集中删除信号。即向set指向的信号集中删除signum信号量

以上函数成功返回0,失败返回-1 。

int   sigismember(const sigset_t *set,int signum)

用于检测signumber是否在set中,若属于返回1,不是返回0,出错返回-1.


二、信号屏蔽字

每个进程都会有一个信号屏蔽字,它规定了当前进程要阻塞的信号集。对于每种可能的信号,信号屏蔽字中都会有一位与之对应,如果该位被设置,也就是说明该信号被屏蔽了,则该信号当前就是阻塞的。

所谓屏蔽, 并不是禁止递送信号, 而是暂时阻塞信号的递送, 解除屏蔽后, 信号将被递送, 不会丢失. 进程可以通过sigprocmask()来获得和修改当前进程的信号屏蔽字。

int sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict oldset);

              功能:可以用来检测或改变目前的信号屏蔽字

              参数:

                        how:指示如何修改屏蔽信号 

SIG_BLOCK   该进程新的信号屏蔽字是其当前信号屏蔽字和set指向信号集的并集。即将set所指向的信号集和当前的信号集屏蔽字按位或。set包含了我们希望阻塞的附加信号。

SIG_UNBLOCK   该进程新的信号屏蔽字是其当前信号屏蔽字和set所指向信号集的补集的交集。set包含了我们希望解除阻塞的信号.

                              SIG_SETMASK  该进程新的信号屏蔽字是set指向的值

                       oldset:是一个非空指针时,存放当前屏蔽信号集

                       set:是一个非空指针时,根据how修改屏蔽信号

                               如果set是个空指针,则不改变该进程的信号屏蔽字,how的值也无意义。

            返回值:执行成功返回0,失败返回-1。

注:如果在调用sigprocmask之后有任何未决的,不再阻塞的信号,则在sigprocmask返回之前,至少会将其中一个信号递送给该进程。如:以前被屏蔽的信号,调用sigprocmask解除屏蔽,但在函数返回之前,该信号便会递送给进程,执行动作,之后函数才会返回。

int sigpending(sigset_t * set);

          功能:返回当前未决的信号集(包括被阻塞不能递送而导致未决的信号)

          参数:set:存放返回信号集

         返回值:函数调用成功返回0,否则返回-1;


 int sigaction(int signum,const struct sigaction *act ,struct sigaction *oldact);

        功能:查询或设置信号处理方式(可同时两种操作)

        参数:

                     signum:要操作的信号编号,可直接写信号的名字

                     act:若act指针非空,则要修改其动作

     oldact : oldact 指针为空,则系统返回该信号的原先动作,并存在oldact中

参数结构sigaction定义如下

struct sigaction {

void (*sa_handler)(int);

void (*sa_sigaction)(int, siginfo_t *, void *);

sigset_t sa_mask;

int sa_flags;

void (*sa_restorer)(void);

      }

信号处理函数可以采用void (*sa_handler)(int)或void (*sa_sigaction)(int, siginfo_t *, void *)。到底采用哪个要看sa_flags中是否设置了SA_SIGINFO位,如果设置了就采用void (*sa_sigaction)(int, siginfo_t *, void *),此时可以向处理函数发送附加信息;默认情况下采用void (*sa_handler)(int),此时只能向处理函数发送信号的数值。

     sa_handler:此参数和signal()的参数handler相同,代表新的信号处理函数,其他意义请参考signal()。

sa_mask:字段说明了一个信号集,在调用该信号捕捉函数之前,这一信号集要加到进程的信号屏蔽字中。仅当从信号捕捉函数返回时再将进程的信号屏蔽字复位为原先值。
sa_flags :用来设置信号处理的其他相关操作,下列的数值可用。
SA_RESTART:如果信号中断了进程的某个系统调用,则系统自动启动该系统调用
SA_SIGINFO:如果设置了此标志,信号处理函数就采用void (*sa_sigaction)(int, siginfo_t *, void *),如果没有设置此标志,信号处理函数就采用void (*sa_handler)(int);
SA_INTERRUPT:由此信号中断的系统调用不会自动启动
(其它标记见UNIX环境高级编程)
void (*sa_sigaction)(int, siginfo_t *, void *);
其中siginfo_t结构体中包含了大量的信号携带信息,可以看出,这个函数比sa_handler要强大,因为前者只能传递一个信号代码,而后者可以传递siginfo_t信息。
typedef struct siginfo_t{
int si_signo;//信号编号
int si_errno;//如果为非零值则错误代码与之关联
int si_code;//说明进程如何接收信号以及从何处收到
pid_t si_pid;//适用于SIGCHLD,代表被终止进程的PID
pid_t si_uid;//适用于SIGCHLD,代表被终止进程所拥有进程的UID
int si_status;//适用于SIGCHLD,代表被终止进程的状态
clock_t si_utime;//适用于SIGCHLD,代表被终止进程所消耗的用户时间
clock_t si_stime;//适用于SIGCHLD,代表被终止进程所消耗系统的时间
sigval_t si_value;
int si_int;
void * si_ptr;
void* si_addr;
int si_band;
int si_fd;
};
返回值:成功返回0,出错:-1
  • 注:而对于sigaction(),Linux默认并不会自动重启动,所以如果希望执行信号处理后自动重启动先前中断的系统调用,就需要为sa_flags指定SA_RESTART标志

int main()

  sigset_t sigset;

  sigfillset(&sigset);/*填充所有信号*/

  if(sigismember(&sigset,SIGINT))/*判断SIGINT*/

  printf("SIGINT exist in signal_set!\n");

  if(sigismember(&sigset,SIGTERM))

  printf("SIGTERM exist in signal_set!\n");

  if(sigismember(&sigset,SIGABRT))

  printf("SIGABRT exist in signal_set!\n");

  if(sigdelset(&sigset,SIGINT)<0)/*移除SIGINT*/

  perror("del error\n");

  else

  printf("SIGINT have been removed!\n");

  if(sigismember(&sigset,SIGINT))/*再次判断*/

  printf("SIGINT exist in signal_set!\n");

  else

  printf("SIGINT not exist in signal_set!\n");

  }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值