一、sigqueue函数

功能:新的发送信号系统调用,主要是针对实时信号提出的支持信号带有参数,与函数sigaction()配合使用。
原型:int sigqueue(pid_t pid, int sig, const union sigval value);
参数:
 sigqueue的第一个参数是指定接收信号的进程id,第二个参数确定即将发送的信号,第三个参数是一个联合数据结构union sigval,指定了信号传递的参数,即通常所说的4字节值。
返回值:成功返回0,失败返回-1

typedef union sigval
 { 
int sival_int; 
void *sival_ptr; 
}sigval_t;

sigqueue()比kill()传递了更多的附加信息,但sigqueue()只能向一个进程发送信号,而不能发送信号给一个进程组。

写两个小程序测试一下:

首先是接收信号:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
 
/*************************************************************************
    > File Name: process_.c
    > Author: Simba
    > Mail: dameng34@163.com
    > Created Time: Sat 23 Feb 2013 02:34:02 PM CST
 ************************************************************************/
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<signal.h>

#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;
    act.sa_sigaction = handler; //sa_sigaction与sa_handler只能取其一
    //sa_sigaction多用于实时信号,可以保存信息
    sigemptyset(&act.sa_mask);
    act.sa_flags = SA_SIGINFO; // 设置标志位后可以接收其他进程
    // 发送的数据,保存在siginfo_t结构体中

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

for (; ;)
        pause();

return 0;

}

void handler(int sig, siginfo_t *info, void *ctx)
{
    printf("recv a sig=%d data=%d data=%d\n",
           sig, info->si_value.sival_int, info->si_int);

}

在前面的《信号捕捉与sigaction函数》中说过,sa_sigaction与SA_SIGINFO要配合使用,如上所示,siginfo_t 结构体也可以参见这篇文章。

然后是信号发送:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
 
/*************************************************************************
    > File Name: process_.c
    > Author: Simba
    > Mail: dameng34@163.com
    > Created Time: Sat 23 Feb 2013 02:34:02 PM CST
 ************************************************************************/
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<signal.h>

#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 val;
    val.sival_int = 100;
    sigqueue(pid, SIGINT, val); // 只可以发信号给某个进程,而不能是进程组

return 0;

}

测试如下:

先运行recv程序:

simba@ubuntu:~/Documents/code/linux_programming/APUE/signal$ ./sigqueue_recv

再ps出recv进程的pid,然后运行send程序:

simba@ubuntu:~/Documents/code/linux_programming/APUE/signal$ ./sigqueue_send 3323

则recv进程会输出一条recv语句,当然我们也可以ctrl+c 给自己发送信号,如下所示,结果是一样的。

recv a sig=2 data=100 data=100
^Crecv a sig=2 data=100 data=100
^Crecv a sig=2 data=100 data=100

......................................................

需要提醒一下的是siginfo_t 结构体的两个参数(int  si_int;   /* POSIX.1b signal */     void
 *si_ptr;  /* POSIX.1b signal */)的值也会与si_value 一致,取决于发送的是sival_int 还是 sival_ptr。

二、实时信号与不可靠信号的区别

下面通过程序来说明区别,主要就是实时信号支持排队不会丢失。(实时信号还有一个特点,即到达的顺序是可以保证的)

先是recv程序:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
 
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>

#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");

if (sigaction(SIGRTMIN, &act, NULL) < 0)
        ERR_EXIT("sigaction error");

if (sigaction(SIGUSR1, &act, NULL) < 0)
        ERR_EXIT("sigaction error");
    for (;;)
        pause();
    return 0;
}

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

在主函数中将SIGINT和SIGRTMIN信号加入信号屏蔽字,只有当接收到SIGUSR1信号时才对前面两个信号unblock。需要注意的是如《信号的未决与阻塞》中说的一样:如果在信号处理函数中对某个信号进行解除阻塞时,则只是将pending位清0,让此信号递达一次(同个实时信号产生多次进行排队都会抵达),但不会将block位清0,即再次产生此信号时还是会被阻塞,处于未决状态。

接着是send程序:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
 
/*************************************************************************
    > File Name: sigrtime_send.c
    > Author: Simba
    > Mail: dameng34@163.com
    > Created Time: Sat 23 Feb 2013 02:34:02 PM CST
 ************************************************************************/
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<signal.h>

#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 val;
    val.sival_int = 100;
    sigqueue(pid, SIGINT, val); // 不可靠信号不会排队,即会丢失
    sigqueue(pid, SIGINT, val);
    sigqueue(pid, SIGINT, val);
    sigqueue(pid, SIGRTMIN, val); //实时信号会排队,即不会丢失
    sigqueue(pid, SIGRTMIN, val);
    sigqueue(pid, SIGRTMIN, val);
    sleep(3);
    kill(pid, SIGUSR1);

return 0;

}

先是运行recv程序:

simba@ubuntu:~/Documents/code/linux_programming/APUE/signal$ ./sigrtime_recv2

接着ps出recv进程的pid,运行send程序:

simba@ubuntu:~/Documents/code/linux_programming/APUE/signal$ ./sigrtime_send 4076

