Linux进程信号之如何产生信号

标签: 信号产生 进程信号
7人阅读 评论(0) 收藏 举报
分类:

一、信号概念

在日常生活中,我们经常也会遇见信号,比如“上下课的铃声”、“十字路口的红路灯” 。而在Linux中,信号如同交通信号灯一样,它就是给操作系统或者进程提供某种信息,让操作系统或者进程做出某种对应的反应,就如同十字路口的红路灯显示红灯时,告诉行人此时应该停下……

让我们来看一下Linux系统定义的信号:
这里写图片描述
如上图所示,一共有62种信号(是不是有读者和我刚开始时一样以为有64种,哈哈哈!上当了吧!)。其中1~31为普通信号,34~64为实时信号。
每个信号都有一个编号和宏定义名称,这些宏定义可以在signal.h中找到。这些信号各自在什么条件下产生,默认的处理动作是什么,在signal(7)中都有详细说明:通过man 7 signal命令可前往查看。
这里写图片描述
二、信号产生
信号有以下四种产生方式:

* (1)在终端按下某种按键,终端驱动程序会发送信号给前台进程(eg:Ctrl+C产生SIGINT信号)
* (2)硬件异常产生信号,这些条件由硬件检测到并通知内核,然后内核向当前进程发送适当的信号
* (3)通过系统函数向进程发信号(闹钟超时产生SIGALRM信号;想读端已经关闭的管道写入数据时产生SIGPIPE信号)
* (4)软件条件产生

信号处理可选的处理动作有以下三种:

* (1)忽略此信号
* (2)执行该信号的默认处理动作
* (3)提供一个信号处理函数,要求内核在处理该信号时切换到用户态执行这个处理函数,这种方式称为捕捉(Catch)一个信号

注:9号信号SIGKILL不能被捕捉


1. 产生方式一:通过终端按键产生信号

我们先来写一个死循环的小程序:(如下图所示)
这里写图片描述
这里写图片描述
运行结果:
这里写图片描述
运行之,发现去掉信号捕捉,键入Ctrl+\ 就会发现后边多了一个core dumped
因为ctrl+C对应的是SIGINT信号,它的默认处理动作是终止进程;ctrl+\ 对应的是SIGQUIT信号,它的默认处理动作是终止进程并且Core Dump。

* Core  Dump(核心转储)

什么是Core Dump嘞? 当一个进程异常终止时,可以选择把进程的用户空间内存数据全部保存到磁盘上,文件名通常是core,这叫做Core Dump。core文件可以帮助开发者进行调试,在程序崩溃之时把内存数据dump到硬盘上,让gdb识别。可以事后调试

一般情况下,系统默认情况下是不允许生成core文件,因为对于线上服务而言,出core的过程意味着服务暂时不能正常响应,需要恢复,并且随着吐core进程的内存空间越大,这个过程就会持续很长一段时间,并且会很占内存(每重启一次进程就会有一个core文件)。同时core文件可能包含用户的密码等敏感信息,不太安全

在开发调试阶段可以用ulimit命令改变这个限制,允许产生core文件。

ulimit -c 1024   // 用ulimit命令改变shell进程的Resource Limit,允许core文件最大为1024k

ulimit -a        // 查看core文件size

用ulimit改变一下限制运行程序看看:
这里写图片描述
运行程序之:
这里写图片描述


2、产生方式二:调用系统函数向进程发信号
(1)kill函数(可以给一个指定的进程发送指定的信号)

函数原型:
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
返回值:成功返回0;错误时返回-1

还是刚才的程序,将它放在后台执行,然后用kill命令给他符SIGSEGV信号
这里写图片描述
上面的命令还可以写成 kill -11 2581 ,11是信号SIGSEGV的编号。以往遇到的段错误都是由非法内存访问产生的,而这个程序本身没错,给它发SIGSEGV也能产生段错误。

(2)raise函数(给当前进程发送指定的信号 <自己给自己发信号>)

#include <signal.h>
int raise(int sig);
返回值:成功返回0;错误时返回-1

(3)abort函数(它使当前进程接受到信号而异常终止)

#include <stdlib.h>
void abort(void);
返回值:abort函数就像exit函数一样,总会成功,所以没有返回值

3、产生方式三:由软件条件产生信号

SIGPIPE和SIGALRM信号都是由软件条件产生的信号。下面主要讲alarm函数和SIGLARM信号

alarm函数

//函数原型
#include <unistd.h>
unsigned int alarm(unsigned int seconds);

