【Linux】进程信号

标签: 进程信号 发送信号 接收信号 捕捉信号
4人阅读 评论(0) 收藏 举报
分类:

一、首先,用 kill -l 命令可以查看系统定义的信号列表:
这里写图片描述
每个信号都有一个编号和一个宏定义名称,这些宏定义可以在 signal.h 中查看,例如:#define SIGINT 2 。编号34以上的信号为实时信号。

二、信号常见的三种处理方式:

(1)忽略此信号。(SIG_IGN)
(2)执行信号的默认处理动作。(SIG_DFL)
(3)提供一个信号处理函数,捕捉信号进行自定义处理。

三、信号的产生:

1、常见的几种产生信号方式:

        a.用户产生信号
        b.系统异常产生信号
        c.自定义捕捉

2、通过终端按键产生信号:

SIGINT的默认处理动作是终止进程,SIGQUIT的默认处理动作是终止进程,并且Core Dump

Core Dump (核心转储):当一个进程异常终止时,可以选择把进程的用户空间内存数据全部保存到磁盘上,文件名通常是Core,这叫做 Core Dump。


系统默认情况不予 Core 分配空间:
这里写图片描述
可使用命令 ulimit -c 1024 给Core 分配 1024个字节空间:
这里写图片描述
实例:写一个死循环

[lize-h@localhost 0409_Siganl]$ cat core_Dump.c 
#include<stdio.h>

int main()
{
    printf("pid is %d\n",getpid());
    while(1);
    return 0;
}  

这里写图片描述
3、调用系统函数向进程发信号:

(1)我们可以用 kill 命令向进程发信号:

[lize-h@localhost 0409_Siganl]$ ./a.out &     
[1] 3102
[lize-h@localhost 0409_Siganl]$ kill -SIGSEGV 3102
[lize-h@localhost 0409_Siganl]$ 
[1]+  段错误               (core dumped) ./a.out
[lize-h@localhost 0409_Siganl]$ cat core_Dump.c 
#include<stdio.h>
int main()
{
    //printf("pid is %d\n",getpid());
    while(1);
    return 0;
}

令程序在后台执行,用 kill 命令向进程发送信号,令进程异常终止,异常信息存入core文件。

(2)发送信号的函数有:

#include<signal.h>

int kill(pid_t pid,int signo);  //向任意进程发送任意信号;成功返回0,出错返回-1。
int raise(int signo);    //向自己发送任意信号;成功返回0,出错返回-1。

#include<stdlib.h>

void abort(void);   //向自己发送 abort 信号

(3)alarm函数:

#include<unistd.h>

unsigned int alarm( unsigned int seconds);
/*
调用alarm函数可设置一个闹钟;当参数seconds设置为0表示取消闹钟,返回值为以前设置的
时间剩余的秒数;当参数seconds设置为8表示8秒后触发闹钟,向当前进程发送SIGALRM信号,
该信号的默认处理动作是终止当前进程。
*/

四、阻塞信号

1、信号的相关概念:

(1)实际执行信号的处理动作称为信号递达。
(2)信号从产生到递达之间的状态,称为信号未决(pending)。
(3)进程可以选择阻塞(Block)某个信号。
(4)被阻塞的信号产生时将保持在未决状态,直到信号解除对此信号的阻塞,才执行递达的动作。
(5)阻塞和忽略不同,只要信号被阻塞就不会递达,而忽略是在递达后可选的一种处理动作。
(6)发送信号相当于更改PCB中的位图

2、在内核中的表示:
这里写图片描述
Linux信号的实现:常规信号在递达之前产生多次只计一次,而实时信号在递达之前产生多次可以依次放在一个队列里。

3、sigset_t 信号集:
未决和阻塞标志可以用相同的数据类型sigset_t来存储,sigset_t称为信号集,这个类型可以表示每个信号的“有效”或“无效”状态,在阻塞信号集中“有效”和“无效”的含义是该信号是否被阻塞,而在未决信号集中“有效”和“无效”的含义是该信号是否处于未决状态。阻塞信号集也叫做当前进程的信号屏蔽字(Signal Mask),这里的“屏蔽”应该理解为阻塞而不是忽略。

4、信号集操作函数:

#include<signal.h>

int sigemptyset(sigset_t* set); //初始化set所指向的信号集,使其中所有信号的对应bit清零。
int sigfillset(sigset_t* set);  //初始化set所指向的信号集,使其中所有信号的对应bit置1。
int sigaddset(sigset_t* set,int signo);  //在信号集中添加编号为signo的信号
int sigdelset(sigset_t* set,int signo);  //删除信号集中编号为signo的信号
   //以上四个函数成功返回0,出错返回-1。  
