可靠信号和不可靠信号的测试

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

/* 
    1. 创建子进程和父进程
    2. 注册 SIGINT 非实时信号 SIGRTMIN 实时信号,添加到进程阻塞中
    3. 注册用户自定义信号 SIGQUIT
    4. 子进程发送3次非实时信号,发3次实时信号
    5. 子进程发送SIGQUIT解除信号阻塞
    6. 观察实时信号和非实时信号的表现与区别 
*/
// int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);  -----> 设置信号阻塞或非阻塞
//        int sigaction(int signum, const struct sigaction *act,    -----> 信号安装函数
//                     struct sigaction *oldact);

void handle(int signum, siginfo_t *info, void *p);

int main(void)
{
    pid_t fpid, pid;
    sigset_t mset;          // 信号集
    struct sigaction act;   // act结构体中含信号处理函数

    act.sa_sigaction = handle;      // 信号处理函数
    act.sa_flags = SA_SIGINFO;      // 标志位为SA_SIGINFO时,sigaction函数才能接收sigqueue发送的信号

    // 安装三个信号,一个实时(SIGRTMIN),一个非实时(SIGINT),一个通过键盘发送信号测试程序(SIGQUIT)
    sigaction(SIGINT, &act, NULL);
    sigaction(SIGRTMIN, &act, NULL);
    sigaction(SIGQUIT, &act, NULL);

    // 设置实时和非实时信号阻塞
    sigemptyset(&mset);
    sigaddset(&mset, SIGINT);
    sigaddset(&mset, SIGRTMIN);

    sigprocmask(SIG_BLOCK, &mset, NULL);

    fpid = fork();

    if (fpid == -1) {
        perror("MSG");
        exit(0);
    }
// int sigqueue(pid_t pid, int sig, const union sigval value);
    if (fpid == 0) {
        union sigval value;
        int i = 0, ret = 0;

        pid = getppid();

        for (i = 1; i < 4; i++) {
            value.sival_int = i;

            // 给父进程发送信号, 3个非实时信号
            ret = sigqueue(pid, SIGINT, value);

            if (ret != 0) {
                printf("发送非实时信号失败\n");
            }
            printf("发送非实时信号成功\n");
        }

        for (i = 1; i < 4; i++) {
            value.sival_int = i;

            // 给父进程发送信号,3个非实时信号
            ret = sigqueue(pid, SIGRTMIN, value);

            if (ret != 0) {
                printf("发送实时信号失败\n");
            }
            printf("发送实时信号成功\n");
        }
        value.sival_int = 1942;

        //sigqueue(pid, SIGQUIT, value);
    }

    while (1) {
        pause();
    }

    return 0;
}

// 信号处理函数,当被阻塞时,不会调用此函数
void handle(int signum, siginfo_t *info, void *p)
{
    int num = 0;
    num = info->si_value.sival_int;

    if (signum == SIGINT) {
        printf("recv signal %d\n", signum);
        printf("recv value %d\n", num);
    }

    if (signum == SIGRTMIN) {
        printf("recv signal %d\n", signum);
        printf("recv value %d\n", num);
    }

    // 通过键盘发送SIGQUIT信号时,会执行下面的代码,作用:
    // 解除阻塞信号集,解除后,进程会执行上面两个if分支,非实时信号会丢失,三个丢失了两个
    // 实时信号没有丢失
    if (signum == SIGQUIT) {
        sigset_t uset;

        sigemptyset(&uset);
        sigaddset(&uset, SIGINT);
        sigaddset(&uset, SIGRTMIN);

        sigprocmask(SIG_UNBLOCK, &uset, NULL);
        printf("SIGINT and SIGRTMIN 已经解除阻塞\n");
    }
}

/*
    运行结果:
    [root@Mysql-dev signal]# ./sigaction 
    发送非实时信号成功
    发送非实时信号成功
    发送非实时信号成功
    发送实时信号成功
    发送实时信号成功
    发送实时信号成功


    ^\SIGINT and SIGRTMIN 已经解除阻塞
    recv signal 2
    recv value 1
    recv signal 34
    recv value 1
    recv signal 34
    recv value 2
    recv signal 34
    recv value 3
    SIGINT and SIGRTMIN 已经解除阻塞

    可以看到发送的时候,都是三个,解除阻塞接受的时候,只有实时信号没有被丢失,非实时信号丢失了两个
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值