C++使用sigaction实战

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chengqiuming/article/details/88934534

一 点睛

sigaction:查询或设置信号处理方式

头文件 

#include<signal.h>

定义函数 

int sigaction(int signum,const struct sigaction *act ,struct sigaction *oldact);

函数说明 

sigaction()会依参数signum指定的信号编号来设置该信号的处理函数。参数signum可以指定SIGKILL和SIGSTOP以外的所有信号。

结构sigaction定义如下

struct sigaction
{
    void (*sa_handler) (int);
    sigset_t sa_mask;
    int sa_flags;
    void (*sa_restorer) (void);
}

sa_handler:是一个函数指针,指向一个信号处理函数。

sa_mask:用来指定信号处理函数执行期间需要被屏蔽的信号,特别是当某个信号被处理时,它自身会自动放入进程的信号掩码,因此在信号处理函数执行期间,这个信号不会再度发生。

sa_restorer:此参数没有使用。

sa_flags:用来设置信号处理的其他相关操作,下列的数值可用。OR 运算(|)组合。

SA_NOCLDSTOP : 使父进程在它的子进程暂停或继续运行时不会收到SIGCHLD信号。

SA_RESTART:被信号中断的系统调用会自行重启

SA_NODEFER:在运行信号的处理函数时再次收到当前的信号,也会触发新处理函数调用。

返回值 

执行成功则返回0,如果有错误则返回-1。

错误代码 

EINVAL:参数signum 不合法, 或是企图拦截SIGKILL/SIGSTOPSIGKILL信号

EFAULT:参数act,oldact指针地址无法存取。

EINTR:此调用被中断

二 实战一——系统调用sigaction函数的简单使用

1 代码

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

static void sig_usr(int signum)
{
    if (signum == SIGUSR1)
    {
        printf("SIGUSR1 received\n");
    }
    else if (signum == SIGUSR2)
    {
        printf("SIGUSR2 received\n");
    }
    else
    {
        printf("signal %d received\n", signum);
    }
}

int main(void)
{
    char buf[512];
    int  n;
    struct sigaction sa_usr;
    sa_usr.sa_flags = 0;
    sa_usr.sa_handler = sig_usr;   //信号处理函数
    
    sigaction(SIGUSR1, &sa_usr, NULL);
    sigaction(SIGUSR2, &sa_usr, NULL);
    
    printf("My PID is %d\n", getpid());
    
    while (1)
    {
        if ((n = read(STDIN_FILENO, buf, 511)) == -1)
        {
            if (errno == EINTR)
            {
                printf("read is interrupted by signal\n");
            }
        }
        else
        {
            buf[n] = '\0';
            printf("%d bytes read: %s\n", n, buf);
        }
    }
    
    return 0;
}

2 第一个终端运行

[root@localhost test]# g++ -o test test.cpp
[root@localhost test]# ./test
My PID is 1939

3 第二个终端运行

[root@localhost ~]# kill -USR1 1939

4 第一个终端结果

SIGUSR1 received
read is interrupted by signal

三 实战二——sa_flags的简单使用

1 代码

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

static void sig_usr(int signum)
{
    if (signum == SIGUSR1)
    {
        printf("SIGUSR1 received\n");
    }
    else if (signum == SIGUSR2)
    {
        printf("SIGUSR2 received\n");
    }
    else
    {
        printf("signal %d received\n", signum);
    }
}

int main(void)
{
    char buf[512];
    int  n;
    struct sigaction sa_usr;
    sa_usr.sa_flags = 0;
    sa_usr.sa_handler = sig_usr;   //信号处理函数
    sa_usr.sa_flags=SA_RESTART;
    
    sigaction(SIGUSR1, &sa_usr, NULL);
    sigaction(SIGUSR2, &sa_usr, NULL);
    
    printf("My PID is %d\n", getpid());
    
    while (1)
    {
        if ((n = read(STDIN_FILENO, buf, 511)) == -1)
        {
            if (errno == EINTR)
            {
                printf("read is interrupted by signal\n");
            }
        }
        else
        {
            buf[n] = '\0';
            printf("%d bytes read: %s\n", n, buf);
        }
    }
    
    return 0;
}

2 第一个终端运行

[root@localhost test]# g++ -o test test.cpp
[root@localhost test]# ./test
My PID is 2087

3 第二个终端运行

[root@localhost ~]# kill -USR1 2087

4 第一个终端结果

SIGUSR1 received

5 比较

比较这两个例子的结果,体会sa_usr.sa_flags=SA_RESTART;的含义。

SA_RESTART:被信号中断的系统调用会自行重启,因此没有read is interrupted by signal打印。

猜你喜欢

转载自blog.csdn.net/chengqiuming/article/details/88934534