zoukankan      html  css  js  c++  java
  • Linux进程间通信(2):信号

    接上一篇的内容——Linux进程间通信(1):管道

    参考书籍:《从实践中学嵌入式linux应用程序开发》(华清远见嵌入式学院)

    UNIX网络编程 卷2 进程间通信(第2版)(中文版)

    参考链接:http://www.ibm.com/developerworks/cn/linux/l-ipc/part2/index1.html

    http://www.ibm.com/developerworks/cn/linux/l-ipc/part2/index2.html

    信号本质:
    信号是在软件层次上对中断机制的一种模拟。在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。信号可以直接进行用户空间进程和内核进程之间的交互,内核进程也可以利用它来通知用户空间进程发生了哪些系统事件。信号是进程间通信机制中唯一的异步通信机制,可以看作是异步通知,通知接收信号的进程有哪些事情发生了。

    信号来源:
    信号事件的发生有两个来源:硬件来源(比如我们按下了键盘或者其它硬件故障);软件来源,最常用发送信号的系统函数是kill, raise, alarm和setitimer以及sigqueue函数,软件来源还包括一些非法运算等操作。

    下面是几种常见的信号:
    SIGHUP :从终端上发出的结束信号.
    SIGINT :来自键盘的中断信号 ( ctrl + c ) .
    SIGKILL :该信号结束接收信号的进程 .
    SIGTERM:kill 命令发出 的信号.
    SIGCHLD:标识子进程停止或结束的信号.
    SIGSTOP:来自键盘 ( ctrl + z ) 或调试程序的停止执行信号.

    进程对信号的响应:     进程可以通过三种方式来响应一个信号:
    (1)忽略信号,即对信号不做任何处理,其中,有两个信号不能忽略:SIGKILL及SIGSTOP;
    (2)捕捉信号。定义信号处理函数,当信号发生时,执行相应的处理函数;
    (3)执行缺省操作,Linux对每种信号都规定了默认操作。

    信号生命周期:
    对于一个完整的信号生命周期(从信号发送到相应的处理函数执行完毕)来说,可以分为三个重要的阶段,这三个阶段由四个重要事件来刻画:信号诞生;信号在进程中注册完毕;信号在进程中的注销完毕;信号处理函数执行完毕。相邻两个事件的时间间隔构成信号生命周期的一个阶段。

    这里信号的产生、注册、注销等是指信号的内部实现机制,而不是信号的函数实现。因此,信号注册与否与后面要讲的发送信号函数(如kill等)及信号安装函数(如signal等)无关,只与信号值有关。

    信号发送与捕捉:
    信号发送:kill()和raise()

    /*kill_raise.c*/
    #include<stdio.h>
    #include<stdlib.h>
    #include<signal.h>
    #include<sys/types.h>
    #include<sys/wait.h>
    int main()
    {
        pid_t pid;
        int ret;
        if((pid=fork())<0)
        {
            printf("fork eoor\n");
            exit(1);
        }
        if(pid==0)
        {
            printf("child(pid:%d) is waiting for any signal\n",getpid());
            raise(SIGSTOP);//调用raise函数发出SIGSTOP信号
            exit(0);
        }
        else
        {
            if((waitpid(pid,NULL,WNOHANG))==0)
            {
                if((ret = kill(pid,SIGKILL)) == 0)//调用kill函数
                {
                    printf("parent kill %d\n",pid);
                }
            }
            waitpid(pid,NULL,0);
            exit(0);
        }
    }

    信号捕捉:alarm()、pause()
    alarm()也常为闹钟函数,当定时器指定的时间到时,就向进程发出SIGALARM信号。一个进程只有一个闹钟时间,如果在调用alarm()之前已设置过闹钟时间,则任何以前的闹钟时间都被新值所替换。
    pause()函数用于将调用进程挂起直至捕捉到信号为止。

    /*alarm_pause.c*/
    #include<stdio.h>
    #include<stdlib.h>
    #include<unistd.h>
    int main()
    {
        int ret = alarm(5);//调用alarm定时器函数
        pause();
        printf("i have been wake up.\n",ret);//此句不会被执行
    }

    信号处理:signal()、信号集函数组
    linux主要有两个函数实现信号的处理:signal()、sigaction()。其中signal()在可靠信号系统调用的基础上实现, 是库函数。它只有两个参数,不支持信号传递信息,主要是用于前32种非实时信号的处理;而sigaction()是较新的函数(由两个系统调用实现:sys_signal以及sys_rt_sigaction),有三个参数,支持信号传递信息,主要用来与 sigqueue() 系统调用配合使用,当然,sigaction()同样支持非实时信号的处理。sigaction()优于signal()主要体现在支持信号带有参数。

    /*signal.c*/
    #include<stdio.h>
    #include<stdlib.h>
    #include<unistd.h>
    #include<signal.h>
    void func(int sign_no){
        if(sign_no == SIGINT){
            printf("i have get SIGINT\n");
        }
        if(sign_no == SIGQUIT){
            printf("i have get SIGQUIT\n");
        }
    }
    int main()
    {
        printf("waiting for signal SIGINT or SIGQUIT...\n");
        signal(SIGINT,func);
        signal(SIGQUIT,func);
        pause();
        exit(0);
    }
    
    /*sigaction.c*/
    int main()
    {
        struct sigaction action;
        printf("waiting for signal SIGINT or SIGQUIT...\n");
        /*sigaction结构初始化*/
        action.sa_handler = func;
        sigemptyset(&action.sa_mask);
        action.sa_flags = 0;
        sigaction(SIGINT,&action,0);
        sigaction(SIGQUIT,&action,0);
        pause();
        exit(0);
    }
    作者:快乐出发0220 ;Android群:151319601 ; Linux群:96394158 ;转载请注明出处 http://klcf0220.cnblogs.com/ !!!
  • 相关阅读:
    Web Service简介
    初识web service
    HTTP 状态代码的完整列表
    【转】JBPM4 RepositoryService
    【转】SD和SDHC和SDXC卡的区别
    【转】PP常用TCODE
    【转】SAP会计科目表
    【转】JBPM4中 state 和 task 的不同
    【转】学习一下车险
    【转】JBPM4 TaskService
  • 原文地址:https://www.cnblogs.com/klcf0220/p/3061479.html
Copyright © 2011-2022 走看看