#Linux#进程间通信# 信号(sinal)

在计算机科学中,信号是Unix、类Unix以及其他POSIX兼容的操作系统中进程间通讯的一种有限制的方式。它是一种异步的通知机制,用来提醒进程一个事件已经发生。当一个信号发送给一个进程,操作系统中断了进程正常的控制流程,此时,任何非原子操作都将被中断。如果进程定义了信号的处理函数,那么它将被执行,否则就执行默认的处理函数。

软中断信号(signal,又简称为信号)用来通知进程发生了异步事件。进程之间可以互相通过系统调用kill发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件。注意,信号只是用来通知某进程发生了什么事件,并不给该进程传递任何数据。收到信号的进程对各种信号有不同的处理方法。处理方法可以分为三类:第一种是类似中断的处理程序,对于需要处理的信号,进程可以指定处理函数,由该函数来处理。第二种方法是,忽略某个信号,对该信号不做任何处理,就象未发生过一样。第三种方法是,对该信号的处理保留系统的默认值,这种缺省操作,对大部分的信 号的缺省操作是使得进程终止。进程通过系统调用signal来指定进程对某个信号的处理行为。在进程表的表项中有一个软中断信号域,该域中每一位对应一个信号,当有信号发送给进程时,对应位置位。由此可以看出,进程对不同的信号可以同时保留,但对于同一个信号,进程并不知道在处理之前来过多少个。

信号与信号量这两个名词只有一字之差,有时候我们会很容易联想到这两个东西是不是一个东西,然而却是完全不同的两个概念。

  • 信号:是由用户、系统或者进程发送给目标进程的信息,以通知目标进程某个状态的改变或系统异常。通知进程产生了某个事件
  • 信号量信号量是一个特殊的变量,它的本质是计数器,信号量里面记录了临界资源的数目,有多少数目,信号量的值就为多少,进程对其访问都是原子操作(pv操作,p:占用资源,v:释放资源)。它的作用就是,调协进程对共享资源的访问,让一个临界区同一时间只有一个进程在访问它。用来同步进程的(用来调协进程对共享资源的访问的)

以下情况会引发信号

  • 键盘事件  如ctrl+c产生SIGINT信号,ctrl+\产生SIGQUIT信号,ctrl+z产生SIGTSTP信号
  • 硬件异常  硬件出现故障。非法访问内存(段错误)、除0(浮点数例外)、内存对齐错误(总线错误)会产生一个信号,由硬件检测并通知内核,然后内核向进程发送适当的信号,比如执行了除以零的指令,进程访问了非法内存地址,cpu的运算单元都会产生异常,内核将这个异常解释成一个个信号发送给进程。
  • 系统调用  kill、abort、raise等系统函数调用
  • 软件条件  使用定时器alarm
  • 系统命令   kill

信号是异步事件,当信号到达时,保存当前的执行环境,转去执行信号处理函数,当信号处理函数完毕,恢复现场,继续执行。

进程收到信号的三种处理方式

  • 默认:执行信号的默认处理动作,如果是系统SIGINT的话,那就会中断这个进程
  • 忽略 :信号来了我们不处理,装作没看到   SIGKILL  SIGSTOP 不能忽略
  • 捕获并处理 :当信号来了,执行我们自己写的代码提供一个信号处理函数,要求内核在处理信号时切换到用户态执行这个处理函数(捕获信号这个动作是需要我们完成的)  SIGKILL SIGSTOP 不能捕获

注册信号

typedef void  (* sighandler_t) (int);
sighandler_t signal (int signum   /*要注册的信号*/, sighandler_t handler /*信号执行函数*/);

信号捕捉

  • (1)首先在用户正常执行主控制流程由于中断,异常或系统调用而直接进入内核态进行处理处理这种异常,
  • (2)内核处理完异常就准备返回用户态了,在这之前会看当前进程有没有可以抵达的信号,如果有就对可递达的信号进行处理,
  • (3)如果信号的处理函数是用户自定义的就返回用户态去执行用户自定义的信号处理函数
  • (4)信号处理函数执行完之后,会调用一个特殊的系统调用函数sigreturn而再一次进入内核态,执行这个系统调用
  • (5)这个系统调用完成之后,就会返回主控制流程被中断的地方继续执行下面的代码
  • (6)执行主控制流程的时候如果再次遇到异常、中断或系统调用就继续回到(1),继续执行下面的流程

可靠信号和不可靠信号

扫描二维码关注公众号,回复: 10470416 查看本文章

实时信号 : 就是可靠信号
非实时信号:不可靠信号

不可靠信号

  • 1-31  都是不可靠的,会出现信号丢失现象
  • Linux的信号继承自早期的Unix信号,Unix信号的缺陷
  • 信号处理函数执行完毕,信号恢复成默认处理方式(Linux已经改进)
  • 会出现信号丢失,信号不排队

可靠信号

  • 34-64重新设计的一套信号集合
  • 不会出现信号丢失,支持排队,信号处理函数执行完毕,不会恢复成缺省处理方式

【 kill -l 】 这个命令就可以查看所有的信号啦,现在信号已经增加到65个了,但是在这里我要提一下,从33-64这些信号一般不会采用,这是为了区分可靠信号和不可靠信号而新增加的32个信号。

cll@cll-linux:~ $ kill -l
 1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
 6) SIGABRT	 7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
