博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux编程基础之进程间通信之三:信号
阅读量:4195 次
发布时间:2019-05-26

本文共 2359 字,大约阅读时间需要 7 分钟。

一、信号的概述

信号是UNIX 中所使用的进程通信的一种最古老的方法。。它是在软件层次上对中断机制的一种模拟,是一种异步通信方式。信号可以直接进行用户空间进程和内核进程之间的交互,内核进程也可以利用它来通知用户空间进程发生了哪些系统事件。它可以在任何时候发给某一进程,而无需知道该进程的状态。如果该进程当前并未处于执行态,则该信号就由内核保存起来,直到该进程恢复执行再传递给它为止;如果一个信号被进程设置为阻塞,则该信号的传递被延迟,直到其阻塞被取消时才被传递给进程。

一个完整的信号生命周期可以分为3 个重要阶段,这3 个阶段由4 个重要事件来刻画的:信号产生、信号在进程中注册、信号在进程中注销、执行信号处理函数,如下图所示:

用户进程对信号的响应有三种方式:

  • 忽略信号,即对信号不做任何处理,但是有两个信号不能忽略,即SIGKILL 及SIGSTOP。
  • 捕捉信号,定义信号处理函数,当信号发生时,执行相应的自定义处理函数。
  • 执行缺省操作,Linux 对每种信号都规定了默认操作。
linux信号大多数是有内核提供的,下面列出了常见信号的含义和默认操作:

二、信号处理

信号处理的主要方法有两种,一种是使用简单的signal()函数,另一种是使用信号集函数组。下面分别介绍这两种处理方式。

1、使用signal()函数

使用signal()函数处理时,只需要指出要处理的信号和处理函数即可。它主要是用于前32 种非实时信号的处理,不支持信号传递信息,但是由于使用简单、易于理解,因此也受到很多程序员的欢迎。Linux 还支持一个更健壮、更新的信号处理函数sigaction(),推荐使用该函数。

函数格式:

void (*signal(int signum, void (*handler)(int)))(int)
        signum : 指定信号代码

        handler:信号处理函数,可以是SIG_IGN、SIG_DFL、用户自定义

2、使用sigaction()函数

函数格式:

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
        signum :信号代码,可以为除SIGKILL 及SIGSTOP 外的任何一个特定有效的信号

        act:指向结构sigaction 的一个实例的指针,指定对特定信号的处理

  oldact:保存原来对相应信号的处理

        返回值:0成功,其他返回错误代码

三、测试

分别对上述两种方式实现的信号处理进行测试。他们实现的功能都是一样的,编写一个信号处理函数用来捕捉用户输入的SIGINT信号(Ctrl + C)。

1、使用signal()函数

完整测试代码如下:

#include 
#include
#include
/* 自定义的信号处理函数 */void my_signal_func(int signum){ if(signum == SIGINT) { printf("Captured the signal is SIGINT!\n"); } else { printf("Cptured error!\n"); }}/* * 功能 : 捕捉SIGINT信号 */int main(void){ printf("Capture SIGINT signal!\n"); /* 捕捉相应的信号 */ signal(SIGINT, my_signal_func); /* wait a signal */ pause(); return 0;}
编译并运行,结果如下:

2、使用sigaction()函数

完整的代码如下所示:

#include 
#include
#include
#if 0struct sigaction { void (*sa_handler)(int); void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; int sa_flags; void (*sa_restorer)(void);};#endif/* 信号处理函数 */static void my_signal_func(int signum){ if(signum == SIGINT) { printf("Captured the signal SIGINT!\n"); } else { printf("Captured error!\n"); }}/* * 功能 : 捕捉信号SIGINT */int main(void){ int ret; struct sigaction my_sigaction; printf("Capture the siganl SIGINT!\n"); /* 设置my_sigaction结构体 */ my_sigaction.sa_handler = my_signal_func; sigemptyset(&my_sigaction.sa_mask); my_sigaction.sa_flags = 0; /* 将相应的信号与信号处理函数绑定起来 */ ret = sigaction(SIGINT, &my_sigaction, 0); pause(); // wait for signal return 0;}
编译并运行结果如下所示:

你可能感兴趣的文章
云管理软件 ManageIQ(转)
查看>>
CentOS 7.0,启用iptables防火墙(转)
查看>>
DISCUZ浅析之COOKIE篇
查看>>
实战DDD(Domain-Driven Design领域驱动设计:Evans DDD)
查看>>
SSH中各个框架的作用以及Spring AOP,IOC,DI详解
查看>>
openstack juno 配置vmware(vcenter、vsphere)
查看>>
远程debug调试(eclipse)之openstack windows
查看>>
PAAS平台对比:OpenShift VS CloudFoundry【51CTO调研报告】
查看>>
JAX-RS(java restful实现讲解)(转)
查看>>
Spring MVC与JAX-RS比较与分析
查看>>
openstack官方docker介绍
查看>>
头痛与早餐
查看>>
[转]在ASP.NET 2.0中操作数据::创建一个数据访问层
查看>>
Linux命令之chmod详解
查看>>
【java小程序实战】小程序注销功能实现
查看>>
Java中子类能否继承父类的私有属性和方法
查看>>
JVM内存模型详解
查看>>
(二)Git--工作区和暂存区、管理修改与撤销
查看>>
(七)Git--自定义Git
查看>>
(五)Git--分支管理
查看>>