美文网首页
Linux 信号量

Linux 信号量

作者: 小小小码农 | 来源:发表于2016-11-26 18:41 被阅读214次

    信号量在在Linux中有着举足轻重的地位,Linux中一些异常错误也由信号量触发,另外信号量也可以用来做进程间的通信,比如Nignx中master-worker模式的进程通信就是使用信号量。

    信号量的自定义处理

    typedef void (*sig_t) (int)
    sig_t signal(int sig, sig_t func)

    sig:自定义处理的信号量
    func:信号量的处理函数

    信号量的屏蔽

    int sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict oldset)

    how有三种模式

    • SIG_BLOCK :屏蔽的信号量集合为set
    • SIG_UNBLOCK : 解出屏蔽的信号量集合为set
    • SIG_SETMASK : 设置的信号量集合为set

    特别注意信号量屏蔽阶段,被屏蔽的信号量如果多次触发,在该信号量解出屏蔽时也只会再触发一次。

    信号量挂起

    int sigsuspend(const sigset_t *sigmask)
    该函数会阻塞当前执行的进程,直到信号集中的信号触发

    特别注意,如果某个信号已经被设置成BLOCK模式的时候,再sisuspend操作的信号集中如果有该信号,那么信号的BLOCK模式将被取消,触发就执行相应的处理。

    例子

    下面用一个例子说明3个函数的使用方法

    #include <signal.h>
    #include <unistd.h>
    #include <stdio.h>
    
    static int quit = 0;
    
    static void Signal_handler(int s)
    {
        printf("Catch a signal:%d\n", s);
    
        if( s == SIGQUIT)
        {
            printf("quit!\n");
            quit = 1;
        }
    }
    
    
    void Init_signal()
    {
    
        struct sigaction act;
        act.sa_handler = Signal_handler;
        sigemptyset(&act.sa_mask);
        act.sa_flags = 0;
    
        sigaction(SIGINT, &act, NULL);
        sigaction(SIGQUIT, &act, NULL);
        sigaction(SIGUSR1, &act, NULL);
        sigaction(SIGUSR2, &act, NULL);
        sigaction(SIGBUS, &act, NULL);
    }
    
    void Block_signal()
    {
        sigset_t set;
        sigemptyset(&set);
        sigaddset(&set, SIGCHLD);
        sigaddset(&set, SIGINT);
        sigaddset(&set, SIGUSR1);
    
        if(sigprocmask(SIG_BLOCK, &set, NULL) < 0)
        {
            printf("sigprocmask error\n");
        }
    
    }
    
    
    int main(int argc, char *argv[])
    {
        Init_signal();
        Block_signal();
    
        sigset_t set;
        sigemptyset(&set);
        sigaddset(&set, SIGCHLD);
        sigaddset(&set, SIGINT);
        sigaddset(&set, SIGUSR1);
    
        printf("%d\n", time(NULL));
        while(1)
        {
            sigsuspend(&set);
            printf("%d\n", time(NULL));
            if( quit == 1)
            {
                break;
            }
        }
        sigemptyset(&set);
        sigsuspend(&set);
        return 0;
    }
    

    假如进程号为:1571
    依次执行以下操作:
    kill -2 1571 //SIG_INT 信号
    kill -3 1571 //SIG_QUIT 信号

    执行结果如下:

    1479737350
    Catch a signal:3
    quit!
    1479737379
    Catch a signal:2

    总结

    信号量看似简单,实则比较复杂,本文只介绍了单进程单线程的信号量使用,多线程的使用比较复杂,还需要继续学习。

    相关文章

      网友评论

          本文标题:Linux 信号量

          本文链接:https://www.haomeiwen.com/subject/vjjgpttx.html