函数signal、sigaction

二、函数sigaction

修改信号处理动作(通常在Linux用来注册一个信号的捕捉函数)

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

参数:

  • act:传入参数,新的处理方式
  • oldact:传出参数,旧的处理方式
struct sigaction
{
    void       (*sa_handler)(int);
    void       (*sa_sigaction)(int, siginfo_t*, void*);
    sigset_t   sa_mask;
    int        sa_flags;
    void       (*sa_restorer)(void);
};

分析:

  •  sa_restorer:该元素是过时的,不应该使用, POSIX.1标准将不指定该元素。(弃用)
  • sa_sigaction:当sa_flags被指定为SA_SIGINFO标志时,使用该信号处理程序(很少使用)
  • sa_handler:指定信号捕捉后的处理函数名(即注册函数)。可赋值为SIG_IGN表忽略或SIG_DFL表执行默认动作
  • sa_mask:调用信号处理函数时,所要屏蔽的信号集合(信号屏蔽字)。注意仅在处理函数调用期间屏蔽。(默认属性:信号捕捉函数执行期间,自动屏蔽本信号)
  • sa_flag:通常设置为0,表默认属性

 

1. 测试代码:

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

void docatch(int signo)
{
    printf("%d signal is catch\n", signo);
}

int main()
{
    int ret;
    struct sigaction act;
    act.sa_handler = docatch;
    sigemptyset(&act.sa_mask);
    sigaddset(&act.sa_mask, SIGQUIT);
    act.sa_flags = 0;  //默认属性:信号捕捉函数执行期间,自动屏蔽本信号
    ret = sigaction(SIGINT, &act, NULL);
    if(ret < 0) {
        perror("sigaction error");
        exit(1);
    }
    while(1)
      sleep(1);
    return 0;
}

输出结果:

 

信号捕捉特性:

  • 进程正常运行时,默认PCB有一个信号屏蔽字,假定为☆,它决定了进程自动屏蔽哪些信号,当注册了某个信号步捕捉函数,捕捉到该信号以后,要调用该函数,而该函数有可能执行很长时间,在这期间所屏蔽的信号不由☆指定,而由sa_mask来指定,调用完信号处理函数,再恢复为☆。
  • xxx信号捕捉函数执行期间,XXX信号自动屏蔽。
  • 阻塞的常规信号不支持排队,产生多次只记录一次(后32个实时信号支持排队)

 

 

2. 测试代码:

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

void docatch(int signo)
{
    printf("%d signal is catch\n", signo);
    sleep(10);
    printf("--------------finish\n");
}

int main()
{
    int ret;
    struct sigaction act;
    act.sa_handler = docatch;
    sigemptyset(&act.sa_mask);
    sigaddset(&act.sa_mask, SIGQUIT);
    act.sa_flags = 0;
    ret = sigaction(SIGINT, &act, NULL);
    if (ret < 0) 
    {
        perror("sigaction error");
        exit(1);
    }
    while (1) sleep(1);
    return 0;
}

输出结果:

 

#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
 
void sys_err(char *str)
{
    perror(str);
    exit(1);
}
 
void do_sig_child(int signo)
{
    int status;
    pid_t pid;
 
    while ((pid = waitpid(0, &status, WNOHANG)) > 0) 
    {
        if (WIFEXITED(status))
            printf("---------------------------child %d exit %d\n", pid, WEXITSTATUS(status));
        else if (WIFSIGNALED(status))
            printf("child %d cancel signal %d\n", pid, WTERMSIG(status));
    }
}
 
int main()
{
    pid_t pid;
    int i;
    for (i = 0; i < 10; i++) 
    {
        if ((pid = fork()) == 0)
            break;
        else if (pid < 0)
            sys_err("fork");
    }
    if (pid == 0) //子进程
    {
        int n = 1;
        while (n--) 
        {
            printf("child ID %d\n", getpid());
            sleep(1);
        }
        return i + 1;
    }
    else if (pid > 0) //父进程
    {
        struct sigaction act;           //SIGCHLD阻塞
        act.sa_handler = do_sig_child;
        sigemptyset(&act.sa_mask);
        act.sa_flags = 0;
        sigaction(SIGCHLD, &act, NULL);  //解除对SIGCHLD的阻塞    
 
        while (1) 
        {
            printf("parent ID %d\n", getpid());
            sleep(1);
        }
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值