sigsuspend()

来源:互联网 发布:淘宝企业店铺转让过程 编辑:程序博客网 时间:2024/06/10 03:28

http://blog.sina.com.cn/s/blog_502d82e10100fw16.html

http://blog.sina.com.cn/s/blog_6af9566301013xp4.html


名称:

sigsuspend

功能:

 

头文件:

#include <signal.h>

函数原形:

int sigsuspend(const sigset_t *sigmask);

参数:

sigmask 要替换的进程信号屏蔽字。

返回值:

-1,errno设置为EINTR.

      

 






sigsuspend用于在接收到某个信号之前, 临时用sigmask替换进程的信号掩码, 并暂停进程执行,直到收到信号为止。sigsuspend 返回后将恢复调用之前的信号掩码。信号处理函数完成后,进程将继续执行。该系统调用始终返回-1,并将errno设置为EINTR

       但要注意的是,sigsuspend的整个操作都是原子的,也就不允许被打断的。sigsuspend的整个原子操作过程为:

              (1) 设置新的mask阻塞当前进程;

              (2) 收到信号,恢复原先mask

              (3) 调用该进程设置的信号处理函数;

              (4) 待信号处理函数返回后,sigsuspend返回。

       这种技术的功能有:

       1.可以保护不希望由信号中断的代码临界区。

       2.等待一个信号处理程序设置一个全局变量。

       3.实现父子进程之间的同步。

      

       这个函数的执行步骤有点难理解,但我们仔细分析一下就会明白,sigsuspend函数是先用我们定义的sigmask来暂时替代信号屏蔽集,然后阻塞当前进程,收到信号时调用信号处理函数函数对信号进行处理,处理后返回。

       下面是函数的一个例子:

 

#include <signal.h>

#include <stdio.h>

#include <stdlib.h>

 

static void sig_int(int);

 

int main(void)

{

sigset_t newmask,oldmask,zeromask;

if(signal(SIGINT,sig_int)==SIG_ERR)

    perror(“signal error”);

sigemtyset(&zeromask);

sigemtyset(&newmask);

if(sigprocmask(SIG_BLICK,&newmask,&oldmask)<0)

    perror(“SIG_BLOCK error”);

printf(“In critical region: SIGINT\n”);

if(sigsuspend(&zeromask)!=-1)

    perror(“sigsuspend error”);

printf(“After return from sigsuspend: SIGINT\n”);

sleep(5);

 

exit(0);

}

 

static void sig_int(int signo) /*信号处理函数

{

printf(“In sig_int: SIGINT\n”);

}

 

       程序先打印In critical region: SIGINT,然后执行sigsuspend阻塞信号,当用户按“ctrl+c”时进程通过signal调用信号处理函数sig_int打印In sig_int: SIGINT,返回后打印After return from sigsuspend: SIGINT。然后程序休眠5秒钟,在这5秒钟如果用户按“ctrl+c”进程是不会有反应的,因为调用完sigsuspend进程就恢复了原先的屏蔽集。而原先的屏蔽集屏蔽了SIGINT信号。


1)头文件:#include <signal.h>

2)一个保护临界区代码的错误实例:(sigprocmask()和pause()实现)

#include <unistd.h>

#include <signal.h>

#include <stdio.h>

 


void handler(int sig)    //信号处理函数的实现

{

   printf("SIGINT sig");

}

int main()

{

    sigset_t new,old;

    struct sigaction act;

    act.sa_handler = handler;  //信号处理函数handler

    sigemptyset(&act.sa_mask);

    act.sa_flags = 0;

    sigaction(SIGINT, &act, 0);  //准备捕捉SIGINT信号

    sigemptyset(&new);

    sigaddset(&new, SIGINT);

    sigprocmask(SIG_BLOCK, &new, &old);  //将SIGINT信号阻塞,同时保存当前信号集

    printf("Blocked");

    sigprocmask(SIG_SETMASK, &old, NULL);  //取消阻塞

    pause();

    return 0;

}

上面实例的问题是:本来期望pause()之后,来SIGINT信号,可以结束程序;可是,如果当“取消阻塞”和“pause”之间,正好来了SIGINT信号,结果程序因为pause的原因会一直挂起。。。

解决的方式,当然是sigsuspend()函数了。

 

3)使用sigsuspend()的程序

#include <unistd.h>

#include <signal.h>

#include <stdio.h>

void handler(int sig)   //信号处理程序

{

   if(sig == SIGINT)

      printf("SIGINT sig");

   else if(sig == SIGQUIT)

      printf("SIGQUIT sig");

   else

      printf("SIGUSR1 sig");

}

 

int main()

{

    sigset_t new,old,wait;   //三个信号集

    struct sigaction act;

    act.sa_handler = handler;

    sigemptyset(&act.sa_mask);

    act.sa_flags = 0;

    sigaction(SIGINT, &act, 0);    //可以捕捉以下三个信号:SIGINT/SIGQUIT/SIGUSR1

    sigaction(SIGQUIT, &act, 0);

    sigaction(SIGUSR1, &act, 0);

   

    sigemptyset(&new);

    sigaddset(&new, SIGINT);  //SIGINT信号加入到new信号集中

    sigemptyset(&wait);

    sigaddset(&wait, SIGUSR1);  //SIGUSR1信号加入wait

    sigprocmask(SIG_BLOCK, &new, &old);       //将SIGINT阻塞,保存当前信号集到old中

   

    //临界区代码执行    

  

    if(sigsuspend(&wait) != -1)  //程序在


0 0
原创粉丝点击