信号
信号是进程间通信的一种方式,这种方式没有数据传输的
只是在内核中传递了一个信号(整数),信号的表示是一个整数。
不同的信号值,代表不同的含义。用户可以自定义信号。
自定义的信号的含义由程序员来定和解释。
Linux 系统查看 man 7 signal
进程处理信号
通过“软件中断/软中断”来实现的。
进程上下文:
在进程的环境下,“时间片轮转”
一个进程的执行状态分为:
用户态:在执行用户自己的代码
内核态:进入操作系统内环境
中断上下文:中断的环境下。
进程在收到一个信号时,通常会由三种处理方式:
(1) 捕获信号
把一个信号与用户自定义的信号处理函数关联起来。
那么在收到该信号时,就会自行调用该处理函数。
(2) 默认行为
收到信号时,采用操作系统默认的行为方式
大部分的信号的默认行为都是把进程干掉
只有一个信号时被忽略的SIGCHLD
(3) 忽略该信号(Ignore)
Linux下面信号相关的API函数
1) 发送信号
#include <sys/types.h>
#include <signal.h>
kill发送一个信号给一个进程或多个进程
int kill(pid_t pid, int sig);
pid:指定信号的接收者(可能多个进程)
pid > 0:pid表示接收者的那一个进程的pid
pid = 0:发送信号给调用进程组的所有的进程
pid = -1:发送信号给所有的进程(有权限发送的所有进出港呢个)
pid < -1:发送信号给组ID等于PID的绝对值的所有进程
sig: 要发送的信号
返回值:
成功(至少有一个进程成功接收到了信号)返回0
失败返回-1,errno被设置。
-------------------------------------------------------------------
raise:发送信号给自己
int raise(int sig);
sig: 要发送的信号
raise(sig) <=> kill(getpid(), sig)
-------------------------------------------------------------------
alarm :设置一个发送信号的闹钟
unsigned int alarm(unsigned int seconds);
seconds:多少秒后,发送一个“闹钟”信号给自己
0, cancal a alarm 取消
返回值:
返回上一个闹钟的剩余秒数。
{
int a = alarm(5);
while(1);
}
alarm:定时发送一个信号(SIGALRM)给本进程。
“闹钟”:每个进程有一个属于自己的闹钟。时间到了,进程就会收到
一个信号(SIGALRM),但是同一时刻,一个进程只能够有一个闹钟。
int main()
{
int a = alarm(5);
a = alarm(10);
printf("%d\n", a);
alarm(0);
while(1);
}
2.捕捉改变信号处理方式
自定义处理函数
typedef void (*sighandler_t)(int);
sighandler_t是一个函数指针的类型,它可以用来定义一个函数指针变量
自定义的处理函数:无返回值,带一个int类型的参数的函数
sighandler_t signal(int signum, sighandler_t handler);
signum:要捕捉的那个信号的信号值。
handler:信号的处理方式
(1) 自定义的处理函数
无返回值
带一个int类型的参数的函数(用来保存
收到的信号的信号值)
void my_sig_handler(int sig)
{
.....
.....
}
(2) SIG_DFL: default,采用系统默认的处理方式
(3) SIG_IGN: 忽略该信号
返回值:
成功返回该信号上一次的处理方式。(上一次处理函数的首地址)
失败返回SIG_ERR,同时errno被设置。
void my_sig_handler(int sig)
{
switch(sig)
{
case SIGINT:
printf("break fail!!\n ");
break;
case SIGQUIT:
printf("exit fail!!\n");
break;
}
}
int main()
{
//捕捉信号: 把一个信号与其它的处理方式关联起来
signal(SIGINT, my_sig_handler);
signal(SIGQUIT, my_sig_handler);
while(1);
}