Linux系统种用于进程间通讯的一种操作----信号

1、信号
    信号是Linux系统种用于进程间通讯或者操作的一种机制。这个信号可以在任何时候发送给一个进程,无需制定该进程的状态。
    如果说这个进程么有在执行的状态,内核可以先把这个信号保存下来。当进程恢复运行再把这个信号发送给它。信号也是可以
    设置成阻塞的状态,这个信号的传递就会延迟,当阻塞的状态取消之后,才可以被进程接收到。
    信号他是软件层面对中断机制的一种模拟,是一个异步通讯的过程。

    信号的来源:
        1)硬件来源,例如我们按下了ctrl+c,就产生了一个中断的信号。
        2)软件的来源,使用系统调用,或者通过命令发送信号,常见的发送信号的系统函数:kill 

    如何处理我们收到的信号:
        1)执行默认的操作,Linux系统对每一种信号都有默认的操作方式。
        2)捕获这个信号,定义信号的处理函数,当接收到这个信号,我们怎么处理?你想怎么处理就怎么处理。
        3)忽略这个信号,就是不对这个信号做处理。
        有两个信号是应用程序无法捕获和忽略的信号,SIGKILL  SEGSTOP.

    系统中的信号定义在这个地方:/usr/include/i386-linux-gnu/bits/signum.h

/* Signals.  */
#define SIGHUP      1   /* Hangup (POSIX).  控制中断挂起的时候 */
#define SIGINT      2   /* Interrupt (ANSI).从键盘上接受到的中断信号,ctrl+c    */
#define SIGQUIT     3   /* Quit (POSIX).    ctrl+d   */
#define SIGILL      4   /* Illegal instruction (ANSI). 非法指令  */
#define SIGTRAP     5   /* Trace trap (POSIX). 调试程序,跟踪  */
#define SIGABRT     6   /* Abort (ANSI).   放弃 */
#define SIGIOT      6   /* IOT trap (4.2 BSD).   */
#define SIGBUS      7   /* BUS error (4.2 BSD). 总线错误   */
#define SIGFPE      8   /* Floating-point exception (ANSI). 浮点运算错误 */
#define SIGKILL     9   /* Kill, unblockable (POSIX).   杀死一个进程,该信号不能被阻塞、处理或者忽略 */
#define SIGUSR1     10  /* User-defined signal 1 (POSIX) .  */
#define SIGSEGV     11  /* Segmentation violation (ANSI).  */
#define SIGUSR2     12  /* User-defined signal 2 (POSIX). 用户定义的信号  */
#define SIGPIPE     13  /* Broken pipe (POSIX).  管段出错 */
#define SIGALRM     14  /* Alarm clock (POSIX).  闹钟时间  */
#define SIGTERM     15  /* Termination (ANSI).  中止  */
#define SIGSTKFLT   16  /* Stack fault.         栈出错   */
#define SIGCLD      SIGCHLD /* Same as SIGCHLD (System V). 子进程状态发送改变  */
#define SIGCHLD     17  /* Child status has changed (POSIX).  子进程的状态发生改变 ,当子进程退出的时候,
        向父进程发送此信号,如果父进程正在运行wait函数,就会被唤醒,如果没有wait函数,父进
        程就不会捕获这个信号,此时子进程就会变成僵尸进程            */
#define SIGCONT     18  /* Continue (POSIX).     继续运行信号  */
#define SIGSTOP     19  /* Stop, unblockable (POSIX).  停止信号  该信号不能被阻塞、处理或者忽略*/
#define SIGTSTP     20  /* Keyboard stop (POSIX).   键盘停止 */
#define SIGTTIN     21  /* Background read from tty (POSIX).  后台读取tty */
#define SIGTTOU     22  /* Background write to tty (POSIX).    后台写tty */
#define SIGURG      23  /* Urgent condition on socket (4.2 BSD).   */
#define SIGXCPU     24  /* CPU limit exceeded (4.2 BSD).  */
#define SIGXFSZ     25  /* File size limit exceeded (4.2 BSD).  */
#define SIGVTALRM   26  /* Virtual alarm clock (4.2 BSD).  */
#define SIGPROF     27  /* Profiling alarm clock (4.2 BSD).  */
#define SIGWINCH    28  /* Window size change (4.3 BSD, Sun). 窗口大小发生改变  */
#define SIGPOLL     SIGIO   /* Pollable event occurred (System V).  */
#define SIGIO       29  /* I/O now possible (4.2 BSD).  */
#define SIGPWR      30  /* Power failure restart (System V).   */
#define SIGSYS      31  /* Bad system call.  */

 