int sigismember(const sigset_t* set,int signo);  
//sigismember是一个布尔函数,用于判断一个信号集的有效信号中是否包含某种信号,若包含则返回1,不包含返回0,出错返回-1。


sigprocmask函数:

调用该函数可以读取或更改进程的信号屏蔽字(阻塞信号集)

#include<signal.h>
int sigprocmask(int how,const sigset_t* set,sigset_t* oset);
//若调用成功返回0,出错返回-1

如果oset为空指针,则读取进程的当前信号屏蔽字通过oset参数传出。如果set是非空指针,则更改进程的信号屏蔽字,参数how指示如何更改。如果oset和set都是非空指针,则先将原来的信号屏蔽字备份到oset里,然后根据set和how参数更改信号屏蔽字。假设当前的信号屏蔽字为mask,以下为how参数的可选值。
这里写图片描述

sigpending函数:

#include<signal.h>
int sigpending(sigset_t* set)
//读取当前进程的未决信号集,通过set参数传出。调用成功返回0,出错返回-1。

范例:

#include<stdio.h>
#include<signal.h>
#include<unistd.h>

void printsigset(sigset_t *set)
{
    int i=0;
    for(;i<32;i++)
    {
        if(sigismember(set,i))
        {
            putchar('1');
        }
        else
        {
            putchar('0'); 
        }
    }
    puts("");
}
int main()
{
    sigset_t s,p;
    sigemptyset(&s);
    sigaddset(&s,SIGINT);
    gprocmask(SIG_BLOCK,&s,NULL);
    while(1)
    {
        sigpending(&p);
        printsigset(&p);
        sleep(1);
    }
    return 0;
}

运行结果:

[lize-h@localhost 0409_Siganl]$ ./a.out
10000000000000000000000000000000
10000000000000000000000000000000
10000000000000000000000000000000
10000000000000000000000000000000
10000000000000000000000000000000
^C10100000000000000000000000000000
10100000000000000000000000000000
10100000000000000000000000000000
10100000000000000000000000000000
^Z
[1]+  Stopped                 ./a.out
[lize-h@localhost 0409_Siganl]$ 
查看评论

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

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

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

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

linux 使用信号和挂起进程

#include #include #include #include #include static int alarm_fired = 0;void ding(int sig){ alarm_fi...
  • mu_gong
  • mu_gong
  • 2005-10-12 17:02:00
  • 2888

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

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

Linux进程间通信 - 信号(signal)机制

Linux进程间通信 - 信号机制 Linux和类Linux系统下进程间通信(Inter-Process Communication, IPC)有很多种方式,包括套接字(socket),共享内存(sh...
  • junyucsdn
  • junyucsdn
  • 2016-01-14 17:36:34
  • 3305

linux:进程中信号的“3种状态 And 3张表”

高能预警本文主要介绍了信号在进程pcb中的表示方法并用代码验证其真实性。主要内容有:1.信号在进程中的表示方法:3种状态—3张表2.对上述方法进行代码验证,包括: 信号集(sigset_t)和信号屏蔽...
  • summy_J
  • summy_J
  • 2017-06-14 19:04:07
  • 382

linux进程如何捕捉信号

linux中一共有32种信号,在/usr/include/bits/signum.h 头文件中可以看到 #define    SIGHUP        1    /* Hangup (POSI...
  • wxx_13679222592
  • wxx_13679222592
  • 2017-09-29 19:11:43
  • 181

Linux 进程与信号的概念和操作 linux process and signals

信号与进程几乎控制了操作系统的每个任务。 在shell中输入ps -ef命令,我们将得到如下结果: (译者注:-e Select all processes. Identical to -...
  • qq3401247010
  • qq3401247010
  • 2017-10-18 23:30:50
  • 256

进程间通信之-信号signal--linux内核剖析(九)

信号及信号来源什么是信号信号是UNIX和Linux系统响应某些条件而产生的一个事件,接收到该信号的进程会相应地采取一些行动。通常信号是由一个错误产生的。但它们还可以作为进程间通信或修改行为的一种方式,...
  • gatieme
  • gatieme
  • 2016-03-27 13:22:21
  • 3426

Linux进程的睡眠和唤醒(一个定时信号唤醒睡眠中的进程)

突然想到Nginx中时间更新这块处理,Nginx中为了减少调用系统调用gettimeofday这个函数(因为一旦调用了系统调用,就会使得进程从用户态切换到内核态,就会发生上下文切换,这个代价很大且不值...
  • yusiguyuan
  • yusiguyuan
  • 2015-08-20 11:35:56
  • 5302
    个人资料
    持之以恒
    等级:
    访问量: 7048
    积分: 682
    排名: 7万+