Linux 信号量

信号量在在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 
#include 
#include 

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 信号量)