1.什么是信号
信号是Linux系统响应某些条件而产生的一个事件,接收到该信号的进程会执行相应的操作。

2.信号的产生
1)由硬件产生,如从键盘输入Ctrl+C可以终止当前进程
2)由其他进程发送,如可在shell进程下,使用命令 kill -信号标号 PID,向指定进程发送信号。
3)异常,进程异常时会发送信号

3.信号的处理
信号是由操作系统来处理的,说明信号的处理在内核态。
信号不一定会立即被处理,此时会储存在信号的信号表中。
处理过程示意图:

由上图中可看出信号有三种处理方式:
1)忽略
2)默认处理方式:操作系统设定的默认处理方式
3)自定义信号处理方式:可自定义信号处理函数

4.自定义信号处理方式
1)signal函数
原型:
void (*signal(int sig, void (*func)(int)))(int);
sig:信号值
func:信号处理函数指针,参数为信号值
代码示例如下:

#include <signal.h>
#include <stdio.h>
void ouch(int sig)
{
printf("\nOUCH! - I got signal %d\n", sig);
//恢复终端中断信号SIGINT的默认行为
(void) signal(SIGINT, SIG_DFL);
}
int main()
{
//改变终端中断信号SIGINT的默认行为,使之执行ouch函数
//而不是终止程序的执行
(void) signal(SIGINT, ouch);
while()
{
printf("Hello World!\n");
sleep();
}
return ;
}

输出结果:

2)sigaction函数
原型:
int sigaction(int sig,const struct sigaction *act,struct sigaction *oact);
sig:信号值
act:指定信号的动作
oact:保存原信号的动作

sigaction结构体的定义如下:
void (*)(int) sa_handler;处理函数指针,相当于signal函数的func参数。
sigset_t sa_mask;处理过程中,屏蔽对sa_mask信号集的处理,sa_mask可以消除信号间的竞态。
int sa_flags;信号处理修改器:处理函数执行完后,信号处理方式修改。如SA_RESETHAND,将信号处理方式重置为SIG_DFL
代码示例如下:

#include <stdio.h>
#include <signal.h>
void ouch(int sig)
{
printf("\nOUCH! - I got signal %d\n", sig);
}
int main()
{
struct sigaction act;
act.sa_handler = ouch;
//创建空的信号屏蔽字,即不屏蔽任何信息
sigemptyset(&act.sa_mask);
//使sigaction函数重置为默认行为
act.sa_flags = SA_RESETHAND;
sigaction(SIGINT, &act, );
while()
{
printf("Hello World!\n");
sleep();
}
return ;
}

输出结果:

4.信号的发送
1)kill函数
int kill(pid_t pid,int signo);
pid:进程ID
signo:信号值

2)raise函数:只能向当前进程发信号
int raise(int signo);
signo:信号值

3)abort函数:发送SIGABRT信号,可以让进程异常终止
void abort(void);

4)alarm函数:发送SIGALRM闹钟信号
unsigned int alarm(unsigned int seconds);

5.信号的阻塞
阻塞是阻止进程收到该信号,此时信号处于未决状态,放入进程的未决信号表中,
当解除对该信号的阻塞时,未决信号会被进程接收。

1)阻塞信号
原型:
int sigprocmask(int how,const sigset_t *set,sigset_t *oset);
how:设置block阻塞表的方式
a.SIG_BLOCK:将信号集添加到block表中
b.SIG_UNBLOCK:将信号集从block表中删除
c.SIG_SETMASK:将信号集设置为block表
set:要设置的集合
oset:设置前保存之前block表信息

2)获取未决信号
前面已经讲过,阻塞的信号处于未决的状态,会放入进程的未决信号表。
原型:
int sigpending(sigset_t *set);
set:out型参数,会将获得的当前进程的pending未决表中的信号集传入。

代码示例如下:

#include <stdio.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <signal.h>
void func(int num)
{
printf("catch signal number is %d",num);
}
void printfpendingsignal(sigset_t *set)
{
int i;
for(i=;i<;++i)
{
if(sigismember(set,i))
{
printf("");
}
else
{
printf("");
}
}
printf("\n");
}
int main()
{
sigset_t s,p,o;
signal(SIGINT,func);
sigemptyset(&s);
sigemptyset(&p);
sigemptyset(&o);
sigaddset(&s,SIGINT);
sigprocmask(SIG_SETMASK,&s,&o);
int count=;
while()
{
sigpending(&p);
printfpendingsignal(&p);
sleep();
if(count++==)
{
printf("recover!\n");
sigprocmask(SIG_SETMASK,&o,NULL);
}
}
return ;
}

输出结果:

6.信号处理函数的安全问题
如果信号处理过程中被中断,再次调用,然后返回到第一次调用时,要保证操作的正确性。
这就要求信号处理函数必须是可重入的。
可重入函数表如下:

7.一些常见的信号

如果进程接收到上面的这些信号,又没有安排捕获它,进程就会终止。

其他的一些信号如下:

