Linux 信号详解六(可靠信号与不可靠信号)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>

void catch_signal(int signo, siginfo_t *info, void *p)
{
    switch (signo)
    {
    case SIGINT:
        printf("accept SIGINT!  recv data=%d
",info->si_value.sival_int);
        break;
    case 34:
        //SIGRTMIN似乎不是一个确定的int类型
        printf("accept SIGRTMIN! recv data=%d
",info->si_value.sival_int);
        break;
    case SIGUSR1:
        printf("accept SIGUSR1!
");
        //取消信号阻塞
        sigset_t uset;
        sigemptyset(&uset);
        sigaddset(&uset, SIGINT);
        sigaddset(&uset, SIGRTMIN);
        sigprocmask(SIG_UNBLOCK, &uset, NULL);
        printf("阻塞解除了!
");
        break;
    }
}

int main(int arg, char *args[])
{
    pid_t pid = 0;
    struct sigaction act;
    act.sa_sigaction = catch_signal;
    sigemptyset(&act.sa_mask);
    act.sa_flags = SA_SIGINFO;
    //注册SIGINT信号
    if (sigaction(SIGINT, &act, NULL) != 0)
    {
        printf("sigaction SIGINT failed !
");
        return -1;
    }
    //注册SIGTMIN信号
    if (sigaction(SIGRTMIN, &act, NULL) != 0)
    {
        printf("sigaction SIGINT failed !
");
        return -1;
    }
    //注册SIGUSR1信号
    if (sigaction(SIGUSR1, &act, NULL) != 0)
    {
        printf("sigaction SIGINT failed !
");
        return -1;
    }
    //阻塞SIGINT信号和SIGTMIN信号
    sigset_t bset;
    sigemptyset(&bset);
    sigaddset(&bset, SIGINT);
    sigaddset(&bset, SIGRTMIN);
    //更新进程屏蔽信号状态字
    if (sigprocmask(SIG_BLOCK, &bset, NULL) != 0)
    {
        printf("sigprocmask() failed !
");
        return -1;
    }
    pid = fork();
    if (pid == -1)
    {
        printf("fork() failed ! error message:%s
", strerror(errno));
        return -1;
    }
    if (pid == 0)
    {
        int i = 0, ret = 0;
        union sigval v1;
        union sigval v2;
        for (i = 0; i < 3; i++)
        {
            v1.sival_int = 201 + i;
            ret = sigqueue(getppid(), SIGINT, v1);
            if (ret != 0)
            {
                printf("发送不可靠信号SIGINT失败! error message:%s
", strerror(errno));
            } else
            {
                printf("发送不可靠信号SIGINT成功!
");
            }
        }
        for (i = 0; i < 3; i++)
        {
            v2.sival_int = 301 + i;
            ret = sigqueue(getppid(), SIGRTMIN, v2);
            if (ret != 0)
            {
                printf("发送可靠信号SIGTMIN失败! error message:%s
", strerror(errno));
            } else
            {
                printf("发送可靠信号SIGTMIN成功!
");
            }
        }
        //发送SIGUSR1信号
        if (kill(getppid(), SIGUSR1) != 0)
        {
            printf("kill() failed ! error message;%s
", strerror(errno));
        }
        exit(0);
    }
    //父进程
    int res = 0, status = 0;
    while (1)
    {
        res = wait(&status);
        if (res == -1)
        {
            if (errno == EINTR)
            {

                continue;
            }
            break;
        }
    }
    while (1)
    {
        sleep(1);
    }
    return 0;
}

一:SIGINT是不可靠信号。发送了3次父进程只接收到1次,SIGRTMIN是可靠信号,发送了3次父进程接收到3次信号。
二:对于可靠信号,Linux内核会缓存可靠信号,Linux内核可以缓存8192(各个Linux版本不同)条可靠信号;对于不可靠信号,Linux只能缓存一条不可靠信号。
三:执行命令行: ulimit -a
查看Linux支持的信号性能参数
四:发送信号的数量超过系统上限,将会发送失败

 

原文地址:https://www.cnblogs.com/zhanggaofeng/p/6092379.html