Linux进程间通信——信号

本文深入介绍了Linux系统中的信号概念,包括信号的定义、种类、处理函数(如signal和sigaction)以及信号发送函数等核心内容。同时,文章还提供了具体的代码示例帮助理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

.什么是信号

信号是进程在运行过程中,由自身产生或进程外部发过来的消息(事件)。

信号是一种软件中断,它提供了一种处理异步事件的方法,也是进程间唯一的异步通信方式。在Linux系统中,不仅可以用来通知某种程序发生了什么事件,还可以给进程传递数据。


.信号的种类

信号的名称是在头文件signal中定义的,信号都是以SIG开头。使用命令kill-l可以打印出信号列表。


















编号为131的信号为不可靠信号(非实时信号),编号3263的信号为可靠信号(实时信号)。不可靠信号和可靠信号的区别在于,不可靠信号不支持排队,可能会造成信号丢失,而可靠信号则不会。



.信号处理函数


linux中有有两个常用的信号处理函数singnalsigaction。有两个信号既不能被忽略也不能被捕捉,它们是SIGKILLSIGSTOP。即进程接收到这两个信号后,只能接受系统的默认处理,即终止进程。

signal不支持信号传递信息,主要用于前32种非实时信号的处理。

signal函数声明如下

#include<signal.h>
typedefvoid (*sighandler_t)(int);
sighandler_t signal(int signum,sighandler_t handler);


第一个参数是指定要处理的信号。第二个参数是个函数指针,用来对指定信号的处理。参数可以为SIG_IGN(忽略该信号)SIG_DFL(系统默认处理)和自定义处理函数(函数原型必须为voidfunc(int))。

一个简单的例子来展示一下signal的用法。





















运行结果如下

















按下ctrl+c后会产生一个SIGINT信号,而该信号的默认操作是终止进程,但是在用signal函数后,更改对SIGINT信号的处理为我们的自定义函数。这个程序中按下ctrl+c无法终止进程,不过其他信号的处理没有改变,可以按下ctrl+ \ 结束进程。


sigcation函数声明如下


#include<signal.h>

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

signal的第1个参数signum表示要捕捉的信号,第2个参数是个函数指针,表示要对该信号进行捕捉的函数,该参数也可以是SIG_DEF(表示交由系统缺省处理)SIG_IGN(表示忽略掉该信号而不做任何处理)signal如果调用成功,返回以前该信号的处理函数的地址,否则返回SIG_ERR
sighandler_t
是信号捕捉函数,由signal函数注册,注册以后,在整个进程运行过程中均有效,并且对不同的信号可以注册同一个信号捕捉函数。该函数只有一个参数,表示信号值。



sigaction函数原型

#include<signal.h>

intsigaction(int sig, const struct sigaction *act, struct sigaction*oldact);


结构体sigaction定义如下

struct sigaction{

void (*sa_handler)(int)

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

sigset_t sa_mask;

int sa_flag;

void (*sa_restore)(void);

}

sa_handler是一个函数指针,其含义与signal函数中的信号处理函数类似。

sa_sigaction则是另一个信号处理函数,它有三个参数,可以获得关于信号的更详细的信息。sa_flags成员的值包含了SA_SIGINFO标志时,系统将使用sa_sigaction函数作为信号处理函数,否则使用sa_handler作为信号处理函数。在某些系统中,成员sa_handlersa_sigaction被放在联合体中,因此使用时不要同时设置。

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

sa_flags成员用于指定信号处理的行为,它可以是一下值的“按位或”组合。
SA_RESTART
:使被信号打断的系统调用自动重新发起。
SA_NOCLDSTOP
:使父进程在它的子进程暂停或继续运行时不会收到SIGCHLD信号。
SA_NOCLDWAIT
:使父进程在它的子进程退出时不会收到SIGCHLD信号,这时子进程如果退出也不会成为僵尸进程。
SA_NODEFER
:使对信号的屏蔽无效,即在信号处理函数执行期间仍能发出这个信号。
SA_RESETHAND
:信号处理之后重新设置为默认的处理方式。
SA_SIGINFO
:使用sa_sigaction成员而不是sa_handler作为信号处理函数。

re_restorer成员则是一个已经废弃的数据域,不要使用。

一个简单的例子来展示一下signal的用法。




























运行结果




















.信号发送函数


1intraise(int sig); 对当前进程发送指定信号

2intpause(void);将进程挂起等待信号

3intkill(pid_t pid,int sig); 通过进程编号发送信号

4unsignedint alarm(unsigned int seconds); 指定时间(秒)发送SIGALRM信号。seconds0时取消所有已设置的alarm请求;

5intsigqueue(pid_t pid,int sig,const union sigval val);类似于kill函数,多了附带共用体unionsigval形数,将共用体中的成员intsival_intvoid*sival_ptr的值传递给信号处理函数中的定义类型siginfo_t中的intsi_intvoid*si_ptr

6intsetitimer(int which,const struct itimerval *value,struct itimerval*oldvalue); 可定时发送信号,根据which可指定三种信号类型:SIGALRMSIGVTALRMSIGPROF;作用时间也因which值不同而不同;structitimerval的成员it_interval定义间隔时间,it_value0时,使计时器失效;

7voidabort(void)将造成进程终止;除非捕获SIGABORT信号;  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值