//作用机制:
调用alarm函数可以设定一个闹钟,也就是告诉内核seconds秒之后给当前进程发SIGALRM信号,该信号默认处理动作是终止当前进程

// 返回值:返回值为0或者以前设置的闹钟时间还余下的秒数

举个例子来说明一下:
某人小睡一次,设定闹钟为30分钟之后响,20分钟后被人吵醒,还想再多睡一次,于是重新设定闹钟为15分钟之后响。“以前设定的闹钟时间还余下的时间”就是10分钟。
如果seconds值为0,表示取消以前设定的闹钟,函数的返回值仍然是以前设定的闹钟时间还余下的秒数。

来写个小程序吧!(1秒之内不停地数数,1秒到了之后就被SIGALRM信号终止)

#include <stdio.h>
#include <unistd.h>
int main()
{
      int count = 10;
    alarm(1);
    for (; 1; count++)
    {
            printf("count = %d\n", count);
    }

    return 0;
}

运行结果比较难截图,我就不截验证结果了,大家自己验证哦!

查看评论

linux信号基本概念及如何产生信号

阅前须知本文的主要内容有:1.信号的基本概念(包括进程对信号的3种处理方式)2.特殊信号举例:写代码证明信号存在,并实现信号的简单捕捉3.如何产生一个信号(代码举例:mykill的实现)其中拓展知识有...
  • summy_J
  • summy_J
  • 2017-06-14 09:34:21
  • 1495

kill(),raise(),abort()函数向进程发送信号

信号的产生有3种方式: (1)通过终端快捷键产生信号(比如Ctrl+c,Ctrl+\等); (2)调用系统函数向进程发送信号(kill() ,raise(),abort()); (3)由软件条件...
  • qq_35420908
  • qq_35420908
  • 2017-04-14 21:00:11
  • 656

Linux中的信号(1)

首先,我们来看一下Linux中都有那些信号: 每个信号都有一个编号和一个宏定义名称,这些宏定义可以在signal.h中找到。 然后来看一下产生信号的条件:   ...
  • windyblankboy
  • windyblankboy
  • 2016-07-26 23:52:56
  • 1283

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

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

linux之信号产生

产生信号的条件主要有:A. 通过终端按键产生信号用户在终端按下某些键时,终端驱动程序会发送信号给前台进程,例如Ctrl-C产生SIGINT信 号,Ctrl-\产生SIGQUIT信号,Ctrl-Z产生S...
  • qq_36221862
  • qq_36221862
  • 2017-04-14 07:29:09
  • 230

Linux程序退出时的信号捕获及处理

#include #include #include #include #include #include #include #include // 程序退出时的函数操作 void...
  • ypist
  • ypist
  • 2012-04-13 14:48:41
  • 6763

Linux向进程发送信号及执行信号处理函数的时机

Linux内核中由于不同原因(例如非法地址、按下Ctrl+C、用户进程系统调用等等)向进程发送信号的函数调用路径最后公用的函数是send_signal(),这个函数位于linux-3.13/kerne...
  • Q_AN1314
  • Q_AN1314
  • 2018-01-23 21:16:59
  • 285

Linux kill --终止进程/发送信号

Linux中的kill命令用来终止指定的进程(terminate a process)的运行,是Linux下进程管理的常用命令。通常,终止一个前台进程可以使用Ctrl+C键,但是,对于一个后台进程就须...
  • mosesmo1989
  • mosesmo1989
  • 2016-04-08 10:33:14
  • 654

Linux子进程的异步等待方式(SIGCHLD信号)

当一个父进程创建一个子进程时,最好要调用wait或者waitpid函数等待子进程,不然会产生僵尸进程造成是内存泄漏的问题。一般父进程在等待子进程时有两种方式等待,一种是阻塞式等待,这时父进程不能处理自...
  • D_leo
  • D_leo
  • 2017-06-11 11:22:31
  • 520

Linux系统编程——进程间通信:信号中断处理

信号是 Linux 进程间通信的最古老的方式。信号是软件中断,它是在软件层次上对中断机制的一种模拟。信号可以导致一个正在运行的进程被另一个正在运行的异步进程中断,转而处理某一个突发事件。 “中断”在我...
  • tennysonsky
  • tennysonsky
  • 2015-06-01 18:55:43
  • 183026
    个人资料
    持之以恒
    等级:
    访问量: 1757
    积分: 346
    排名: 23万+
    最新评论