经过了漫长的间歇,对于c语言的学习也被中断了很久,现实确实有很多的无耐,计划中的事情总会被打乱,但不管怎样,学习的道路是不能休止的,所以经过了一断温习后现在继续学习C语言,话不多说,进入正题:

信号分类
可靠信号与不可靠信号

不可靠信号:
linux信号机制基本上是从unix系统中继承过来的。早期unix系统中的信号机制比较简单和原始,后来在实践中暴露出一些问题,它的主要问题是:
我们用上节课的例子来解释上面的这断话:
运行来看下:
而第二次再按ctrl+c,还是会输出我们的处理程序:
所以与之对比,上面文字中提到的不可靠信号的默认动作就能理解了,就是早期的unix当我们注册完了信号,并处理信号时,则会恢复到默认动作,表现形式也就是这样(模拟):
 
"用户如果不希望这样的操作,那么就要在信号处理函数结尾再一次调用signal(),重新安装该信号。",也就是这样做:
 
从上面这段程序可以看出,当再次注册信号时,如果新的SIGINT信号过来了,但是信号还没注册完,那么还是会响应ctrl+c的默认动作,也就是程序退出了,这就说明是做出了一个错误的反应,另外,关于信号可能会丢失说的是哪方面呢?是指当来了多个SIGINT信号时,不可靠信号是不会排队的,只会保留一个,其它的都被丢弃掉 
也就是说,如今的linux的不可靠信号在处理完之后,是不会被恢复成默认动作的,而不可靠信号同样还有这样的特征:"不可靠信号是不会排队的,只会保留一个,其它的都被丢弃掉",也就是存在信号的丢失。
总结一下:早期unix的不可靠信号在执行完之后会被恢复成默认动作,也就是会做出错误的反应,并且信号不会排队,存在信号丢失问题;而如今的linux的不可靠信号在执行完之后是不会被恢复的,也就是不会做出错误的反应,但是还是存在信号丢失的问题,所以基于这个原因,就出现了下面要介绍的可靠信号了。
 
可靠信号:
那新增的可靠信号是哪些呢?
在之前介绍不可靠信号时,其中说到“linux信号安装函数(signal)是在可靠机制上的实现”,也就是说signal和sigaction是一样的,都是可靠信号的安装,实际上它们都调用了更加底层的dosigaction内核函数,只能内核才能调用到,做一个了解。
实时信号:
 
其中后32个信号是没有具体含义的,可供应用程序进行使用, 另外SIGRTMIN不一定都是从34开始,先查看一下目前它是从哪开始的:
可以从signal的帮助文档中可以阅读到:
这个做为了一个了解。
 
信号发送
关于kill函数,我们经常会用到:
实际上更准确的说法是向pid进程发送9号信号,由于9号信号不能被忽略,也不能被捕获的,而它默认动作就是将进程给杀掉,所以我们经常用这个命令来杀死进程。
实际上kill命令的实现是靠kill系统函数,可以man查看一下:
下面对该函数的描述进行认识,之后会用到:
 
 
 
当pid=-1时,信号sig将发送给调用者进程有权限发送的每一个进程,除了1号进程和自身之外。
 
好了,上面理论较多,先简单看下,下面开始用代码来进行说明,举一个子进行程父进程发送信号的例子:
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h> #include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h> #define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while() void handler(int sig);
int main(int argc, char *argv[])
{
if (signal(SIGUSR1, handler) == SIG_ERR)//注册了一个可靠信号
ERR_EXIT("signal error");
pid_t pid = fork();
if (pid == -)
ERR_EXIT("fork error"); if (pid == )
{
kill(getppid(), SIGUSR1);//向父进程发送一个信号
exit(EXIT_SUCCESS);
} sleep(5);//父进程睡眠五秒
return ;
} void handler(int sig)
{
printf("recv a sig=%d\n", sig);
}

编译运行:

原因是由于sleep函数会被信号所打断而返回,在打断返回之前会先处理信号,所以就没有出现了我们的预期,那如果要实现真正睡眠5秒怎么做呢?可以查看sleep函数的man帮助:

这时再看效果:
可见通过这种取巧的办法就解决了我们所遇到的问题。
下面来看一下这个情况,也就是给进程组发送信号:
首先查看一下怎么得到进程组ID:
下面看下具体代码:
运行效果:
解释一下程序,之所以打印出两条语句,是由于注册信号是在fork()之前,所以子进程会继承父进程的信号所安装的程序,也就是子进程中也安装了这个信号,而子进程向进程组发送了一个信号,则每个进程都会收到信号,当子进程收到时,会打印一条语句,然后立马退出了,而父进程同样也会收到,但是它会sleep五秒后才退出,所以才出现了如上效果。
另外向父进程发送信号还有另外一种等价的使用方法:
代码如下:
具体效果这就不演示了,一样。
查看一下帮助:
 
这个函数会在之后学到,先认识一下。
pause
直接用代码来进行说明,这样就会很容易理解了:
先回顾一下之前的一个代码,然后利用pause进程改装:
运行效果:
而比较好的方式是采用我们要学的这个pause函数来让进程挂起,直到一个信号被捕获了,代码调整如下:
看下效果:
可以很清楚的看到,当收到信号时,则pause函数就被返回了,这样的做法就会比较好,在信号没发送之前让进程挂起,信号处理完,则就返回了。
好了,今天的内容学到这,下节再见!!

