信号(SIGNAL)是操作系统的一部分,任何操作系统都离不开信号,信号就是操作系统自带的一套机制,由系统内核维护无需用户管理在操作系统中。信号是以软中断的形式存在的。
信号的官方宏定义及含义
在linux中可以在终端中输入指令man 7 signal来查看
Signal Value Action Comment
──────────────────────────────────────────────────────────────────────
SIGHUP 1 Term Hangup detected on controlling terminal
or death of controlling process
在控制终端收到一个"挂起" 或控制进程死亡时会收到这个信号
SIGINT 2 Term Interrupt from keyboard ==> Ctrl+C
SIGQUIT 3 Core Quit from keyboard ==> 来自键盘的退出 Ctrl+\
SIGILL 4 Core Illegal Instruction ==> 遇到非法指令
SIGABRT 6 Core Abort signal from abort(3) ==> 非正常终止
SIGFPE 8 Core Floating point exception ==>遇到一个浮点错误 比如 a/0
SIGKILL 9 Term Kill signal ==>杀死信号
SIGSEGV 11 Core Invalid memory reference ==>非法内存引用
SIGPIPE 13 Term Broken pipe: write to pipe with no ==> 有写无读的管道
readers
SIGALRM 14 Term Timer signal from alarm(2) ==> 超时信号
SIGTERM 15 Term Termination signal ==> 中止信号
SIGUSR1 30,10,16 Term User-defined signal 1 ==> 用户自定义信号1
SIGUSR2 31,12,17 Term User-defined signal 2 ==> 用户自定义信号2
SIGCHLD 20,17,18 Ign Child stopped or terminated ==>子进程退出或结束时,父进程收到的信号
SIGCONT 19,18,25 Cont Continue if stopped ==> 继续信号,继续停止的进程
SIGSTOP 17,19,23 Stop Stop process ==> 停止进程信号
SIGTSTP 18,20,24 Stop Stop typed at terminal ==> 终端发起的停止信号Ctrl+Z
SIGTTIN 21,21,26 Stop Terminal input for background process 后台试图从控制端输入
SIGTTOU 22,22,27 Stop Terminal output for background process 后台试图从控制端输出
信号的处理方式
- 忽略:不进行任何处理
- 默认:采用操作系统的方式去处理信号。例如: ctrl+c就是发送一个信号,将运行的程序终止。(注意:SIGKILL和SIGSTOP只能默认处理)
- 重定向:采用signal函数捕捉信号,并重新指定信号的处理方式
linux中与信号机制相关的几个接口函数
- signal:用来捕获一个信号,并修改其信号的处理函数
头文件:
#include <signal.h>
函数原型:
sighandler_t signal(int signum, sighandler_t handler);
@signum: 信号值,表示要捕获的信号
@handler:指定信号处理方式
1) SIG_IGN 忽略,不进行任何处理
2) SIG_DFL 默认,采用操作系统默认的信号处理行为
3) 自定义的信号处理函数的函数名表示由开发者执行决定处理方式
返回值:失败返回SIG_ERR
#include <stdio.h>
#include <signal.h>
int flag = 1; //标志位,默认初始化为1
/*
自定义的信号处理函数
*/
void function(int signal)
{
printf("按下ctrl + c\n");
flag = 0; //标志位设置为0
}
int main()
{
//捕获信号SIGINT(即ctrl+c)
if(SIG_ERR == signal(SIGINT, function))
{
//函数失败
perror("signal error");
return 0;
}
//死循环,当运行了function函数使标志位设置为0后结束循环
while (flag)
;
printf("程序ctrl+c后未结束\n");
return 0;
}
- kill:用来给pid指定的进程发送一个sig信号
头文件:
#include <sys/types.h>
#include <signal.h>
函数原型:
int kill(pid_t pid, int sig);
@pid: 进程号,表示发送信号给那个进程
@sig: 信号,整数(宏),表示要发送的信号
返回值:成功返回0,失败返回-1,并且errno被设置
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
int main()
{
//结束pid为3098的进程(进程pid可以在终端输入ps来查看)
if(-1 == kill(3098, SIGKILL))
{
perror("kill error");
}
return 0;
}
-
pause:等待某个信号到来,阻塞进程的执行,直到有信号
头文件:
#include <unistd.h>
函数原型:
int pouse(void);
如果该进程执行过程中,没有收到信号,则pause函数会一直等待直到任意信号到来 -
alarm:指定时间后产生一个SIGALRM(超时)信号
头文件:
#include <unistd.h>
函数原型:
unsigned int alarm(unsigned int seconds);
@seconds:设置的超时时间(以秒为单位)
alarm函数不会阻塞进程,调用alarm函数时,程序照常运行下去,只不过,当alarm设定的时间到来后,会产生SIGALRM信号SIGALRM信号的默认处理方式是,输出”闹钟“,同时中止进程。在linux中,如果一个进程中有多个alarm,则以最后设定的时间为准
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
/*
自定义的信号处理函数
*/
void function(int signal)
{
printf("time out!\n");
}
int main()
{
//捕获信号SIGALRM
if (SIG_ERR == signal(SIGALRM, function))
{
perror("signal error");
}
//设置闹钟(由于设置两个闹钟,所以闹钟仅最后一个有效,即5妙后发出SIGALRM(超时)信号)
alarm(3);
alarm(10);
alarm(5);
//pause函数,阻塞进程,有信号时才结束
pause();
return 0;
}