(P21)信号:sigqueue函数、sigval函数、sigqueue示例

文章目录

    • 1.sigqueue函数
    • 2.sigval联合体

1.sigqueue函数

  • 功能:新的发送信号系统调用,主要是针对实时信号提出的支持信号带有参数,与sigaction()配合使用
    sigqueue可以将数据从一个进程发送给另一个进程;
    前2个参数与kill一样,只是它不能向进程组发送信号,pid只能是大于0的值,不能是负数;
int sigqueue(pid_t pid, int sig, const union sigval value);

参数:
第一个参数:指定接收信号的进程id
第二个参数:确定即将发送的信号
第三个信号:是一个联合数据结构union sigval,指定了信号传递的参数,即通常多说的4字节值

返回值:
成功返回0,失败返回-1

2.sigval联合体

  • sigqueue()比kill传递了更多的附加信息,但sigqueue()只能向一个进程发送信号,而不能发送信号给一个进程组
union sigval 
{
	 int   sival_int;//一个进程发送给另一个进程可以传递一个整数
	 void *sival_ptr;//一个进程发送给另一个进程可以传递一个指针
};
  • eg:sigqueue发送信号的时候,怎么传递数据?
    一个用来发送数据的进程,一个用来接收数据的进程
    P21sigqueue_recv.c
#include 
#include 
#include 
#include 

#include 
#include 
#include 
#include 
#include 


#define ERR_EXIT(m) \
    do \
    { \
        perror(m);
        exit(EXIT_FAILURE);
    } while(0)

void  handler(int, siginfo_t *, void *);

int main(int argc, char *argv[])
{
    struct sigaction act;
    //要想接收数据,得用sa_sigaction
    act.sa_sigaction = handler;
    sigemptyset(&act.sa_mask);
    act.sa_flags = SA_SIGINFO;//安装信号接收数据的时候,要用SA_SIGINFO!!否则,不能接收数据

    if (sigaction(SIGINT, &act, NULL) <0)
        ERR_EXIT("sigaction error\n");

    for (;;)
        pause();
    return 0;

}
void  handler(int sig, siginfo_t *info, void *ctx)
{
    //接收的数据在siginfo_t中的si_value中
    //si_value对应的就是联合体union sigval
    //man sigqueue
    //若是整型数据:数据接收还可以用这个字段info->si_int
    //若是指针数据,则用 info->si_ptr字段来接收
    printf("recv a sig = %d date=%d date=%d\n", sig, info->si_value.sival_int,info->si_int);
}

P21sigqueue_send.c

#include 
#include 
#include 
#include 

#include 
#include 
#include 
#include 
#include 


#define ERR_EXIT(m) \
    do \
    { \
        perror(m);
        exit(EXIT_FAILURE);
    } while(0)

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        fprintf(stderr, "Usage %s pid \n", argv[0]);
        exit(EXIT_FAILURE);
    }

    pid_t pid = atoi()argv[1];
    union sigval v;
    v.sival_int = 100;
    sigqueue(pid, SIGINT, v);

    return 0;
}
  • 测试:
    先运行接收的进程,再运行发送的进程
    在这里插入图片描述
    (P21)信号:sigqueue函数、sigval函数、sigqueue示例_第1张图片
    在这里插入图片描述
  • eg:模拟可靠信号支持排队,不可靠信号不支持排队
    P21recv.c
#include 
#include 
#include 
#include 

#include 
#include 
#include 
#include 
#include 


#define ERR_EXIT(m) \
    do \
    { \
        perror(m);
        exit(EXIT_FAILURE);
    } while(0)

void  handler(int);

int main(int argc, char *argv[])
{
    struct sigaction act;
    act.sa_handler = handler;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;

    //对这两个信号进行阻塞
    sigset_t s;
    sigemptyset(&s);
    sigaddset(&s, SIGINT);
    sigaddset(&s, SIGRTMIN);
    sigprocmask(SIG_BLOCK, &s, NULL);

    //安装一个不可靠信号
    if (sigaction(SIGINT, &act, NULL) <0)
        ERR_EXIT("sigaction error\n");

    //安装一个可靠信号
    if (sigaction(SIGRTMIN, &act, NULL) <0)
        ERR_EXIT("sigaction error\n");

    //用来解除阻塞的信号
    if (sigaction(SIGUSR1, &act, NULL) <0)
        ERR_EXIT("sigaction error\n");

    for (;;)
        pause();
    return 0;

}
void  handler(int sig)
{
    if (sig == SIGINT || sig == SIGRTMIN)
        printf("recv a sig = %d", sig);
    else if (sig == SIGUSR1)
    {
        //解除阻塞
        sigset_t s;
        sigemptyset(&s);
        sigaddset(&s, SIGINT);
        sigaddset(&s, SIGRTMIN);
        sigprocmask(SIG_UNBLOCK, &s, NULL);
    }
}

P21send.c

#include 
#include 
#include 
#include 

#include 
#include 
#include 
#include 
#include 


#define ERR_EXIT(m) \
    do \
    { \
        perror(m);
        exit(EXIT_FAILURE);
    } while(0)

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        fprintf(stderr, "Usage %s pid \n", argv[0]);
        exit(EXIT_FAILURE);
    }

    pid_t pid = atoi()argv[1];
    union sigval v;
    v.sival_int = 100;
    sigqueue(pid, SIGINT, v);
    sigqueue(pid, SIGINT, v);
    sigqueue(pid, SIGINT, v);
    sigqueue(pid, SIGRTMIN, v);
    sigqueue(pid, SIGRTMIN, v);
    sigqueue(pid, SIGRTMIN, v);
    sleep(3);
    kill(pid, SIGUSR1);//目的是:解除对SIGINT和SIGRTMIN信号的阻塞
    return 0;
}
  • 测试:
    在这里插入图片描述
    在这里插入图片描述
    说明43号可靠信号支持排队不会丢失,2号不可靠信号不支持排队,会丢失
    (P21)信号:sigqueue函数、sigval函数、sigqueue示例_第2张图片

  • Makefile

.PHONY:clean all
CC=gcc
CFLAGS=-Wall -g
BIN=01sigqueue_sen \
04sigaction_recv
all:$(BIN)
%.o:%.c
	$(CC) $(CFLAGS) -c $< -o $@
clean:
	rm -f *.o $(BIN)

你可能感兴趣的:(Linux高性能编程)