1、信号的概述
信号是Linux进程间通信的最古老的方式。信号是软件中断,它是在 软件层次上对中断机 制的一种模拟,是一种异步通信的方式。 信号可以导致一个 正在运行的进程被另一个正在运行的异步进程中断,转而处理某一个突 发事件。
特点:简单不能携带大量信息满足某个特设条件才发。 一个完整的信号周期包括三个部分: 信号 的产生,信号在进程中的注册(执行信号处理函数),信号在进程中的注销。
查看信号编号:kill -l
其中1-31号信号称之为常规信号(也叫普通信号或标准 信号),34-64称之为实时信号, 驱动编程与硬件相关。
终端上按“Ctrl+c”组合键通常产生 中断信号SIGINT
终端上按“Ctrl+\”键通常产生中断信号SIGQUIT
终端上按 “Ctrl+z”键通常产生中断信号SIGSTOP等
2、信号产生
a) 当用户按某些终端键时,将产生信号。终端上按“Ctrl+c”组合键通常产生 中断信号 SIGINT 终端上按“Ctrl+\”键通常产生中断信号 SIGQUIT终端上按 “Ctrl+z”键通常产生中断信 号SIGSTOP等。
b) 硬件异常将产生信号。除数为 0,无效的内存访问等。这些情况通常由硬件检测到,并 通知内核,然后内核产生 适当的信号发送给相应的进程。
c) 软件异常将产生信号。当检测到某种软件条 件已发生(如:定时器alarm),并将其通知 有关进程时,产生信号。
d) 调用系统 函数(如:kill、raise、abort)将发送信号。 注意:接收信号进程和发送信号进 程 的所有者必须相同,或发送信号进程的所有者必须是超级用户。
e) 运行kill /killall 命令将发送信号。此程序实际上是使用kill函数来发送信号。也常用此命 令终止一个失控的后台进程。
3、未决信号集合、信号阻塞集
产生信号后,在未决信号集中查看未解决的信号,然后在信号阻塞集中查看该信号是否被阻塞,如果阻塞就一直循环这个过程,如果未阻塞就进行信号处理
4、API
kill()
kill(pid,9)
raise()
abort()
alarm()
返回上一个闹钟剩余的秒数
setitimer()
通过signal改变SIGALRM信号的功能,默认是终止进程。
5、修改信号的处理方式






#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
char *p;
void my_deal_func(int sig)
{
if (p != NULL)
{
free(p);
p = NULL;
}
printf("我自己释放了p\n");
//_exit(-1);
return;
}
int main(int argc, char const *argv[])
{
struct sigaction act;
// 保存自定义函数的入口地址
act.sa_handler = my_deal_func;
// 将所有信号添加到集合中
sigset_t set;
sigfillset(&set);
act.sa_mask = set;
// 信号的处理方式
//act.sa_flags = 0;
act.sa_flags |= SA_RESETHAND;
// 注册 CTRL+C信号的处理函数
sigaction(SIGINT, &act, NULL);
p = (char *)calloc(1, 128);
strcpy(p, "hello signal");
printf("p=%s\n", p);
while (1)
;
printf("p指向的堆区空间释放了\n");
free(p);
return 0;
}

6、集合



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
char *p;
void my_deal_func(int sig)
{
if (p != NULL)
{
free(p);
p = NULL;
}
printf("我自己释放了p\n");
_exit(-1);
return;
}
int main(int argc, char const *argv[])
{
// 注册 CTRL+C信号的处理函数
signal(SIGINT, my_deal_func);
// 将SIGINT添加到阻塞集
sigset_t set;
// 清空集合
sigemptyset(&set);
// 将SIGINT添加到信号集set中
sigaddset(&set, SIGINT);
// 将set信号集 添加到 阻塞集中
sigprocmask(SIG_BLOCK, &set, NULL);
printf("已经将SIGINT添加到阻塞集中,持续时间10秒\n");
p = (char *)calloc(1, 128);
strcpy(p, "hello signal");
printf("p=%s\n", p);
sleep(10);
printf("已经将SIGINT从阻塞集删除\n");
sigprocmask(SIG_UNBLOCK, &set, NULL);
while (1)
;
printf("p指向的堆区空间释放了\n");
free(p);
return 0;
}