概述
signal() 函数只能提供简单的信号安装操作,使用该函数处理信号比较简单,只要把要处理的信号和处理函数列出即可。signal() 函数主要用于从 Unix 继承过来的不可靠、非实时信号的处理,并且不支持信号传递信息。Linux 提供了功能更强大的 sigaction() 函数,此函数可以用来检查和更改信号处理操作,可以支持可靠、实时信号的处理,并且支持信号传递信息。
先看 kill() 的升级版:
#include <signal.h>
/* 功能:给指定进程发送信号 */
int sigqueue(pid_t pid, int sig, const union sigval value);
/* 参数:
pid: 进程号。
sig: 信号的编号,这里可以填数字编号,也可以填信号的宏定义,可以通过命令 kill -l ("l" 为字母)进行相应查看。
value: 通过信号传递的参数。
*/
union sigval
{
int sival_int;
void *sival_ptr;
};
/* 返回值:
0:成功
-1:失败
*/
在看 signal() 的升级版:
#include <signal.h>
/* 功能:检查或修改指定信号的设置(或同时执行这两种操作)。*/
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
/* 参数:
signum:要操作的信号。
act: 要设置的对信号的新处理方式(设置)。
oldact:原来对信号的处理方式(设置)。
如果 act 指针非空,则要改变指定信号的处理方式(设置),如果 oldact 指针非空,则系统将此前指定信号的处理方式(设置)存入 oldact。
*/
/* 现在 struct sigaction 被定义得比较复杂,简化一下如下: */
struct sigaction
{
/*旧的信号处理函数指针*/
void (*sa_handler)(int signum) ;
/*新的信号处理函数指针*/
void (*sa_sigaction)(int signum, siginfo_t *info, void *context);
/*信号阻塞集*/
sigset_t sa_mask;
/*信号处理的方式*/
int sa_flags;
/*这个暂时不用管*/
void (*sa_restorer) (void);
};
/*
sa_handler、sa_sigaction:信号处理函数指针,和 signal() 里的函数指针用法一样,应根据情况给 sa_sigaction、sa_handler 两者之一赋值,其取值如下:
SIG_IGN:忽略该信号
SIG_DFL:执行系统默认动作
处理函数名:自定义信号处理函数
信号处理函数定义为如下形式:
void (*sa_sigaction)( int signum, siginfo_t *info, void *context );
signum:信号的编号。
info:记录信号发送进程信息的结构体。
context:可以赋给指向 ucontext_t 类型的一个对象的指针,以引用在传递信号时被中断的接收进程或线程的上下文。
sa_mask:信号阻塞集
sa_flags:用于指定信号处理的行为,它可以是一下值的“按位或”组合:
SA_RESTART:使被信号打断的系统调用自动重新发起(已经废弃)
SA_NOCLDSTOP:使父进程在它的子进程暂停或继续运行时不会收到 SIGCHLD 信号。
SA_NOCLDWAIT:使父进程在它的子进程退出时不会收到 SIGCHLD 信号,这时子进程如果退出也不会成为僵尸进程。
SA_NODEFER:使对信号的屏蔽无效,即在信号处理函数执行期间仍能发出这个信号。
SA_RESETHAND:信号处理之后重新设置为默认的处理方式。
SA_SIGINFO:使用 sa_sigaction 成员而不是 sa_handler 作为信号处理函数。
*/
/* 返回值:
成功:0
失败:-1
*/
代码
/* study.cpp 发送程序 */
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
if(argc >= 2)
{
pid_t pid,pid_self;
union sigval tmp;
/* 将命令参数转化为进程号 */
pid = atoi(argv[1]);
/* 用命令参数作为传递值 */
tmp.sival_int = atoi(argv[2]);
/* 给进程 pid,发送 SIGINT 信号,并把 tmp 传递过去 */
sigqueue(pid, SIGINT, tmp);
pid_self = getpid();
printf("pid = %d, pid_self = %dn", pid, pid_self);
}
return 0;
}
/* main.c 接收程序 */
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
/* 信号处理回调函数 */
void signal_handler(int signum, siginfo_t *info, void *ptr)
{
printf("signum = %dn", signum);
/* 发送信号的进程的进程号 */
printf("info->si_pid = %dn", info->si_pid);
/* 对方传递过来的信息 */
printf("info->si_sigval = %dn", info->si_value.sival_int);
}
int main(int argc, char *argv[])
{
struct sigaction act, oact;
/* 指定信号处理回调函数 */
act.sa_sigaction = signal_handler;
/* 设置阻塞集为空 */
sigemptyset(&act.sa_mask);
/* 使用 sa_sigaction 成员而不是 sa_handler 作为信号处理函数。 */
act.sa_flags = SA_SIGINFO;
/* 注册信号 SIGINT */
sigaction(SIGINT, &act, &oact);
while(1)
{
printf("pid is %dn", getpid());
/* 捕获信号,此函数会阻塞 */
pause();
}
return 0;
}
先执行:
[lingyun@manjaro study]$ gcc main.c -o main
[lingyun@manjaro study]$ gcc study.cpp -o study
[lingyun@manjaro study]$ ./main
pid is 13758
再在另一个命令窗口执行:
[lingyun@manjaro study]$ ./study 13758 777
pid = 13758, pid_self = 13761
[lingyun@manjaro study]$ ./study 13758 7775
pid = 13758, pid_self = 13762
第一个命令窗口会得到一些信息,可见接受进程接收到了发送进程发送的信号以及一些信息,如 info->si_sigval. 另外,siginfo_t *info 这个结构体里面还有很多其他信息,可以看看。
[lingyun@manjaro study]$ gcc main.c -o main
[lingyun@manjaro study]$ gcc study.cpp -o study
[lingyun@manjaro study]$ ./main
pid is 13758
signum = 2
info->si_pid = 13761
info->si_sigval = 777
pid is 13758
signum = 2
info->si_pid = 13762
info->si_sigval = 7775
最后
以上就是无辜小甜瓜为你收集整理的可靠信号的用法的全部内容,希望文章能够帮你解决可靠信号的用法所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复