首页 > 代码库 > Linux环境编程之信号(一):信号基本概述

Linux环境编程之信号(一):信号基本概述

引言

假如在后台运行一个可执行程序./a.out,如果想终止该程序,通常会按下Ctrl-C,从而产生一个中断,其实这个过程的实现就是通过信号完成的。信号是软件中断,它提供了一种处理异步事件的方法。

(一)

每个信号都有一个名字,这些名字都以三个字符SIG开头。例如SIGALARM是闹钟信号,当由alarm函数设置的计时器超时后产生此信号。Linux除支持31种不同信号外,还支持应用程序额外定义信号。信号定义在<bits/signum.h>中,也可以通过命令kill -l查看。

(二)信号的产生

信号是如何产生的呢,下列方式均可产生信号:

1、当用户按某些终端键时,引发终端产生的信号。

2、硬件异常产生信号:除数为0、无效的内存引用等等。

3、进程调用kill(2)函数可将信号发送给另一个进程或进程组。

4、用户可用kill(1)命令将信号发送给其他进程。

5、当检测到某种软件条件已经发生,并应将其通知有关进程时也产生信号。

(三)信号的处理

进程不能简单地测试一个变量来判别是否出现了一个信号,而是必须告诉内核“在此信号出现时,请执行下列操作”。信号的处理包括三种方式:忽略信号、捕捉信号、执行系统默认动作。

注意:

1、大多数信号都可以使用忽略信号的方式进行处理,但对于SIGKILL和SIGSTOP信号则不能忽略,因为它们向超级用户提供了使进程终止或停止的可靠方法。

2、为了捕捉信号,要通知内核在某种信号发生时调用一个用户函数。SIGKILL和SIGSTOP信号不能被捕捉。

3、大多数信号的系统默认动作是终止进程。

(三)signal函数示例

信号机制最简单的接口就是signal函数。原型如下:

#include <signal.h>

void (*signal(int signo, void (*func)(int)))(int); 

signo是以SIG三个字母开头的信号名。func的值是常量SIG_IGN(忽略此信号)、常量SIG_DFL(系统默认动作)或当接到此信号后要调用的函数地址(信号发生时,调用该函数,即信号处理程序)。

/*
 *File Name:signal.c
 *Author   : libing
 *Mail     : libing1209@126.com
 */
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

static void sig_usr(int);

int
main(void)
{
	if(signal(SIGUSR1, sig_usr) == SIG_ERR)//signal函数
		printf("can‘t catch SIGUSR1");
	if(signal(SIGUSR2, sig_usr) == SIG_ERR)
		printf("can‘t catch SIGUSR2");
	for(;;)
		pause(); /*go to sleep, waiting for signal*/
	return 0;
}

static void
sig_usr(int signo)
{
	if(signo == SIGUSR1)
		printf("received SIGUSR1.\n");
	else if(signo == SIGUSR2)
		printf("received SIGUSR2.\n");
	else
		printf("received signal %d\n", signo);
}
程序测试:

编译:gcc signal.c -o signal
运行:./signal &
测试:kill -USR1 8522
kill -USR2 8522
kill 8522
注意:kill命令和kill函数只是将一个信号送给一个进程或进程组。信号是否终止进程则取决于信号的类型,以及进程是否安排了捕捉该信号。