十五、Linux系统编程-信号(二)信号分类、可靠信号与不可靠信号、信号发送 pause

一、信号分类

(1)、可靠信号不可靠信号

linux信号机制基本上是从unix系统中继承过来的。早期unix系统中的信号机制比较简单和原始,后来在实践中暴露出一些问题,它的主要问题是:
  1. 进程每次处理信号后,就将对信号的响应设置为默认动作。在某些情况下,将导致对信号的错误处理;因此,用户如果不希望这样的操作,那么就要在信号处理函数结尾再一次调用signal(),重新安装该信号。
  2. 早期unix下的不可靠信号主要指的是进程可能对信号做出错误的反应以及信号可能丢失。
  3. linux支持不可靠信号,但是对不可靠信号机制做了改进:在调用完信号处理函数后,不必重新调用该信号的安装函数(信号安装函数是在可靠机制上的实现)。因此,linux下的不可靠信号问题主要指的是信号可能丢失
        随着时间的发展,实践证明了有必要对信号的原始机制加以改进和扩充。所以,后来出现的各种unix版本分别在这方面进行了研究,力图实现"可靠信 号"。由于原来定义的信号已有许多应用,不好再做改动,最终只好又新增加了一些信号,并在一开始就把它们定义为可靠信号,这些信号支持排队,不会丢失。
        同 时,信号的发送和安装也出现了新版本:信号发送函数sigqueue()及信号安装函数sigaction()。

(2)、实时信号非实时信号

        早期Unix系统只定义了32种信号,Rethat7.2支持64种信号,编号0-63(SIGRTMIN=31,SIGRTMAX=63),将来可能进一步增加,这需要得到内核的支持。前32种信号已经有了预定义值,每个信号有了确定的用途及含义,并且每种信号都有各自的缺省动作。如按键盘的CTRL ^C时,会产生SIGINT信号,对该信号的默认反应就是进程终止。1 ~ 31的信号为传统UNIX支持的信号,是不可靠信号(非实时的), 后32个信号表示实时信号,等同于前面阐述的可靠信号。这保证了发送的多个实时信号都被接收。实时信号是POSIX标准的一部分,可用于应用进程。
         非实时信号都不支持排队,都是不可靠信号;实时信号都支持排队,都是可靠信号。

二、信号发送 

(1)、kill 向某进程发送信号

函数声明:

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

进程号,信号代码

If pid is positive, then signal sig is sent to the process with the  ID specified by pid.


If pid equals 0, then sig is sent to every process in the process group of the calling process.


If pid equals -1, then sig is sent to every process for which the calling  process  has  permission  to  send  signals,  except for process 1(init), but see below.(除1号进程和自身)


If pid is less than -1, then sig  is  sent  to  every  process  in  the process group whose ID is -pid.


If  sig  is 0, then no signal is sent, but error checking is still performed; this can be used to check for the existence of a process ID  or process group ID.

返回值:

成功返回0,失败返回-1,并设置errno.
(2)、raise 给本进程发送信号

函数声明:

#include <signal.h>
int raise(int sig);
函数参数:

信号代码

返回值:

成功返回0,失败返回非0
(3)、killpg 给进程组发送信号

函数声明:

#include <signal.h>
int killpg(int pgrp, int sig);
函数参数: 进程组号,信号代码

返回值:同kill

(4)、sigqueue 给进程发送信号,支持排队,可附带信息

函数声明:

<pre name="code" class="cpp">#include <signal.h>
int sigqueue(pid_t pid, int sig, const union sigval value);

 函数参数:进程号,信号代码,附带信息 

返回值:同kill


示例:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#define ERR_EXIT(m) \
        do \
        { \
                perror(m); \
                exit(EXIT_FAILURE); \
        }while(0)
void handle(int sig);
int main(int argc,char* argv[])
{
        if ( signal(SIGUSR1,handle) == SIG_ERR)
                ERR_EXIT("signal error");
        pid_t pid = fork();
        if (pid == -1)
                ERR_EXIT("fork error");
        if (pid == 0)
        {
                //kill(getppid(),SIGUSR1);//进程
                //kill(-getpgrp(),SIGUSR1);//进程组
                //raise(SIGUSR1);//自己
                //killpg(getpgrp(),SIGUSR1);//进程组
                exit(EXIT_SUCCESS);
        }
        int n;
        n = 5;
        do
        {
                n = sleep(n);
        }while(n > 0);
        return 0;
}

void handle(int sig)
{
        printf("recv a sig=%d\n",sig);
}

三、pause

        pause将进程置为可中断睡眠状态。然后它调用schedule(),使linux进程调度器找到另一个进程来运行。它使调用者进程挂起,直到一个信号被捕获。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值