转:步步LINUX C--进程间通信(二)信号
源地址:http://blog.csdn.net/jmy5945hh/article/details/7529651
linux间进程通信的方法在前一篇文章中已有详细介绍。http://blog.csdn.net/jmy5945hh/article/details/7350564
本篇详细介绍及代码测试第二种方式,即信号(Signal)。
1 信号简介
信号全称为软中断信号,主要用于进程控制。
信号是进程间通信机制中唯一的异步通信机制,可以看作是异步通知。信号机制经过POSIX实时扩展后,功能更加强大,除了基本通知功能外,还可以传递附加信息。
信号的来源包括硬件来源与软件来源。
生存周期从被创建开始,到进程接收到信号。某些情况下允许信号排队。
内核对信号的处理机制:
(1)发送信号的方法为在进程所在的进程表项的信号域设置对应于该信号的位。
(2)睡眠进程的睡眠优先级高于信号时,信号不会唤醒进程。
(3)内核处理信号的时机是进程从内核态返回用户态时或者进程要切换到低优先级睡眠态时。
(4)处理方法:退出,忽略或通过signal函数调用用户定义函数处理。
典型应用:LINUX下程序在命令行运行时,按下CTRL+C将向程序发送SIGINT信号,强制进程结束。
在命令行使用kill -l命令可以列出所有LINUX系统支持的信号

