Linux可靠/不可靠信号编程实践

综合案例

1) 创建子进程与父进程;

2) 注册SIGINT非实时信号与SIGRTMIN实时信号,并将这两种信号添加到进程屏蔽信号组中;

3) 注册用户自定义信号;

4) 子进程发送5次非实时信号,发5次实时信号;

5) 然后子进程发送SIGUSR1解除进程对SIGINT,SIGTRMIN信号的阻塞

6) 观察实时信号与非实时信号的区别

//程序示例
void onSigAction(int signalNumber, siginfo_t *sigInfoStruct, void *)
{
    //获取接收到的数据
    int receiveNumber = sigInfoStruct->si_int;

    //如果收到的是SIGUSR1信号,则解除对SIGINT,SIGRTMIN的屏蔽
    if (signalNumber == SIGUSR1)
    {
        sigset_t unblockSet;
        sigemptyset(&unblockSet);
        sigaddset(&unblockSet,SIGINT);
        sigaddset(&unblockSet,SIGRTMIN);;
        sigprocmask(SIG_UNBLOCK,&unblockSet,NULL);

        //Value值会是乱码!
        //cout << "Receive SIGUSR1, Value = " << receiveNumber << endl;
        cout << "Unblock, Receive SIGUSR1" << endl;
    }
    else if (signalNumber == SIGINT)
    {
        cout << "Receive SIGINT, Value = " << receiveNumber << endl;
    }
    else if (signalNumber == SIGRTMIN)
    {
        cout << "Receive SIGRTMIN, Value = " << receiveNumber << endl;
    }
}

//错误退出函数
inline void err_exit(string str);

int main()
{
    struct sigaction act;
    //如果需要使得信号处理程序接收额外数据,
    //则必须将sa_flags位置为SA_SIGINFO
    act.sa_flags = SA_SIGINFO;
    sigemptyset(&act.sa_mask);
    act.sa_sigaction = onSigAction;

    //注册信号处理函数
    if (sigaction(SIGINT,&act,NULL) < 0)
        err_exit("sigaction SIGINT");
    if (sigaction(SIGRTMIN,&act,NULL) < 0)
        err_exit("sigaction SIGRTMIN");
    if (sigaction(SIGUSR1,&act,NULL) < 0)
        err_exit("sigaction SIGUSR1");

    //将信号SIGINT,SIGRTMIN信号阻塞
    sigset_t blockSet;
    sigemptyset(&blockSet);
    sigaddset(&blockSet,SIGINT);
    sigaddset(&blockSet,SIGRTMIN);
    if (sigprocmask(SIG_BLOCK,&blockSet,NULL) < 0)
        err_exit("sigprocmask error");

    pid_t pid = fork();
    if (pid == -1)
        err_exit("fork error");
    else if (pid == 0)
    {
        union sigval Value;
        Value.sival_int = 200;

        //给父进程发送五次带额外数据的非可靠信号(其实最终只接受到了一次)
        for (int i = 0; i < 5; ++i)
        {
            ++ Value.sival_int;
            if (sigqueue(getppid(),SIGINT,Value) != 0)
                err_exit("sigqueue error");
        }

        //给父进程发送五次带额外数据的可靠信号(最终接收到了五次!!!)
        Value.sival_int = 0;
        for (int i = 0; i < 5; ++i)
        {
            ++ Value.sival_int;
            if (sigqueue(getppid(),SIGRTMIN,Value) != 0)
                err_exit("sigqueue error");
        }

        //给父进程发送SIGUSR1信号,解除对SIGINT,SIGRTMIN信号的阻塞
        kill(getppid(),SIGUSR1);
    }

    while (true)
    {
        pause();
    }
}

void err_exit(string str)
{
    perror(str.c_str());
    exit(EXIT_FAILURE);
}

运行结果:

其实只是收到了一份非可靠信号SIGINT!

附-查看系统限制命令:ulimit

[email protected]:~$ ulimit -a
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 47131
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 47131
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
时间: 2024-10-22 12:59:22

Linux可靠/不可靠信号编程实践的相关文章

[学习笔记]可靠信号与不可靠信号编程实践