Linux进程间通信-信号的更多相关文章

  1. Linux进程间通信——信号集函数

    一.什么是信号 用过Windows的我们都知道,当我们无法正常结束一个程序时,可以用任务管理器强制结束这个进程,但这其实是怎么实现的呢?同样的功能在Linux上是通过生成信号和捕获信号来实现的,运行中 ...

  2. 详解linux进程间通信-信号

    前言:之前说看<C++ Primer >暂时搁浅一下,迷上公司大神写的代码,想要明白,主要是socket.进程间通信! 知道进程间通信:信号.信号量.管道.消息队列.共享内存(共享存储), ...

  3. Linux进程间通信—信号

    三.信号(Signal) 信号是Unix系统中使用的最古老的进程间通信的方法之一.操作系统通过信号来通知某一进程发生了某一种预定好的事件:接收到信号的进程可以选择不同的方式处理该信号,一是可以采用默认 ...

  4. Linux进程间通信——信号

    一.认识信号 信号(Signals)是Unix.类Unix以及其他POSIX兼容的操作系统中进程间通讯的一种有限制的方式.它是一种异步的通知机制,用来提醒进程一个事件已经发生.当一个信号发送给一个进程 ...

  5. Linux 进程间通信 信号(signal)

    1. 概念: 1)信号是在软件层次上对中断机制的一种模拟,是一种异步通信方式 2)信号可以直接进行用户空间进程和内核进程之间的交互,内核进程也可以利用它来通知用户空间进程发生了哪些系统事件. 3)如果 ...

  6. Linux进程间通信(一): 信号 signal()、sigaction()

    一.什么是信号 用过Windows的我们都知道,当我们无法正常结束一个程序时,可以用任务管理器强制结束这个进程,但这其实是怎么实现的呢?同样的功能在Linux上是通过生成信号和捕获信号来实现的,运行中 ...

  7. [转]Linux进程间通信——使用信号

    转载于:http://blog.csdn.net/ljianhui/article/details/10128731         经典!!! Linux进程间通信——使用信号 一.什么是信号 用过 ...

  8. Linux进程间通信——使用信号

    一.什么是信号 用过Windows的我们都知道,当我们无法正常结束一个程序时,可以用任务管理器强制结束这个进程,但这其实是怎么实现的呢?同样的功能在Linux上是通过生成信号和捕获信号来实现的,运行中 ...

  9. Linux进程间通信(五):信号量 semget()、semop()、semctl()

    这篇文章将讲述别一种进程间通信的机制——信号量.注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物.有关信号的更多内容,可以阅读我的另一篇文章:Linux进程间通信 -- 信号.下面 ...

随机推荐

  1. Pattern和Matcher

    java util本身提供了Pattern和Matcher(java.util.regex.Pattern,Matcher),两个类均是与正则表达式相关的类,其中: java.util.regex是一 ...

  2. 2016-1-7第一个完整APP 私人通讯录的实现 5:保存数据

    一:登陆界面 1):用户点击登陆按钮并成功登陆后,根据此时的开关情况选择是否保存数据,代码如下: "]) { [self performSegueWithIdentifier:@" ...

  3. php大力力 [021节]mysql表名在mac下不能大写

    2015-08-27 php大力力021.mysql表名在mac下不能大写 刚才数据库里面,phpMyAdmin狂出错. Some errors have been detected on the s ...

  4. JQuery源码分析(七)

    了解jQuery对DOM进行遍历背后的工作机制,这样可以在编写代码时有意识地避免一些不必要的重复操作,从而提升代码的性能. 关于jQuery对象的包装 var $aaron = $("aar ...

  5. JS-OC通信之Cordova简介

    Cordova 是一个可以让 JS 与原生代码(包括 Android 的 java,iOS 的 Objective-C 等)互相通信的一个库,并且提供了一系列的插件类,比如 JS 直接操作本地数据库的 ...

  6. URl中文转ASCII

    编码 System.Web.HttpUtility.UrlEncode("中国", System.Text.Encoding.GetEncoding("GB2312&qu ...

  7. Apache 中 .htaccess 文件设置技巧16则

    .htaccess 文件 (Hypertext Access file) 是Apache Web服务器的一个非常强大的配置文件,对于这个文件,Apache有一堆参数可以让你配置出几乎随心所欲的功能.. ...

  8. 《MORE EFFECTIVE C++》条款20 条款21

    条款20 协助编译器实现返回值优化 当重载运算符的时候,比如+ - * / 这类运算符,该函数返回的值一定是个右值(即不能是引用),那么执行一次运算的开销可能会在临时对象上调用多次构造函数和析构函数, ...

  9. web app 开发必不可少的滑动插件 Flipsnap

    flipsnap.js一个轻量级的滑动效果JS开发库,仅有8k大小(压缩版),包含了10种滑动方式,是web app开发必备的js库,除了兼容主流的智能手机浏览器(iossafari,android, ...

  10. iOS学习笔记---c语言第六天

    函数  function 命名规范:工程名第一个字母大写,变量函数名小写,不要用拼音和中文, eg:lessonFunction 一.函数声明定义 函数是具有特定功能的代码块        作用:模块 ...