四川卫生信息学会年会:sigqueue

来源:百度文库 编辑:偶看新闻 时间:2024/05/02 11:32:36
 

sigqueue函数 进程间通信 信号的发送携带数据

2011-04-10 23:37 450人阅读 评论(0) 收藏 举报

今天只看SIGQUEUE函数:声明:其中有部分

http://www.bccn.net/Article/kfyy/vc/jszl/200708/5849.html(编程中国)的摘抄:

3、sigqueue()
#include
#include
int sigqueue(pid_t pid, int sig, const union sigval val)
调用成功返回 0;否则,返回 -1。

sigqueue()是比较新的发送信号系统调用,主要是针对实时信号提出的(当然也支持前32种),支持信号带有参数,与函数sigaction()配合使用。

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

 


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

sigqueue()比kill()传递了更多的附加信息,但sigqueue()只能向一个进程发送信号,而不能发送信号给一个进程组。如果 signo=0,将会执行错误检查,但实际上不发送任何信号,0值信号可用于检查pid的有效性以及当前进程是否有权限向目标进程发送信号。

在调用sigqueue时,sigval_t指定的信息会拷贝到3参数信号处理函数(3参数信号处理函数指的是信号处理函数由sigaction安 装,并设定了sa_sigaction指针,稍后将阐述)的siginfo_t结构中,这样信号处理函数就可以处理这些信息了。由于sigqueue系统 调用支持发送带参数信号,所以比kill()系统调用的功能要灵活和强大得多。

注:sigqueue()发送非实时信号时,第三个参数包含的信息仍然能够传递给信号处理函数; sigqueue()发送非实时信号时,仍然不支持排队,即在信号处理函数执行过程中到来的所有相同信号,都被合并为一个信号。

***************************************************************************************************************************

根据以上对SIGQUEUE函数的讲解,

在调用sigqueue时,sigval_t指定的信息会拷贝到3参数信号处理函数(3参数信号处理函数指的是信号处理函数由sigaction安装,并 设定了sa_sigaction指针,稍后将阐述)的siginfo_t结构中,这样信号处理函数就可以处理这些信息了。由于sigqueue系统调用支 持发送带参数信号

 

这一部分较难理解:

SIGQUEUE函数的第三个参数是拷贝到SIGQUEUE函数中的,这里有一个3参数SIGQUEUE函数,以下是关于SIGACTION函数此方面的详解:

***********************************************SIGACTION*************************************************************

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

sigaction函数用于改变进程接收到特定信号后的行为。该函数的第一个参数为信号的值,可以为除SIGKILL及SIGSTOP外的任何一个 特定有效的信号(为这两个信号定义自己的处理函数,将导致信号安装错误)。第二个参数是指向结构sigaction的一个实例的指针,在结构 sigaction的实例中,指定了对特定信号的处理,可以为空,进程会以缺省方式对信号处理;第三个参数oldact指向的对象用来保存原来对相应信号 的处理,可指定oldact为NULL。如果把第二、第三个参数都设为NULL,那么该函数可用于检查信号的有效性。

第二个参数最为重要,其中包含了对指定信号的处理、信号所传递的信息、信号处理函数执行过程中应屏蔽掉

sigaction的结构形态如下:
struct sigaction {
    void (*sa_handler)(int);
    void (*sa_sigaction)(int, siginfo_t *, void *);
    sigset_t sa_mask;
    int sa_flags;
    void (*sa_restorer)(void);
}

参数:

在一些体系上,sa_handler和sa_sigaction共用一个联合体(union),所以不要同时指定两个字段的值。

sa_restorer字段已淘汰,不应该再被使用。

sa_handler字段指定与signum信号关联的行为,可能是SIG_DFL默认行为,SIG_IGN忽略接送到的信号,或者一个信号处理函数指针。这个函数以一个信号编码作为它的唯一参数 。

如果sa_flags中存在SA_SIGINFO标志,那么sa_sigaction将作为signum信号的处理函数。这个函数的第一参数是信号编码,第二参数是siginfo_t结构的指针,第三参数是ucontext_t结构指针(造型为void *)。

sa_mask指定信号处理函数执行的过程中应被阻塞的信号。另外,除了SA_NODEFER标志被指定外,触发信号处理函数执行的那个信号也会被阻塞。

