概念:
- 信号是在软件层次上对中断机制的一种模拟,是一种异步通信方式
- 信号可以直接进行用户空间进程和内核进程之间的交互,内核进程也可以利用它来通知用户空间进程发生了哪些系统事件。
- 如果该进程当前并未处于执行态,则该信号就由内核保存起来,直到该进程恢复执行再传递给它;如果一个信号被进程设置为阻塞,则该信号的传递被延迟,直到其阻塞被 取消时才被传递给进程。
用户进程对信号的响应方式:
- 忽略信号:对信号不做任何处理,但是有两个信号不能忽略:即SIGKILL及SIGSTOP。
- 捕捉信号:定义信号处理函数,当信号发生时,执行相应的处理函数。
- 执行缺省操作:Linux对每种信号都规定了默认操作
signal
设置信号处理方式
1
2
3
| #include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
|
参数说明:
返回值:
- 成功:返回先前的信号处理函数指针
- 失败:SIG_ERR(-1)
示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| #include <stdio.h>
#include <signal.h>
#include <sys/time.h>
void signalHandler(int signo)
{
switch (signo){
case SIGALRM:
printf("Caught the SIGALRM signal!\n");
break;
}
}
int main(int argc, char *argv[])
{
signal(SIGALRM, signalHandler);
struct itimerval new_value, old_value;
new_value.it_value.tv_sec = 0;
new_value.it_value.tv_usec = 1;
new_value.it_interval.tv_sec = 0;
new_value.it_interval.tv_usec = 200000;
setitimer(ITIMER_REAL, &new_value, &old_value);
for(;;);
return 0;
}
|
常用信号列表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
| SIGABRT 由调用abort函数产生,进程非正常退出
SIGALRM 用alarm函数设置的timer超时或setitimer函数设置的interval timer超时
SIGBUS 某种特定的硬件异常,通常由内存访问引起
SIGCANCEL 由Solaris Thread Library内部使用,通常不会使用
SIGCHLD 进程Terminate或Stop时候,SIGCHLD会发送给它的父进程。缺省情况下该Signal会被忽略
SIGCONT 当被stop的进程恢复运行的时候,自动发送
SIGEMT 和实现相关的硬件异常
SIGFPE 数学相关的异常,如被0除,浮点溢出,等等
SIGFREEZE Solaris专用,Hiberate或者Suspended时候发送
SIGHUP 发送给具有Terminal的Controlling Process,当terminal被disconnect时候发送
SIGILL 非法指令异常
SIGINFO BSD signal。由Status Key产生,通常是CTRL+T。发送给所有Foreground Group的进程
SIGINT 由Interrupt Key产生,通常是CTRL+C或者DELETE。发送给所有ForeGround Group进程
SIGIO 异步IO事件
SIGIOT 实现相关的硬件异常,一般对应SIGABRT
SIGKILL 无法处理和忽略。中止某个进程
SIGLWP 由Solaris Thread Libray内部使用
SIGPIPE 在reader中止之后写Pipe的时候发送
SIGPOLL 当某个事件发送给Pollable Device的时候发送
SIGPROF Setitimer指定的Profiling Interval Timer所产生
SIGPWR 和系统相关。和UPS相关。
SIGQUIT 输入Quit Key的时候(CTRL+\)发送给所有Foreground Group的进程
SIGSEGV 非法内存访问
SIGSTKFLT Linux专用,数学协处理器的栈异常
SIGSTOP 中止进程。无法处理和忽略。
SIGSYS 非法系统调用
SIGTERM 请求中止进程,kill命令缺省发送
SIGTHAW Solaris专用,从Suspend恢复时候发送
SIGTRAP 实现相关的硬件异常。一般是调试异常
SIGTSTP Suspend Key,一般是Ctrl+Z。发送给所有Foreground Group的进程
SIGTTIN 当Background Group的进程尝试读取Terminal的时候发送
SIGTTOU 当Background Group的进程尝试写Terminal的时候发送
SIGURG 当out-of-band data接收的时候可能发送
SIGUSR1 用户自定义signal 1
SIGUSR2 用户自定义signal 2
SIGVTALRM setitimer函数设置的Virtual Interval Timer超时的时候
SIGWAITING Solaris Thread Library内部实现专用
SIGWINCH 当Terminal的窗口大小改变的时候,发送给Foreground Group的所有进程
SIGXCPU 当CPU时间限制超时的时候
SIGXFSZ 进程超过文件大小限制
SIGXRES Solaris专用,进程超过资源限制的时候发送
|
sigemptyset
将信号集初始化为空。
glibc中的实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| /* A `sigset_t' has a bit for each signal. */
typedef unsigned long int __sigset_t;
/* A set of signals to be blocked, unblocked, or waited for. */
typedef __sigset_t sigset_t;
/* Clear all signals from SET. */
int
sigemptyset (sigset_t *set)
{
if (set == NULL)
{
__set_errno (EINVAL);
return -1;
}
memset (set, 0, sizeof (sigset_t));
return 0;
}
|
sigaddset
将指定信号加入到信号集合中去
1
2
| #include <signal.h>
int sigaddset(sigset_t *set, int signum);
|
sigaction
sigaction函数的功能是检查或修改与指定信号相关联的处理动作
1
2
| int sigaction(int signum, const struct sigaction *act,
struct sigaction *oldact);
|
参数:
- signum:信号id
- act:对信号的处理
- oldact:保存之前的信号处理信息,可以为NULL
act与oldact为NULL时,用于检测信号的有效性
相关结构体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
| struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
};
siginfo_t {
int si_signo; /* Signal number */
int si_errno; /* An errno value */
int si_code; /* Signal code */
int si_trapno; /* Trap number that caused
hardware-generated signal
(unused on most architectures) */
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 */
int si_overrun; /* Timer overrun count; POSIX.1b timers */
int si_timerid; /* Timer ID; POSIX.1b timers */
void *si_addr; /* Memory location which caused fault */
long si_band; /* Band event (was int in
glibc 2.3.2 and earlier) */
int si_fd; /* File descriptor */
short si_addr_lsb; /* Least significant bit of address
(since Linux 2.6.32) */
}
#ifdef __USE_POSIX199309
union sigval
{
int sival_int;
void *sival_ptr;
};
typedef union sigval __sigval_t;
#else
union __sigval
{
int __sival_int;
void *__sival_ptr;
};
typedef union __sigval __sigval_t;
#endif
|
示例(发送信号函数在sigqueue
函数的例子中,需要两个配合测试):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| #include <stdio.h>
#include <signal.h>
void handle_sigaction(int signum, siginfo_t *info, void *context)
{
printf("signal:%d\n", signum);
printf("info:%x\n", info->si_int);
}
int main()
{
int i = 0;
struct sigaction act;
sigemptyset(&act.sa_mask);
act.sa_sigaction = handle_sigaction;
act.sa_flags = SA_SIGINFO|SA_RESTART;
sigaction(SIGRTMIN+9, &act, NULL);
while(1)
{
sleep(1);
printf("sleeping %d\n", i);
i++;
}
return 0;
}
|
sigqueue
用于给指定进程发送信号,并附带一些参数
1
| int sigqueue(pid_t pid, int sig, const union sigval val)
|
参数:
- pid:进程pid
- sig:发送的信号
- val:发送信号时附带的参数
示例(对应sigaction
函数的信号处理示例):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
| #include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
static void send_signal(int flag)
{
FILE * fp;
char buffer[80];
pid_t pid;
union sigval sival_data;
int ret;
fp = popen("pidof signal_process","r");
if(fp != NULL){
memset(buffer,0x00,sizeof(buffer));
if ((fgets(buffer,sizeof(buffer),fp) == NULL) || (buffer[0] == '\0')){
pclose(fp);
return;
}
}else{
return;
}
pclose(fp);
pid = atoi(buffer);
sival_data.sival_int = flag;
ret = sigqueue(pid, SIGRTMIN+9, sival_data);
return;
}
int main()
{
send_signal(8);
return 0;
}
|