可靠信号.不可靠性信号的观察 综合案例 1.  创建子进程和父进程 2.  注册SIGINT非实时信号  SIGRTMIN 实时信号 添加到到进程阻塞中 3.  注册用户自定义信号SIGUSR1 4.  子进程发送3次非实时信号,发3次实时信号 5.  子进程发送 SIGUSR1解除信号阻塞: 6.  观察实时信号和非实时信号的表现与区别! 7. man手册sigaction中 struct sigaction { void (*sa_handler)(int); void (*sa_sigac

Linux shell一行流编程实践

Linux下很多命令用起来真相当方便,尤其是进行批处理操作时.(话说感觉这种程序也不复杂,windows咋一直不搞一个好用的shell呢) 这里列出一些常用shell操作的应用,具体命令的用法与解释就不列了,网上有很多很好的教程. 批量重命名 假如当前目录下有若干.wma文件,我希望把它们批量转成.mp3文件 例: 001.wma -> 001.mp3 解决方案: awk ? 1 ls * | awk -F '.' '{print "mv "$0" "$1&q

linux应用开发-信号编程

linux应用开发-信号编程 一 信号用于进程间通信 信号定义在/usr/include/asm/signal.h下 常见的信号有: SIGKILL杀死进程 SIGSTOP暂停进程 SIGCHLD子进程停止或者结束时通知父进程 二 相关的函数 发送信号 函数名    kill 函数原形  int kill(pid_t pid, int sig) 函数功能  向任何的进程和进程组发送信号 所属头文件 #include <sys/types.h> #include <signal.h>

Linux下的socket编程实践(四)TCP服务端优化和常见函数

并发下的僵尸进程处理 只有一个进程连接的时候,我们可以使用以下两种方法处理僵尸进程: 1)通过忽略SIGCHLD信号,避免僵尸进程 在server端代码中添加 signal(SIGCHLD, SIG_IGN); 2)通过wait/waitpid方法,解决僵尸进程 signal(SIGCHLD,onSignalCatch); void onSignalCatch(int signalNumber) { wait(NULL); } 那么如果是多进程状态下多个客户端同时关闭呢? 我们可以用下面的客户端

linux系统socket通信编程实践

简单介绍并实现了基于UDP(TCP)的windows(UNIX下流程基本一致)下的服务端和客户端的程序,本文继续探讨关于UDP编程的一些细节. 下图是一个简单的UDP客户/服务器模型: .imageplus-append-lu-img-txt { overflow: hidden; margin: 10px 0 } .imageplus-append-nova-txt { border: 1px solid #f2f2f2; font-family: Microsoft YaHei; line-

Linux下的socket编程实践(八) Select的限制和poll(并发的初步知识)

select的限制 用select实现的并发服务器,能达到的并发数一般受两方面限制: 1)一个进程能打开的最大文件描述符限制.这可以通过调整内核参数来改变.可以通过ulimit -n(number)来调整或者使用setrlimit函数设置(需要root权限),但一个系统所能打开的最大数也是有限的,跟内存大小有关,可以通过cat /proc/sys/fs/file-max 查看. 2)select中的fd_set集合容量的限制(FD_SETSIZE,一般为1024),这需要重新编译内核才能改变.

Linux下的socket编程实践(十) 基本UDP编程细节

在我的这两篇博客中,简单介绍并实现了基于UDP(TCP)的windows(UNIX下流程基本一致)下的服务端和客户端的程序,本文继续探讨关于UDP编程的一些细节. http://blog.csdn.net/nk_test/article/details/47733307 http://blog.csdn.net/nk_test/article/details/47756381 下图是一个简单的UDP客户/服务器模型: 我在这里也实现了一个简单的UDP回射服务器/客户端: /**实践: 实现一个基

Linux下的socket编程实践(三)端口复用和 P2P多进程服务器

Socket端口复用 先说为什么要使用socket端口复用?如果你遇到过这样的问题:server程序重启之后,无法连接,需要过一段时间才能连接上? 1.一个监听(listen)server已经启动 2.当有client有连接请求的时候,server产生一个子进程去处理该client的事物. 3.server主进程终止了,但是子进程还在占用该连接处理client的事情.虽然子进程终止了,但是由于子进程没有终止,该socket的引用计数不会为0,所以该socket不会被关闭. 4.server程序重

Linux下的socket编程实践(一) 网络基本知识以及 TCP/IP简述

ISO/OSI七层参考模型 1.物理层:主要定义物理设备标准,如网线的接口类型.光纤的接口类型.各种传输介质的传输速率等.它的主要作用是传输比特流(就是由1.0转化为电流强弱来进行传输,到达目的地后再转化为1.0,也就是我们常说的数模转换与模数转换).这一层的数据叫做比特.(标志:RJ-45) 2.数据链路层:定义了如何让格式化数据以进行传输,以及如何让控制对物理介质的访问.这一层通常还提供错误检测和纠正,以确保数据的可靠传输,交换机属于本层. 3.网络层:在位于不同地理位置的网络中的两个主机系