sa_flags指定一系列用于修改信号处理过程行为的标志,由下面的0个或多个标志通过or运算组合而成:
 SA_NOCLDSTOP //此标志为on时,假如signum的值是SIGCHLD,则在子进程停止或恢复执行时不会传信号给调用本系统调用的进程。
 SA_NOCLDWAIT //此标志为on时,当调用此系统调用的进程之子进程终止时,系统不会建立zombie进程。
 SA_RESETHAND //此标志为on时,信号处理函数接收到信号后,会先将对信号处理的方式设为预设方式,而且当函数处理该信号时,后来发生的信号将不会被阻塞。
 SA_ONSTACK //如果利用sigaltstack()建立信号专用堆栈,则此标志会把所有信号送往该堆栈。
 SA_RESTART //此标志为on时,核心会自动重启信号中断的系统调用,否则返回EINTR错误值。
 SA_NODEFER //当此标志为on时,在信号处理函数处置信号的时段中,核心程序不会把这个间隙中产生的信号阻塞。
 SA_SIGINFO //此标志为on时,指定信号处理函数需要三个参数,所以应使用sa_sigaction替代sa_handler。

 

看看头文件:

#define SA_SIGINFO    4          /* Invoke signal-catching function with
 57                                     three arguments instead of one.  */

这是头文件中对SA-SIGINFO的描述****************************************************************

好啦,到目前我们捋捋思路:

函数sigaction()的第二个参数指向一个struct sigaction结构的指针,这个结构中有两个函数指针

void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);

他们都可以作为信号处理函数,使用那一个就要看SA-FLAGS是否标志位SA-SIGINFO,标志啦,就用sa_sigaction指针指向的函数,没有标志,就使用sa_handler指向的函数。

由_sa_handler指定的处理函数只有一个参数,即信号值,所以信号不能传递除信号值之外的任何信息;由_sa_sigaction是指定的信号处 理函数带有三个参数,是为实时信号而设的(当然同样支持非实时信号),它指定一个3参数信号处理函数。第一个参数为信号值,第三个参数没有使用 (posix没有规范使用该参数的标准),第二个参数是指向siginfo_t结构的指针,结构中包含信号携带的数据值,参数所指向的结构如下:

sa_sigaction第二个参数siginfo_t结构的原型如下:

siginfo_t {
    int      si_signo;  /* Signal number */
    int      si_errno;  /* An errno value */
    int      si_code;   /* Signal code */
    pid_t    si_pid;    /* Sending process ID */
    uid_t    si_uid;    /* Real user ID of sending process */
    int      si_status; /* Exit value or signal */
    clock_t  si_utime;  /* User time consumed */
    clock_t  si_stime;  /* System time consumed */
    sigval_t si_value;  /* Signal value */ 
    int      si_int;    /* POSIX.1b signal */
    void *   si_ptr;    /* POSIX.1b signal */
    void *   si_addr;   /* Memory location which caused fault */
    int      si_band;   /* Band event */
    int      si_fd;     /* File descriptor */
}

看见加黑的结构体没有,这个才是我们今天尧讨论的

他的定义和sigval这个结构定义在一个头文件中

下面是sigval的结构体定义:

/* Type for data associated with a signal.  */
 33 typedef union sigval
 34   {
 35     int sival_int;
 36     void *sival_ptr;
 37   } sigval_t;

采用联合数据结构,说明siginfo_t结构中的si_value要么持有一个4字节的整数值,要么持有一个指针,这就构成了与信号相关的数据。在信号 的处理函数中,包含这样的信号相关数据指针,但没有规定具体如何对这些数据进行操作,操作方法应该由程序开发人员根据具体任务事先约定。

************************************************SIGACTION***************************************************************

现在回到SIGQUEUE函数:

在调用sigqueue时,sigval_t指定的信息会拷贝到3参数信号处理函数(3参数信号处理函数指的是信号处理函数由sigaction安装,并 设定了sa_sigaction指针)的siginfo_t结构中,这样信号处理函数就可以处理这些信息了。由于sigqueue系统调用支 持发送带参数信号,所以比kill()系统调用的功能要灵活和强大得多。

现在就好理解这段话啦!!!