值得注意的是,信号的编号不是连续的。在SIGRTMIN之前的信号被称为不可靠信号,之后的称为可靠信号。
主要的区别在于,不可靠信号:
1/进程每次处理信号后,就将对信号的响应设置为默认动作。在某些情况下,将导致对信号的错误处理;因此,用户如果不希望这样的操作,那么就要在信号处理函数结尾再一次调用signal(),重新安装该信号。
2/不支持排队,信号可能丢失。 因此,早期unix下的不可靠信号主要指的是进程可能对信号做出错误的反应以及信号可能丢失。
2 信号的处理
注册处理函数
- #include <signal.h>
- void (*signal (int signum, void (*handler) (int) ) ) (int);
- /* 等效形式 */
- typedef void(*sighandler_t) (int);
- sighandler_t signal(int signum, sighandler_t handler);
#include <signal.h>
void (*signal (int signum, void (*handler) (int) ) ) (int);
/* 等效形式 */
typedef void(*sighandler_t) (int);
sighandler_t signal(int signum, sighandler_t handler);
成功返回之前的处理信号配置;出错返回SIG_ERR。
不能捕捉SIGKILL或者SIGSTOP信号。handler取值为SIG_IGN表示忽略,为SIG_DFL表示执行系统默认操作,为函数名时表示执行特定操作。
处理函数增强版
- #include <signal.h>
- int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
#include <signal.h>
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
成功后返回0;出错返回-1。
- struct sigaction
- {
- void (*sa_sighandler) (int);
- void (*sa_sigaction) (int, siginfo_t *, void *);
- sigset_t sa_mask;
- int sa_flags;
- void (*sa_restorer) (void);
- }
struct sigaction
{
void (*sa_sighandler) (int);
void (*sa_sigaction) (int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer) (void);
}
sa_flags参数
| 取值 | 含义 |
| SA_NOCLDSTOP | 用于指定信号SIGCHLD。 |
| SA_NOCLDWAIT | 对信号SIGCHLD,子进程结束时,不创建僵死进程。 |
| SA_NODEFER | 处理信号时如果产生了其他信号,则先去处理其他信号。 |
| SA_NOMASK | 与SA_NODEFER相似。 |
| SA_RESETHAND | 处理完信号后,注销处理函数。 |
| SA_ONESHOT | 同SA_RESETHAND相似 |
| SA_RESTART | 信号发生时正处在程序阻塞处,则处理完信号从阻塞处返回。 |
| SA_SIGINFO | 指示sa_sigaction有效。不设置表示sa_handler有效。 |
信号集
- #include <signal.h>
- int sigemptyset( sigset_t *set );
- int sigfillset( sigset_t *set );
- int sigaddset( sigset_t *set, int signum );
- int sigdelset( sigset_t *set, int signum );
- int sigismember( const sigset_t *set, int signum );
#include <signal.h>
int sigemptyset( sigset_t *set );
int sigfillset( sigset_t *set );
int sigaddset( sigset_t *set, int signum );
int sigdelset( sigset_t *set, int signum );
int sigismember( const sigset_t *set, int signum );
前四个函数成功返回0;出错返回-1.最后一个函数为真返回1;为假返回0。
信号集用于表示由多个信号所组成的数据类型。empty置空,fill置满,add添加,del删除,member检测。
3 信号的发送
向其他进程发送信号
- #include <signal.h>
- #include <sys/types.h>
- int kill( pid_t pid, int signum );
#include <signal.h>
#include <sys/types.h>
int kill( pid_t pid, int signum );
成功后返回0;出错返回-1。发送对象可以使一个进程组。
向本进程发送信号
- #include <signal.h>
- #include <sys/types.h>
- int raise( int signum );
#include <signal.h>
#include <sys/types.h>
int raise( int signum );
成功后返回0;出错返回-1。
实时信号的发送
- #include <signal.h>
- #include <sys/types.h>
- int sigqueue( pid_t pid, int signum, const union sigval val );
#include <signal.h>
#include <sys/types.h>
int sigqueue( pid_t pid, int signum, const union sigval val );
- typedef union sigval
- {
- int sival_int;
- void *sigval_ptr; // 指向要传递的信号参数
- } sigval_t;
typedef union sigval
{
int sival_int;
void *sigval_ptr; // 指向要传递的信号参数
} sigval_t;
支持信号带有参数。成功后返回0;出错返回-1。发送对象只能是单个进程。
指定时间的发送
- #include <unistd.h>
- unsigned int alarm( unsigned int seconds );
#include <unistd.h>
unsigned int alarm( unsigned int seconds );
seconds参数指定了下一次发送SIGALRM信号的时间。如果调用前设置了闹钟,则返回闹钟剩余时间,否则返回0。
- #include <sys/time.h>
- int setitimer( int which, const struct itimerval *value, struct itimerval *oldvalue);
- struct itimerval
- {
- struct timeval it_interval;
- struct timeval it_value;
- };
#include <sys/time.h>
int setitimer( int which, const struct itimerval *value, struct itimerval *oldvalue); struct itimerval
{
struct timeval it_interval;
struct timeval it_value;
};
which参数
| 取值 | 定时器类型 | 信号 |
| ITIMER_REAL | 根据系统时间设定绝对时间。 | SIGALRM |
| ITIMER_VIRTUAL | 设定程序执行时间,用户模式下可跟踪。 | SIGVTALRM |
| TIMER_PROF | 从用户进程开始后开始计时。 | SIGPROF |
成功后返回0;出错返回-1。相比于alarm,setitimer支持三种类型的定时器。
3 信号的阻塞
- #include <signal.h>
- int sigprocmask( int how, const sigset_t *set, sigset_t *oldset );
#include <signal.h>
int sigprocmask( int how, const sigset_t *set, sigset_t *oldset );
how参数
| 取值 | 功能 |
| SIG_BLOCK | 将set信号集的信号与掩码做逻辑或运算 |
| SIG_UNBLOCK | 将set信号集的信号与掩码做逻辑减运算 |
| SIG_SETMASK | 以set信号集对信号掩码进行赋值操作 |
成功后返回0;出错返回-1。用于信号的阻塞延迟处理。
- #include <signal.h>
- int sigsuspend( const sigset_t *sigmask );
#include <signal.h>
int sigsuspend( const sigset_t *sigmask );
成功后无返回值;出错返回-1。调用此函数后进程挂起,直到接收到信号复原信号集,然后调用处理函数。
3 信号通信测试代码:
- #include <stdio.h>
- #include <signal.h>
- #include <sys/types.h>
- #include <unistd.h>
- void op(int, siginfo_t*, void*);
- int main(int argc,char**argv) {
- struct sigaction act;
- int sig;
- pid_t fpid, spid;
- if((spid =fork()) == 0) {
- int signum;
- union sigval mysigval;
- signum = 5; //信号值取5
- fpid = getppid(); //获取父进程ID
- mysigval.sival_int = 8; // 用于测试
- if(sigqueue(fpid, signum, mysigval) == -1) //子进程发送信号
- printf("send error\n");
- sleep(2);
- }
- else if(spid > 0) {
- struct sigaction act;
- int sig = 5;
- sigemptyset(&act.sa_mask);
- act.sa_sigaction=op;
- act.sa_flags=SA_SIGINFO;
- if(sigaction(sig, &act, NULL) < 0) //父进程指定对于信号的处理
- printf("install sigal error\n");
- sleep(2);
- }
- }
- void op(int signum, siginfo_t *info, void *myact) { // 信号处理函数
- printf("the int value is %d \n", info->si_int);
- }
运行结果:
- jimmy@MyPet:~/code/ipc$ gcc -g -o ipc ipc.c
- jimmy@MyPet:~/code/ipc$ ./ipc
- the int value is 8
非正常测试结果及总结
1)将子进程中的signum改为与父进程中的sig值不一致,不能进行信号通信。
2)信号通信是惟一的进程间异步通信模式。
3)可以在终端输入kill -l查看系统支持的信号。其中前半部分(<=32)是不可靠信号,后半部分是可靠信号。
4)进程对于实时信号的默认处理方式都是终止进程。
转:步步LINUX C--进程间通信(二)信号的更多相关文章
- Linux环境进程间通信(二):信号(下)
linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...
- Linux环境进程间通信(二): 信号(上)
linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...
- <转>Linux环境进程间通信(二): 信号(上)
原文链接:http://www.ibm.com/developerworks/cn/linux/l-ipc/part2/index1.html 原文如下: 一.信号及信号来源 信号本质 信号是在软件层 ...
- Linux环境进程间通信(二): 信号--转载
http://www.ibm.com/developerworks/cn/linux/l-ipc/part2/index1.html http://www.ibm.com/developerworks ...
- [转]Linux进程间通信——使用信号
转载于:http://blog.csdn.net/ljianhui/article/details/10128731 经典!!! Linux进程间通信——使用信号 一.什么是信号 用过 ...
- linux内核剖析(九)进程间通信之-信号signal
信号及信号来源 什么是信号 信号是UNIX和Linux系统响应某些条件而产生的一个事件,接收到该信号的进程会相应地采取一些行动.通常信号是由一个错误产生的.但它们还可以作为进程间通信或修改行为的一种方 ...
- 练习--LINUX进程间通信之信号SIGNAL
同样的,信号也不要太迷信可靠信号及不及靠信号,实时或非实时信号. 但必须要了解这些信号之间的差异,函数升级及参数,才能熟练运用. ~~~~~~~~~~~~~~~~ 信号本质 信号是在软件层次上对中断机 ...
- Linux进程间通信(三) - 信号
什么是信号 软中断信号(signal,又简称为信号)用来通知进程发生了异步事件.在软件层次上是对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的.信号是进程间通 ...
- 【转载】Linux的进程间通信-信号量
原文:Linux的进程间通信-信号量 Linux的进程间通信-信号量 版权声明: 本文章内容在非商业使用前提下可无需授权任意转载.发布. 转载.发布请务必注明作者和其微博.微信公众号地址,以便读者询问 ...
随机推荐
- 微信sdk 隐藏右上角菜单项
wx.ready(function () { // 8.3 批量隐藏菜单项 wx.hideMenuItems({ menuList: [ 'menuItem:share:qq', //分享到QQ 'm ...
- csp-s模拟测试87
csp-s模拟测试87 考场状态还可以$T1$我当时以为我秒切,$T2$确认自己思路不对后毅然决然码上,$T3$暴力挂了太可惜了. 03:01:28 03:16:07 03:11:38 140 03: ...
- Sublime Text 3,有了Anaconda就会如虎添翼
作为Python开发环境的Sublime Text 3,有了Anaconda就会如虎添翼.Anaconda是目前最流行也是最有威力的Python代码提示插件. 操作步骤 1.打开package con ...
- HTTP协议请求篇
http协议的基本概念 超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议.是工作在tcp/ip协议基础上的,所有的WWW文件都必须 ...
- 02.万恶之源-python 运算符和编码
一.流程控制语句if: 第一种语法: (最基本的语法) if 条件: 代码块/结果1 结果2 # 如果条件是真(True)执行结果为1,然后结果为2,如果条件为错(False), 直接结果2. 第二种 ...
- 机器学习-线性回归算法(单变量)Linear Regression with One Variable
1 线性回归算法 http://www.cnblogs.com/wangxin37/p/8297988.html 回归一词指的是,我们根据之前的数据预测出一个准确的输出值,对于这个例子就是价格,回归= ...
- 锐速与BBR的原理简单解析
锐速与BBR的原理简单解析 4 前言 昨天,有一位朋友在我的文章下留言说,锐速和BBR不都是一样,是拥塞算法嘛.因为这方面需要讲的东西比较多,所以我还是专门水一篇文章吧. 锐速 参考资料: http ...
- eclipse中启动tomcat之后,项目一直重复部署导致内存报警!!!
项目环境:jdk1.8+tomcat8.0; 出现该问题的原因:目前还没有确定,网友有很多的说法. 但是我在部署其中一个项目时出现此情况,在同样的环境下部署另外一个项目未出现此情况. 其中的一种解决方 ...
- VS2010-MFC(MFC消息映射机制概述)
转自:http://www.jizhuomi.com/software/147.html 前面已经说过,Windows应用程序是消息驱动的.在MFC软件开发中,界面操作或者线程之间通信都会经常用到消息 ...
- Docker系列(十一):Kubernetes集群集群部署实践
Kubernetes分布式集群架构 服务注册和服务发现问题怎么解决的? 分布式通讯的核心就是ip加端口 每个服务分配一个不变的虚拟IP+端口 系统env环境变量里有每个服务的服务名称到IP的映射 如下 ...