Linux编程基础之进程间通信之三:信号

一、信号的概述

信号是UNIX 中所使用的进程通信的一种最古老的方法。。它是在软件层次上对中断机制的一种模拟,是一种异步通信方式。信号可以直接进行用户空间进程和内核进程之间的交互,内核进程也可以利用它来通知用户空间进程发生了哪些系统事件。它可以在任何时候发给某一进程,而无需知道该进程的状态。如果该进程当前并未处于执行态,则该信号就由内核保存起来,直到该进程恢复执行再传递给它为止;如果一个信号被进程设置为阻塞,则该信号的传递被延迟,直到其阻塞被取消时才被传递给进程。

一个完整的信号生命周期可以分为3 个重要阶段,这3 个阶段由4 个重要事件来刻画的:信号产生、信号在进程中注册、信号在进程中注销、执行信号处理函数,如下图所示:


用户进程对信号的响应有三种方式:

  • 忽略信号,即对信号不做任何处理,但是有两个信号不能忽略,即SIGKILL 及SIGSTOP。
  • 捕捉信号,定义信号处理函数,当信号发生时,执行相应的自定义处理函数。
  • 执行缺省操作,Linux 对每种信号都规定了默认操作。
linux信号大多数是有内核提供的,下面列出了常见信号的含义和默认操作:



二、信号处理

信号处理的主要方法有两种,一种是使用简单的signal()函数,另一种是使用信号集函数组。下面分别介绍这两种处理方式。

1、使用signal()函数

使用signal()函数处理时,只需要指出要处理的信号和处理函数即可。它主要是用于前32 种非实时信号的处理,不支持信号传递信息,但是由于使用简单、易于理解,因此也受到很多程序员的欢迎。Linux 还支持一个更健壮、更新的信号处理函数sigaction(),推荐使用该函数。

函数格式:

void (*signal(int signum, void (*handler)(int)))(int)
        signum : 指定信号代码

        handler:信号处理函数,可以是SIG_IGN、SIG_DFL、用户自定义

2、使用sigaction()函数

函数格式:

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
        signum :信号代码,可以为除SIGKILL 及SIGSTOP 外的任何一个特定有效的信号

        act:指向结构sigaction 的一个实例的指针,指定对特定信号的处理

  oldact:保存原来对相应信号的处理

        返回值:0成功,其他返回错误代码

三、测试

分别对上述两种方式实现的信号处理进行测试。他们实现的功能都是一样的,编写一个信号处理函数用来捕捉用户输入的SIGINT信号(Ctrl + C)。

1、使用signal()函数

完整测试代码如下:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

/* 自定义的信号处理函数 */
void my_signal_func(int signum)
{
	if(signum == SIGINT)
	{
		printf("Captured the signal is SIGINT!\n");
	}
	else
	{
		printf("Cptured error!\n");
	}
}

/*
 *	功能 : 捕捉SIGINT信号
 */
int main(void)
{
	printf("Capture SIGINT signal!\n");

	/* 捕捉相应的信号 */
	signal(SIGINT, my_signal_func);

	/* wait a signal */
	pause();

	return 0;
}
编译并运行,结果如下:


2、使用sigaction()函数

完整的代码如下所示:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

#if 0
struct sigaction {
   void     (*sa_handler)(int);
   void     (*sa_sigaction)(int, siginfo_t *, void *);
   sigset_t   sa_mask;
   int        sa_flags;
   void     (*sa_restorer)(void);
};
#endif

/* 信号处理函数 */
static void my_signal_func(int signum)
{
	if(signum == SIGINT)
	{
		printf("Captured the signal SIGINT!\n");
	}
	else
	{
		printf("Captured error!\n");
	}
}

/*
 *	功能 : 捕捉信号SIGINT
 */
int main(void)
{
	int ret;
	struct sigaction my_sigaction;

	printf("Capture the siganl SIGINT!\n");

	/* 设置my_sigaction结构体 */
	my_sigaction.sa_handler = my_signal_func;
	sigemptyset(&my_sigaction.sa_mask);
	my_sigaction.sa_flags = 0;

	/* 将相应的信号与信号处理函数绑定起来 */
	ret = sigaction(SIGINT, &my_sigaction, 0);

	pause();	// wait for signal
	
	return 0;
}
编译并运行结果如下所示:



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值