在send程序中连续各发送了SIGINT和SIGRTMIN信号3次,接着睡眠3s后使用kill函数发送SIGUSR1信号给recv进程,此时recv进程会输出如下:

recv a sig=34
recv a sig=34
recv a sig=34
recv a sig=2

即实时信号支持排队,3个信号都接收到了,而不可靠信号不支持排队,只保留一个信号。

参考:《APUE》

实时信号与sigqueue函数的更多相关文章

  1. sigaction和实时信号sigqueue

    sigaction函数sigaction函数的功能是用于改变进程接收到特定信号后的行为.int sigaction(int signum, const struct sigaction *act,st ...

  2. 信号发送接收函数:sigqueue/sigaction

    信号是一种古老的进程间通信方式,下面的例子利用sigqueue发送信号并附带数据:sigaction函数接受信号并且处理时接受数据. 1.sigqueue: 新的信号发送函数,比kill()函数传递了 ...

  3. 一款DMA性能优化记录:异步传输和指定实时信号做async IO

    关键词:DMA.sync.async.SIGIO.F_SETSIG. DMA本身用于减轻CPU负担,进行CPU off-load搬运工作. 在DMA驱动内部实现有同步和异步模式,异步模式使用dma_a ...

  4. Qt之自定义信号和槽函数

    自定义信号和槽函数: 1.类的声明和实现分别放在.h和.cpp文件中: 2.类声明包含Q_OBJECT宏: 3.信号只要声明不要设计其的实现函数 4.发射信号用emit关键字 5.自定义槽的实现与普通 ...

  5. 信号之sigsuspend函数

    更改进程的信号屏蔽字可以阻塞所选择的信号,或解除对它们的阻塞.使用这种技术可以保护不希望由信号中断的代码临界区.如果希望对一个信号解除阻塞,然后pause等待以前被阻塞的信号发生,则又将如何呢?假定信 ...

  6. qt的信号与槽函数

    关联: bool connect ( const?QObject?*?sender, const?char?*?signal, const QObject * receiver, const char ...

  7. Linux 信号signal处理函数

    转自:http://www.cnblogs.com/taobataoma/archive/2007/08/30/875662.html alarm(设置信号传送闹钟) 相关函数 signal,slee ...

  8. 【QT】无需写connect代码关联信号和槽函数

    对于一些简单的事件判别,如点击按钮. 无需写代码关联信号和槽函数. connect(ui->Btnshowhello,SIGNAL(clicked(bool)),this,SLOT(Btnsho ...

  9. Linux 信号signal处理函数--转

    alarm(设置信号传送闹钟)相关函数 signal,sleep 表头文件 #include<unistd.h> 定义函数 unsigned int alarm(unsigned int ...

随机推荐

  1. 如何在Windows 7 或Vista中修改MTU

    Windows操作系统使用Maximum Transmission Unit (MTU) 来确定在下面的网络层上可以传输的协议数据包(protocol data packet)的最大尺寸. MTU参数 ...

  2. IE6与CSS样式兼容问题汇总

    1.PNG半透明图片的问题 虽然可以通过JS等方式解决,但依然存在载入速度等问题,所以,这个上能不要用还是尽量不要用.以达到网站最大优化. 2.IE6下的圆角 IE6不支持CSS3的圆角属性,比较好的 ...

  3. 让ie6(opera)支持微软雅黑字体

    一.让IE6支持微软雅黑,添加一句声明: <html  lang="zh-CN"> 在网页的HTML标签内加入红色部分的声明,就可以了. 二.让Opera浏览器支持微软 ...

  4. c#写扩展方法

    学习MVC时,学会了写扩展方法,用起来很方便. 01 using System; 02 using System.Collections.Generic; 03 using System.Linq; ...

  5. Java基础(九):抽象类

    在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类. 抽象类除了不能实例化对象之外, ...

  6. jquery获得select option的值和对select option的操作

    <body> <select name="month" id="selMonth" onchange="set()"> ...

  7. 【Python】Django数据模型、级联删除、级联更新、ER图导出等

    在本文中,我们将向读者详细介绍如何在更新和删除父表数据的同时,触发有关子表数据的级联更新和删除操作.您将看到当使用InnoDB表的时候,借助于外键约束就可以轻松搞定这一过程. 一.利用外键约束更新并删 ...

  8. Java8新特性之重复注解(repeating annotations)浅析

    Java8新特性之重复注解(repeating annotations)浅析 学习了:https://www.jb51.net/article/50827.htm

  9. 2014年ENVI/IDL遥感应用与开发培训班-11月重庆站 開始报名了

    主办单位: 中国遥感应用协会 Esri中国信息技术有限公司 内容简单介绍: 依据中国遥感应用协会栾恩杰理事长推动国内遥感技术和应用的指示精神,2014年中国遥感应用协会组织培训交流部与Esri中国信息 ...

  10. vb sendmessage 详解2

    首先我们了解一下Windows的消息机制.Windows是一个消息驱动式系统,Windows消息提供应用程序与应用程序之间,应用程序与Windows系统之间进行通信的手段.举个例子,打开记事本程序,该 ...