进程间通信_04信号

一 概述

信号的作用是通知进程某一特定事件的发生,是一种软件中断。采用异步处理机制,即当信号发送到某个进程中的时候,操作系统会中断进程的正常处理流程,转而去进入信号处理函数进行操作,等信号处理函数完成之后,返回中断处继续执行。

信号的发送:硬件产生(按键 或者 硬件错误) 、软件产生(程序调用kill、alarm等函数)

信号的处理:用户自定义函数处理、系统默认方式处理、忽略。

二 常见的信号

"动作(Action)"栏 的 字母 有 下列 含义:

A  缺省动作是结束进程.

B  缺省动作是忽略这个信号.

C  缺省动作是结束进程, 并且核心转储.

D  缺省动作是停止进程.

E  信号不能被捕获.

F  信号不能被忽略.

信号 动作 说明
SIGINT 2 A 从键盘输入的中断
SIGQUIT 3 C 从键盘输入的退出
SIGILL 4 C 无效硬件指令
SIGABRT 6 C 非正常终止, 可能来自 abort(3)
SIGFPE 8 C 浮点运算例外
SIGKILL 9 AEF 杀死进程信号
SIGSEGV 11 C 无效的内存引用
SIGPIPE 13 A 管道中止: 写入无人读取的管道
SIGALRM 14 A 来自 alarm(2) 的超时信号
SIGTERM 15 A 终止信号
SIGUSR1 30,10,16 A 用户定义的信号 1
SIGUSR2 31,12,17 A 用户定义的信号 2
SIGCHLD 20,17,18 B 子进程结束或停止
SIGCONT 19,18,25 继续停止的进程
SIGSTOP 17,19,23 DEF 停止进程
SIGTSTP 18,20,24 D 终端上发出的停止信号
SIGTTIN 21,21,26 D 后台进程试图从控制终端(tty)输入
SIGTTOU 22,22,27 D 后台进程试图在控制终端(tty)输出
信号 动作 说明
SIGPOLL A I/O就绪事件 (Sys V). 等同于SIGIO
SIGPROF 27,27,29 A 系统资源定时器(Profiling timer)超时 
SIGSYS 12,-,12 C 用错误参数调用系统例程 (SVID)
SIGTRAP 5 C 跟踪/断点自陷
SIGURG 16,23,21 B 套接口上出现 urgent 情况 (4.2 BSD)
SIGVTALRM 26,26,28 A 虚拟超时时钟 (4.2 BSD)
SIGXCPU 24,24,30 C 超过了CPU时间限制 (4.2 BSD)
SIGXFSZ 25,25,31 C 超过了文件大小限制 (4.2 BSD)
信号 动作 说明
SIGEMT 7,-,7
SIGSTKFLT -,16,- A 协处理器堆栈错误
SIGIO 23,29,22 A I/O 有效信号 (4.2 BSD)
SIGCLD -,-,18 等同于 SIGCHLD
SIGPWR 29,30,19 A 电源无效 (System V)
SIGINFO 29,-,- 等同于 SIGPWR
SIGLOST -,-,- A 文件锁丢失
SIGWINCH 28,28,20 B 窗口大小调整信号 (4.3 BSD, Sun)
SIGUNUSED -,31,- A 未使用的信号 (将成为 SIGSYS)

三 信号的产生

1 键盘产生

ctrl+c 产生 SIGINT 信号

ctrl+z 产生 SIGSTP 信号

2 shell命令产生

kill -9 15212 表示发送信号9(SIGKILL)给pid为15212的进程。

3 调用函数产生

(1) kill向进程发送实时信号(包括自己)

#include <sys/types.h>
#include <signal.h>

int kill( pid_t pid,     //发送给哪个进程
          int sig );     //发送什么信号,见"常见的信号"
//参数pid:>0  表示发送给特定的进程
//         0   表示发送给所有和发送信号进程在同一个进程组的进程
//        <0  表示发送给abs(pid)对应的进程组中的所有进程
//返回值:0(发送成功)、-1(发送失败,失败信息见errno)


(2) 比较新的带参数的信号发送函数,sigqueue(), 一般配合sigaction()函数使用


#include <sys/types.h>
#include <signal.h>
int sigqueue(pid_t pid,                         //对那个进程发送
                  int sig,                      //发送什么信号
                  const union sigval val);      //处理函数中需要携带什么参数?
//返回值:成功返回0;错误返回-1

(3) 调用raise函数像自己立即发送信号,等价于 kill(getpid(), signo);


#include <signal.h>
int raise(int signo);
//返回值:成功返回 0;否则返回 -1