11) SIGSEGV	12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
16) SIGSTKFLT	17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
21) SIGTTIN	22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
26) SIGVTALRM	27) SIGPROF	28) SIGWINCH	29) SIGIO	30) SIGPWR
31) SIGSYS	34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
63) SIGRTMAX-1	64) SIGRTMAX	

【man 7 signal 】 这个命令使用man手册查看,因为在第七页,所以直接用 man 7。常用标准信号如下:

Standard signals
       Linux  supports the standard signals listed below.  Several signal num‐
       bers are architecture-dependent, as indicated in  the  "Value"  column.
       (Where three values are given, the first one is usually valid for alpha
       and sparc, the middle one for x86, arm, and most  other  architectures,
       and  the  last one for mips.  (Values for parisc are not shown; see the
       Linux kernel source for signal numbering on that  architecture.)   A  -
       denotes that a signal is absent on the corresponding architecture.)

       First the signals described in the original POSIX.1-1990 standard.

       Signal     Value     Action   Comment
       ──────────────────────────────────────────────────────────────────────
       SIGHUP        1       Term    Hangup detected on controlling terminal
                                     or death of controlling process
       SIGINT        2       Term    Interrupt from keyboard
       SIGQUIT       3       Core    Quit from keyboard
       SIGILL        4       Core    Illegal Instruction
       SIGABRT       6       Core    Abort signal from abort(3)
       SIGFPE        8       Core    Floating point exception
       SIGKILL       9       Term    Kill signal
       SIGSEGV      11       Core    Invalid memory reference
       SIGPIPE      13       Term    Broken pipe: write to pipe with no
                                     readers
       SIGALRM      14       Term    Timer signal from alarm(2)
       SIGTERM      15       Term    Termination signal
       SIGUSR1   30,10,16    Term    User-defined signal 1
       SIGUSR2   31,12,17    Term    User-defined signal 2
       SIGCHLD   20,17,18    Ign     Child stopped or terminated
       SIGCONT   19,18,25    Cont    Continue if stopped
       SIGSTOP   17,19,23    Stop    Stop process
       SIGTSTP   18,20,24    Stop    Stop typed at terminal
       SIGTTIN   21,21,26    Stop    Terminal input for background process
       SIGTTOU   22,22,27    Stop    Terminal output for background process

       The signals SIGKILL and SIGSTOP cannot be caught, blocked, or ignored.

       Next  the  signals  not  in  the POSIX.1-1990 standard but described in
 Manual page signal(7) line 134 (press h for help or q to quit)

在以上的信号中,

程序不可捕获、阻塞或忽略的信号 9) SIGKILL,19) SIGSTOP
不能恢复至默认动作的信号 4) SIGILL,5) SIGTRAP
默认会导致进程流产的信号 6) SIGABRT,7) SIGBUS,8) SIGFPE,4) SIGILL,29) SIGIO,3) SIGQUIT,11) SIGSEGV,5) SIGTRAP,24) SIGXCPU,25) SIGXFSZ
默认会导致进程退出的信号 14) SIGALRM,1) SIGHUP,2) SIGINT,9) SIGKILL,13) SIGPIPE,SIGPOLL(当某个事件发送给Pollable Device的时候发送, 部分系统),27) SIGPROF,31) SIGSYS,15) SIGTERM,10) SIGUSR1,12) SIGUSR2,26) SIGVTALRM
默认会导致进程停止的信号 19) SIGSTOP,20) SIGTSTP,21) SIGTTIN,22) SIGTTOU
默认进程忽略的信号 17) SIGCHLD,30) SIGPWR,23) SIGURG,28) SIGWINCH
  • 此外,SIGIO在SVR4是退出,在4.3BSD中是忽略;
  • SIGCONT在进程挂起时是继续,否则是忽略,不能被阻塞。

默认动作:

  •               Term:终止进程
  •               Ign: 忽略信号 (默认即时对该种信号忽略操作)
  •               Core:终止进程,生成Core文件。(查验进程死亡原因, 用于gdb调试)
  •               Stop:停止(暂停)进程
  •               Cont:继续运行进程

kill、killall、kill(pid_t pid, int sig);

kill、killall

这两个命令是用来向进程发送信号的。kill 命令需要进程号作为参数,而 killall 需要进程名称。另外,还可以在这两个命令后附加要发送信号序号作为参数。默认情况下,它们都向相关进程发送信号 15 (TERM)。例如,如果你想要终止 PID 为 666的进程,请输入以下命令:

kill 666

如果您要向它发送信号 9 (SIGKILL),请输入:

kill -9 666

假设您知道想要终止的进程的命令名称。您可以通过该名称来终止它,而不用再使用 ps 找出该进程的进程号:

killall -9 your-process-name

kill(pid_t pid, int sig);

用于向任何进程组或进程发送信号。

头文件用法:

#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);

参数:
pid:可能选择有以下四种

  • 1. pid大于零时,pid是信号欲送往的进程的标识。
  • 2. pid等于零时,信号将送往所有与调用kill()的那个进程属同一个使用组的进程。
  • 3. pid等于-1时,信号将送往所有调用进程有权给其发送信号的进程,除了进程1(init)。
  • 4. pid小于-1时,信号将送往以-pid为组标识的进程。

sig:准备发送的信号代码,假如其值为零则没有任何信号送出,但是系统会执行错误检查,通常会利用sig值为零来检验某个进程是否仍在执行。

发布了170 篇原创文章 · 获赞 207 · 访问量 459万+

猜你喜欢

转载自blog.csdn.net/xiaoting451292510/article/details/103731042