linux系统编程之信号(二)的更多相关文章

  1. linux系统编程之信号(七)

    今天继续学习信号,主要是学习关于时间和定时器相关的函数的使用,关于这个实际上有很多内容,这里先简要进行说明,等之后再慢慢进行相关深入,也主要是为接下来要做的一个综合linux系统编程的例子做准备,好了 ...

  2. linux系统编程之信号(一):中断与信号

    一,什么是中断? 1.中断的基本概念 中断是指计算机在执行期间,系统内发生任何非寻常的或非预期的急需处理事件,使得CPU暂时中断当前正在执行的程序而转去执行相应的事件处理程序,待处理完毕后又返回原来被 ...

  3. linux系统编程之信号(二):信号处理流程(产生、注册、注销、执行)

        对于一个完整的信号生命周期(从信号发送到相应的处理函数执行完毕)来说,可以分为三个阶段: 信号诞生 信号在进程中注册 信号在进程中的注销 信号处理函数执行 1    信号诞生     信号事件 ...

  4. linux系统编程之信号(三):信号安装、signal、kill,arise讲解

    一,信号安装 如果进程要处理某一信号,那么就要在进程中安装该信号.安装信号主要用来确定信号值及进程针对该信号值的动作之间的映射关系,即进程将要处理哪个信号:该信号被传递给进程时,将执行何种操作. li ...

  5. linux系统编程之信号(八):三种时间结构及定时器setitimer()详解

    一,三种时间结构 time_t://seconds   struct timeval { long tv_sec; /* seconds */ long tv_usec; /* microsecond ...

  6. linux系统编程之信号(七):被信号中断的系统调用和库函数处理方式

        一些IO系统调用执行时, 如 read 等待输入期间, 如果收到一个信号,系统将中断read, 转而执行信号处理函数. 当信号处理返回后, 系统遇到了一个问题: 是重新开始这个系统调用, 还是 ...

  7. linux系统编程之信号(六):信号发送函数sigqueue和信号安装函数sigaction

    一,sigaction() #include <signal.h> int sigaction(int signum,const struct sigaction *act,struct ...

  8. linux系统编程之信号(五):信号集操作函数,信号阻塞与未决

    一,信号集及相关操作函数 信号集被定义为一种数据类型: typedef struct { unsigned long sig[_NSIG_WORDS]: } sigset_t 信号集用来描述信号的集合 ...

  9. linux系统编程之信号:信号发送函数sigqueue和信号安装函数sigaction

    信号发送函数sigqueue和信号安装函数sigaction sigaction函数用于改变进程接收到特定信号后的行为. sigqueue()是比较新的发送信号系统调用,主要是针对实时信号提出的(当然 ...

随机推荐

  1. [LeetCode] 340. Longest Substring with At Most K Distinct Characters 最多有K个不同字符的最长子串

    Given a string, find the length of the longest substring T that contains at most k distinct characte ...

  2. 分享一下我的个人微信小程序

    分享一下我的个人微信小程序 1.有我平时整理的一些小程序相关的技术,供大家参考. 2.有几个好玩的例子 有问题可以一起参考

  3. Javaweb的概念与C/S、B/S体系结构

    大家好,乐字节的小乐又来了,今天的文章是接上次<客户端请求服务器端通信, Web 编程发展基础|乐字节>,这次是讲述Javaweb的介绍和C/S.B/S体系结构. 一.Javaweb的概念 ...

  4. 重回ubutntu12.04小记(装完ubuntu做的几件事)

    原来一直是在windows下用虚拟机跑redhat 和debian 做实验和一些工程,以前也装过ubuntu和windows双系统,但是换电脑后,就一直懒得捣鼓了. 现在,由于长期需要在linux上做 ...

  5. Mysql查看优化后的SQL 语句

    EXPLAIN  EXTENDED 1先执行 EXPLAIN  EXTENDED 2 show warnings: EXPLAIN EXTENDED SELECT * FROM `receivable ...

  6. 端口占用问题:java.net.BindException: Address already in use: bind

    解决方法 方法一:换一个端口 若仍然想要使用该端口,则可以将占用该端口的进程杀死即可. 方法二:杀死占用该端口的进程 若仍然想要使用该端口,则可以将占用该端口的进程杀死即可 查找端口被占用的进程id ...

  7. 分布式全文搜索引擎(ElasticSearch)

    1. ElasticSearch介绍(简称ES) ES即为了解决原生Lucene使用的不足,优化Lucene的调用方式,并实现了高可用的分布式集群的搜索方案. 首先,ES的索引库管理支持依然是基于Ap ...

  8. openstack-nova源码之阅读流程

    以创建虚拟机为例 1.项目入口setup.cfg文件 2.根据nova-compute = nova.cmd.compute:main找到功能入口 3.nova/api/openstack/compu ...

  9. 创建包含CRUD操作的Web API接口-第一部

    在这里,我们将创建一个新的Web API项目,它将使用实体框架实现Get,POST.PUT和DELETE方法来实现CRUD操作. 首先,在Visual Studio 2013 for Web expr ...

  10. Hadoop 系列(六)—— HDFS 常用 Shell 命令

    一.基本命令 打开 Hbase Shell: # hbase shell 1.1 获取帮助 # 获取帮助 help # 获取命令的详细信息 help 'status' 1.2 查看服务器状态 stat ...