(4) 调用abort()函数实时发送SIGABORT()信号


#include <stdlib.h>
void abort(void);

(5) alarm定时向自己发送SIGALRM信号


#include <unistd.h>

unsigned int alarm( unsigned int seconds );
//参数seconds: >0 定时seconds秒之后产生SIG_ALRM信号
//             =0 不在产生信号(等于关闭闹钟)

四 信号的捕捉

1 由系统捕捉,程序不做处理,此时会由系统采用默认方法处理。

2 程序捕捉

(1)  没有参数的信号处理

#include <signal.h>
typedef void(* sighandler_t)(int);
sighandler_t signal(int signal,             //信号
                    sighandler_t handler);  //信号对应的处理函数

handler取值:如果对信号不做处理,直接忽略。 取值为 SIG_IGN

如果采用系统默认方式处理信号。 取值为 SIG_DFL

如果,需要执行操作用户自定义的操作,则取值为用户定义的 函数指针

(2) 有参数的信号处理,和一般和sigqueue()配合使用

#include <signal.h>
int sigaction(int signo,                                 //信号,为除SIGKILL及SIGSTOP外的任何一个信号;
                  const struct sigaction *act,           //对信号的处理结构体
                  struct sigaction *oact);               //用来保存原来对相应信号的处理,可以置为NULL

//struct sigaction结构体原型:
struct sigaction
{
    void (*sa_handler)(int signo) ;                                    //只有信号值为参数的处理函数
    void (*sa_sigaction)(int signu, siginfo_t *info, void *act) ;      //可以携带siginfo_t结构体参数的处理函数,act参数保留不用
    sigset_t sa_mask;                                                  //指定信号处理过程中哪些信号被阻塞,默认是当前正在处理的信号
    int sa_flags;                                                      //信号处理相关标志位,比如:传递信息的时候置为SA_SIGINFO
    void (*sa_restore)(void);                                          //POSIX不在支持,忽略不用
}

//其中,siginfo_t 的原型:
siginfo_t {
    int si_signo;          /* Signal number */
    int si_errno;           /* An errno value */
    int si_code;           /* Signal code */
    pid_t si_pid;          /* Sending process ID */
    uid_t si_uid;          /* Real user ID of sending process */
    int si_status;         /* Exit value or signal */
    clock_t si_utime;      /* User time consumed */
    clock_t si_stime;      /* System time consumed */
    sigval_t si_value;     /* Signal value */
    int si_int;                 /* POSIX.1b signal */
    void * si_ptr;             /* POSIX.1b signal */
    void * si_addr;        /* Memory location which caused fault */
    int si_band;            /* Band event */
    int si_fd;                  /* File descriptor */
}

//sigval就是携带的参数信息,可以是int型也可以是指针。
union sigval
{
    int sival_int;
    void *sival_ptr;
}

五 使用实例

1 没有参数的信号

/*************************************************************************
    > File Name: testsignal.c
    > Author: qiaozp
    > Mail: [email protected]
    > Created Time: 2014-9-18 17:12:01
    > Step: 1 定义信号处理函数
            2 绑定信号 和 处理函数
            3 发出信号
 ************************************************************************/
#include <signal.h>
#include<iostream>
using namespace std;

//1 定义信号处理函数
void dealSignal(int signo)
{
    cout << "收到不带参数的信号 : " << signo << endl;
    return ;
}

int main()
{
    //2 绑定信号 和 处理函数
    signal(SIGINT, dealSignal);

    sleep(3);

    //3 发出信号
    raise(SIGINT);

    return 0;
}

2 有参数的信号

/*************************************************************************
    > File Name: testsigaction.c
    > Author: qiaozp
    > Mail: [email protected]
    > Created Time: 2014-9-18 17:12:01
    > Step: 1 定义信号处理函数
            2 绑定信号和处理函数
            3 发出信号,携带参数
 ************************************************************************/
#include <signal.h>
#include<iostream>
using namespace std;

//1 定义信号处理函数
void dealSigAction(int signo, siginfo_t* info, void *)
{
    cout << "收到带参数的信号 : " << signo << endl;
    cout << "参数信息是 : " << info->si_value.sival_int << endl;
    return ;
}

int main()
{
    struct sigaction sigAction;
    sigAction.sa_sigaction = dealSigAction;
    sigAction.sa_flags = SA_SIGINFO;//这个是传参的开关,需要设置,否则参数传不过去

    //2 绑定信号 和 处理函数
    if (sigaction(SIGTSTP, &sigAction, NULL) != 0)
    {
        cout << "绑定信号处理函数失败" << endl;
    }

    sleep(3);

    union sigval info;
    info.sival_int = 10;
    //3 发送信号
    if (sigqueue(getpid(), SIGTSTP, info) != 0)
    {
        cout << "发送信号失败" << endl;
    }

    return 0;
}

