APUE——sigprocmask,sigaction

18 篇文章 0 订阅
4 篇文章 0 订阅

sigprocmask

在调用sigprocmask后如果有任何未决的、不再阻塞的信号,则在sigprocmask返回前,至少会将其中一个信号递送给该进程。
不能阻塞SIGKILL和SIGSTOP信号。

#include <signal.h>
int sigprocmask( int how, const sigset_t *restrict set, sigset_t *restrict oset );
返回值:若成功则返回0,若出错则返回-1

首先,若oset是非空指针,那么进程的当前信号屏蔽字通过oset返回。
其次,若set是一个非空指针,则参数how指示如何修改当前信号屏蔽字。

信号集操作方法:


#include <signal.h>

int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signo);
int sigdelset(sigset_t *set, int signo);
四个函数的返回值:若成功则返回0,若出错则返回-1

int sigismember(const sigset_t *set, int signo);
返回值:若真则返回1,若假则返回0,若出错则返回-1

函数sigemptyset初始化由set指向的信号集,清除其中所有信号。

函数sigfillset初始化由set指向的信号集,使其包括所有信号。

所有应用程序在使用信号集前,要对该信号集调用sigemptyset或sigfillset一次

函数sigaddset将一个信号添加到现有集中,sigdelset则从信号集中删除一个信号。


在这里插入图片描述
sigprocmask是仅为单线程的进程定义的。
进程屏蔽信号集

#include "apue.h"

static void sig_quit();

int main()
{
    sigset_t newmask,oldmask,pendingmask;

    if(signal(SIGQUIT,sig_quit)<0)
        printf("can't catch SIGQUIT");

    sigemptyset(&newmask);
    sigaddset(&newmask,SIGQUIT);
    if(sigprocmask(SIG_BLOCK,&newmask,&oldmask)<0)
        printf("SIG_BLOCK error");
    sleep(8);

    if(sigpending(&pendingmask)<0)
        printf("pendingmask error");
    if(sigismember(&pendingmask,SIGQUIT))
        printf("\n SIGQUIT pengding");

    if(sigprocmask(SIG_SETMASK,&oldmask,NULL)<0)
        printf("SIG_SETMASK error");

    if(sigpending(&pendingmask)<0)
        printf("pendingmask error");
    if(sigismember(&pendingmask,SIGQUIT))
    {
        printf("\n SIGQUIT pengding");
    }
    else
    {
        printf("\n SIGQUIT is not pengded");
    }
        
    
}

static void sig_quit(int signo)
{
    printf("caught SIGQUIT\n");
    if(signal(SIGQUIT,SIG_DFL)==SIG_ERR)
        printf("cat't reset SIGQUIT");
}

sigaction

参考链接
APUE原文

#include <signal.h>
int sigaction( int signo, const struct sigaction *restrict act, struct sigaction *restrict oact);
返回值:若成功则返回0,若出错则返回-1
struct sigaction {
    void    (*sa_handler)(int);    /* addr of signal handler, or SIG_IGN, or SIG_DFL */
    sigset_t    sa_mask;           /* additional signals to block */
    int    sa_flags;               /* signal options */

    /* alternate handler */
    void    (*sa_sigaction)(int, siginfo_t *, void *);
};

在这里插入图片描述
这里要注意,SA_NODEFER 表示信号处理函数可以重复进入,原调用该信号处理函数后,操作系统会将该信号加入mask里,阻塞表里,进入信号后,会被阻塞。当该函数执行完毕后,会再次处理该函数!但是如果SA_RESETHAND,那么该信号处理函数将会设置缺省值SIG_DFL!!!如果设置sa_flags = 0 ,那么原调用该信号处理函数后,会阻塞,不能重复进入,必须等函数执行完毕!!!

  1. sa_handler此参数和signal()的参数handler相同,代表新的信号处理函数
  2. sa_mask 用来设置在处理该信号时暂时将sa_mask 指定的信号集搁置
  3. sa_flags 用来设置信号处理的其他相关操作,下列的数值可用。
  4. SA_RESETHAND:当调用信号处理函数时,将信号的处理函数重置为缺省值SIG_DFL
  5. SA_RESTART:如果信号中断了进程的某个系统调用,则系统自动启动该系统调用
  6. SA_NODEFER :一般情况下, 当信号处理函数运行时,内核将阻塞该给定信号。但是如果设置了 SA_NODEFER标记, 那么在该信号处理函数运行时,内核将不会阻塞该信号

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

void show_handler(int sig)
{
    printf("I got signal %d\n", sig);
    int i;
    for(i = 0; i < 5; i++) 
   {
        printf("i = %d\n", i);
        sleep(1);
    }
}
 
int main(void)
{
    int i = 0;
    struct sigaction act, oldact;
    act.sa_handler = show_handler;
    sigaddset(&act.sa_mask, SIGQUIT);         //见注(1)
    act.sa_flags = SA_RESETHAND | SA_NODEFER; //见注(2)
    //act.sa_flags = 0;                      //见注(3)
    sigaction(SIGINT, &act, &oldact);  //sigaction是执行信号处理函数的时候屏蔽!!!!
    pr_mask("hello world!!!!!!"); //与int sigprocmask( int how, const sigset_t *restrict set, sigset_t *restrict oset );
    // 不一样!!!!!!sigprocmask是屏蔽但线程的进程
    while(1) 
   {
        sleep(1);
        printf("sleeping %d\n", i);
        i++;
    }
}
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>

void handler();


int main()
{                              //sigaction都是设置与捕捉信号有关的处理
   
   struct sigaction act,old;
   sigemptyset(&act.sa_mask);
   sigaddset(&act.sa_mask,SIGQUIT);
   act.sa_flags =  0;
   act.sa_handler = handler;
   //sigaction(SIGINT,&act,&old);  //这里是在捕捉信号时,阻塞SIGQUIT
   sigprocmask(SIG_SETMASK,&act.sa_mask,NULL);   //主进程阻塞SIGQUIT信号!!
   //signal(SIGINT,handler);
   while(1)
   {
      int d = 0;
      d++;
      printf("value d is : %d\n ",d);
      sleep(1);
   }
   
}

void handler(int signum)
{
   int i=0;

   for(;i<5;i++){
   printf("value i is : %d\n ",i);
   sleep(1);
   }
}

重写signal

#include "apue.h"

Sigfunc* signal(int signo, Sigfunc* func)
{
    struct sigaction act, old;
    sigemptyset(&act.sa_mask);
    act.sa_handler = func;
    act.flags = 0;

    if(signo == SIGALARM)
    {
    #ifdef SA_INTERUPT
        act.sa_flags |= SA_INTERUPT;   //被阻止的系统调用不会重启
    #endif
    }
    else{
    #ifdef SA_RESTART
        act.sa_flags |= SA_RESTART;  //被阻止的系统调用会重启
    #endif
    }
    if (sigaction(,&act,&old)<0)
        return(SIG_ERR);
    return(old.sa_handler);

}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值