2、信号的发送
    通过系统提供的一些函数,可以发送一些信号:
   
    kill ,发送一个SIGKILL给进程。
    raise  发送信号给进程或者给自己
    alarm  定时器的事件到,向进程发送一个SIGALRM
    pause  没有捕获到信号之前一直是挂起
    signal() 当捕获到某一种信号之后,绑定对应的处理函数,然后自定义去处理这个信号。
     
     #include <signal.h>
    
       sigset_t *set先定义信号的集合,

       int sigemptyset(sigset_t *set); 清空该集合

       int sigfillset(sigset_t *set);   初始化信号集合为所有信号

       int sigaddset(sigset_t *set, int signum); 将指定的信号,加到对应的信号集合里面

       int sigdelset(sigset_t *set, int signum); 把指定的信号从这个集合里面去掉

       int sigismember(const sigset_t *set, int signum); 查询指定的信号,在不在这个集合里面。

    以上函数,成功就返回0,失败返回-1,并且对应的错误码会被设置。

3、信号的处理
    可以使用调用signal这个函数,将我们需要捕获的信号,和我们自定义的这个处理函数绑定起来,
    当捕获到绑定的信号的时候处理函数就会被调用。

       #include <signal.h>

       typedef void (*sighandler_t)(int);

       sighandler_t signal(int signum, sighandler_t handler);

 

4、信号的阻塞
    当我们不想将收到的信号,立刻处理的时候,但是我们也不想把这个信号忽略掉,希望延时一段时间再去处理它,
    这个时候,就需要用到信号的阻塞来处理。

       #include <signal.h>
    
    sigset_t *set先定义信号的集合,

       int sigemptyset(sigset_t *set); 清空该集合

       int sigfillset(sigset_t *set);   初始化信号集合为所有信号

       int sigaddset(sigset_t *set, int signum); 将指定的信号,加到对应的信号集合里面

       int sigdelset(sigset_t *set, int signum); 把指定的信号从这个集合里面去掉

       int sigismember(const sigset_t *set, int signum); 查询指定的信号,在不在这个集合里面。

    以上函数,成功就返回0,失败返回-1,并且对应的错误码会被设置。    

    将信号变成阻塞型的信号:
    #include <signal.h>
    int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

    阻塞:SIG_BLOCK
    不阻塞:SIG_UNBLOCK

 

例子:

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

void func_ctrl_c(int sig)
{
    if(sig == SIGINT)
    {
        printf("Now you press ctrl+c\n");
    }
    if(sig == SIGQUIT)
    {
        printf("Now we get a signal SIGQUIT\n");
    }
//    signal(SIGINT,SIG_DFL); //当我们捕获到绑定的信号之后,也可以调用系统默认的方式去处理它。
}

int main()
{
    int i;
    sigset_t set;
    signal(SIGINT,func_ctrl_c);
    signal(SIGQUIT,func_ctrl_c);

    if(sigemptyset(&set) < 0) //清空该集合
    {
        perror("sigemptyset error");
        exit(-1);
    }
    if(sigaddset(&set,SIGINT) < 0) //将指定的信号加到对应的信号集合里面
    {
        perror("sigaddset fail");
        exit(-1);
    }
    if(sigprocmask(SIG_BLOCK,&set,NULL) < 0)//将信号变成阻塞型的信号
    {
        perror("set block fail");
        exit(-1);
    }

    for(i=0;i<3;i++)
    {
        printf("Now is block the signal\n");
        sleep(3);
    }
    if(sigprocmask(SIG_UNBLOCK,&set,NULL) < 0)
    {
        perror("set block fail");
        exit(-1);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值