时间: 2024-08-07 15:55:16

进程间通信_04信号的相关文章

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

信号及信号来源 什么是信号 信号是UNIX和Linux系统响应某些条件而产生的一个事件.接收到该信号的进程会对应地採取一些行动.通常信号是由一个错误产生的. 但它们还能够作为进程间通信或修改行为的一种方式,明白地由一个进程发送给还有一个进程.一个信号的产生叫生成.接收到一个信号叫捕获. 信号本质 信号是在软件层次上对中断机制的一种模拟,在原理上.一个进程收到一个信号与处理器收到一个中断请求能够说是一样的. 信号是异步的.一个进程不必通过不论什么操作来等待信号的到达,其实,进程也不知道信号究竟什么

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

什么是信号? 信号是 Linux 进程间通信的最古老的方式.信号是url=474nN303T2Oe2ehYZjkrggeXCaJPDSrmM5Unoh4TTuty4wSgS0nl4-vl43AGMFbo0_5uH5OQFr_vaRJaZ-3lq_" style="color:rgb(202,0,0); text-decoration:none">软件中断,它是在软件层次上对中断机制的一种模拟,是一种异步通信的方式 . 信号能够导致一个正在执行的进程被还有一个正在执行的异

Linux进程间通信(三) - 信号

什么是信号 软中断信号(signal,又简称为信号)用来通知进程发生了异步事件.在软件层次上是对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的.信号是进程间通信机制中唯一的异步通信机制,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达.进程之间可以互相通过系统调用kill发送软中断信号.内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件.信号机制除了基本通知功能外,还可以传递附加信息. 收到信号的进程对各种信

深入理解进程间通信之信号

信号及信号源 信号本质 信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的.信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达. 信号是进程间通信机制中唯一的异步通信机制,可以看作是异步通知,通知接收信号的进程有哪些事情发生了.信号机制经过POSIX实时扩展后,功能更加强大,除了基本通知功能外,还可以传递附加信息. 信号来源 信号事件的发生有两个来源:硬件来源(比如我们按下了键盘或者其它硬件故

进程间通信之信号

说起信号,就像是一个软中断一样,就是一个信号来了以后我们程序中断当前执行的代码,找到之前注册过的相应信号的执行代码进行处理.其实我们使用的非常的广泛了,就像我们在终端里面要停止一个进程的运行,我们会同时按下ctrl+C的按键来终止程序,这个就是一个信号,是停止信号,是标号为9的信号,我们可以使用kill -l的命令来查看我们系统支持的信号.很多信号的处理都有系统默认的方式进行解决,所以我们在编程中并没有对9号信号进行处理,我们的程序却会在ctrl+C的信号到来的时候终止程序.一般Linux系统中

详解linux进程间通信-信号

前言:之前说看<C++ Primer >暂时搁浅一下,迷上公司大神写的代码,想要明白,主要是socket.进程间通信! 知道进程间通信:信号.信号量.管道.消息队列.共享内存(共享存储),也能写些简单代码进行通信,但不知道应用在哪?感觉很多小伙伴跟我有类似经历吧? 一.应用实例: 要去linux设备上去添加.改密用户:本地去linux设备添加用户,用socket实现,其实大神改的ssh源码来实现的,这不是我要讲的重点,而我要讲的是准备过程,去登陆linux设备,要准备好:管理员.密码等. 简略

进程间通信和线程间通信

进程间通信: # 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用.进程的亲缘关系通常是指父子进程关系.# 有名管道 (named pipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信.# 信号量( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问.它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源.因此,主要作为进程间以及同一进程内不同线程之间的同步手段.#

Linux进程间通信——使用共享内存(转)

这篇文章将讲述别一种进程间通信的机制--信号量.注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物.有关信号的更多内容,可以阅读我的另一篇文章:Linux进程间通信--使用信号.下面就进入信号量的讲解. 一.什么是信号量 为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域.临界区域是指执行数据更新的代码需要独占式地执行.而信号量就可以提供这样的一种访问机制,让一个临界区同

Linux进程间通信——使用信号量(转)

这篇文章将讲述别一种进程间通信的机制--信号量.注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物.有关信号的更多内容,可以阅读我的另一篇文章:Linux进程间通信--使用信号.下面就进入信号量的讲解. 一.什么是信号量 为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域.临界区域是指执行数据更新的代码需要独占式地执行.而信号量就可以提供这样的一种访问机制,让一个临界区同