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\n",info->si_value.sival_int);
        break;
    case 34:
        //SIGRTMIN似乎不是一個確定的int類型
        printf("accept SIGRTMIN! recv data=%d\n",info->si_value.sival_int);
        break;
    case SIGUSR1:
        printf("accept SIGUSR1!\n");
        //取消信號阻塞
        sigset_t uset;
        sigemptyset(&uset);
        sigaddset(&uset, SIGINT);
        sigaddset(&uset, SIGRTMIN);
        sigprocmask(SIG_UNBLOCK, &uset, NULL);
        printf("阻塞解除了!\n");
        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 !\n");
        return -1;
    }
    //注冊SIGTMIN信號
    if (sigaction(SIGRTMIN, &act, NULL) != 0)
    {
        printf("sigaction SIGINT failed !\n");
        return -1;
    }
    //注冊SIGUSR1信號
    if (sigaction(SIGUSR1, &act, NULL) != 0)
    {
        printf("sigaction SIGINT failed !\n");
        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 !\n");
        return -1;
    }
    pid = fork();
    if (pid == -1)
    {
        printf("fork() failed ! error message:%s\n", 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\n", strerror(errno));
            } else
            {
                printf("發送不可靠信號SIGINT成功!\n");
            }
        }
        for (i = 0; i < 3; i++)
        {
            v2.sival_int = 301 + i;
            ret = sigqueue(getppid(), SIGRTMIN, v2);
            if (ret != 0)
            {
                printf("發送可靠信號SIGTMIN失敗! error message:%s\n", strerror(errno));
            } else
            {
                printf("發送可靠信號SIGTMIN成功!\n");
            }
        }
        //發送SIGUSR1信號
        if (kill(getppid(), SIGUSR1) != 0)
        {
            printf("kill() failed ! error message;%s\n", 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支持的信號性能參數
四:發送信號的數量超過系統上限,將會發送失敗

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM