您的位置:首页 > 运维架构 > Linux

12.linux中的信号

2016-09-02 15:37 134 查看
12.1.什么是信号

(1)信号是通信内容受限(int型数字)的1种异步通信机制;信号是当前进程对外通信的1种手段;信号的目的用来通信的;信号是异步的(类似硬件中断);信号本质上是操作系统事先定义好的int型数字编号。

(2)信号由谁发出;用户在终端按下按键(譬如用户按下Ctrl+c按键终止程序运行);硬件异常后由操作系统内核发出信号;用户使用kill命令向其它进程发出信号;某种软件条件满足后也会发出信号,如alarm闹钟时间到会产生SIGALARM信号,向1个读端已经关闭的管道write时会产生SIGPIPE信号。

(3)信号由谁处理并如何处理;忽略信号(收到信号直接丢弃);捕获信号(信号绑定了某个函数);默认处理(当前进程收到该信号后执行信号默认操作,一般是忽略或终止进程)。

12.2.常见信号介绍

(1)SIGINT(2-Ctrl+C时OS送给前台进程组中每个进程);SIGABRT(6-调用abort函数,进程异常终止);SIGPOLL/SIGIO(8-指示1个异步IO事件,在高级IO中提及);SIGKILL(9-杀死进程的终极办法,该信号无法被忽略);SIGSEGV(11-无效存储访问时OS发出该信号,提示段错误信息)。

(2)SIGPIPE(13-涉及管道和socket编程);SIGALARM(14-涉及alarm函数的实现);SIGTERM(15-kill命令发送的OS默认终止信号);SIGCHLD(17-子进程终止或停止时OS向其父进程发此信号)。SIGUSR1

(3)SIGUSR1(10-用户自定义信号,作用和意义由应用自己定义);SIGUSR2(12-用户自定义信号,作用和意义由应用自己定义)。

(4)信号定位在/usr/include/signal.h和/usr/include/i386-linux-gnu/bits/signum.h这两个头文件中。

12.3.进程对信号的处理

(1)默认处理+忽略处理+捕获处理;signal函数绑定某个捕获函数后,当信号发生后会自动执行绑定的捕获函数,并且把信号编号作为传参传给捕获函数;signal的返回值在出错时为SIG_ERR,绑定成功时返回旧的捕获函数;signal函数的优点-简单好用,捕获信号常用;缺点-无法简单直接得知之前设置的对信号的处理方法。

(2)sigaction函数比signal更具有可移植性,其使用方法的关键是2个sigaction指针;sigaction可以1次得到设置新捕获函数和获取旧的捕获函数(其实还可以单独设置新的捕获或者单独只获取旧的捕获函数),而signal函数必须在设置新的捕获函数的同时才获取旧的捕获函数。

12.4.alarm和pause函数

(1)alarm函数,内核以API形式提供的闹钟;内核在1个进程中只维持1个alarm闹钟,在首次调用alarm后会返回0,在第2次调用alarm后返回上次闹钟还剩下的秒数并重新注册alarm闹钟。

(2)pause函数,pause函数的作用就是让当前进程暂停运行,交出CPU给其它进程去执行,当前进程进入pause状态后当前进程会表现为卡住/阻塞住,退出pause状态当前进程需要被信号唤醒。

12.signal
/*
* 公司:XXXX
* 作者:Rston
* 博客:http://blog.csdn.net/rston
* GitHub:https://github.com/rston
* 项目:linux中的信号
* 功能:演示signal函数的简单使用。
*/
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>

typedef void (*sighandler_t)(int);

// ctrl+c信号捕捉函数
void signal_func(int sig)
{
printf("I catch ctrl + c.\n");
}

int main(int argc, char **argv)
{
#if 1
// 指定信号SIGINT为具体的signal_func处理函数
sighandler_t ret = ((sighandler_t) -2);
ret = signal(SIGINT, signal_func);
if (SIG_ERR == ret)
{
perror("signal error");
exit(-1);
}
#endif

#if 0
// 指定信号SIGINT为默认处理
signal(SIGINT, SIG_DFL);
#endif

#if 0
// 指定信号SIGINT为忽略处理
signal(SIGINT, SIG_IGN);
#endif

printf("before while(1).\n");
while(1);
printf("after while(1).\n");

return 0;
}


12.sigaction_alarm_pause
/*
* 公司:XXXX
* 作者:Rston
* 博客:http://blog.csdn.net/rston
* GitHub:https://github.com/rston
* 项目:linux中的信号
* 功能:演示sigaction和alarm和pause函数的简单使用。
*/
#include <stdio.h>
#include <signal.h>
#include <unistd.h>

void mysleep(unsigned int seconds);

#if 1
void signal_func(int sig)
{

}
#endif

#if 0
void signal_func(int sig)
{
printf("alarm happened.\n");
}
#endif

int main(int argc, char **argv)
{
#if 0
int ret = -1;
struct sigaction act = {0};
act.sa_handler = signal_func;

ret = sigaction(SIGALRM, &act, NULL);

ret = alarm(5);
printf("1st, ret = %d.\n", ret);    // 1st, ret = 0.
sleep(3);

ret = alarm(5);
printf("2st, ret = %d.\n", ret);    // 2st, ret = 2.
sleep(1);

ret = alarm(5);
printf("3st, ret = %d.\n", ret);    // 3st, ret = 4.

#if 0
while (1);
#endif

#if 1
pause();
#endif
#endif

#if 1
// 使用alarm和pause来模拟sleep
printf("before mysleep.\n");
mysleep(3);
printf("after mysleep.\n");
#endif

return 0;
}

#if 0
void mysleep(unsigned int seconds)
{
struct sigaction act = {0};

act.sa_handler = signal_func;
sigaction(SIGALRM, &act, NULL);

alarm(seconds);
pause();
}
#endif
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  信号 默认 忽略 捕获