• 进程间通信_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: qiaozongpeng@163.com
        > 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: qiaozongpeng@163.com
        > 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;
    }



  • 相关阅读:
    【MongoDB】 C#官方驱动增删查改
    【MongoDB】MongoHelper
    【设计模式】简单的单例模式
    andriod深度探索及驱动开发展望
    搭建Android开发环境
    第一章Android系统移植与驱动开发概述
    时间
    django-admin和manage.py
    自定义django-admin命令
    会话session
  • 原文地址:https://www.cnblogs.com/cynchanpin/p/7027354.html
Copyright © 2020-2023  润新知