Chinaunix首页 | 论坛 | 博客
  • 博客访问: 342452
  • 博文数量: 60
  • 博客积分: 1570
  • 博客等级: 上尉
  • 技术积分: 620
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-02 23:37
文章分类

全部博文(60)

文章存档

2012年(2)

2010年(2)

2009年(56)

分类: LINUX

2009-12-27 22:14:18

1.函数原型

#include <signal.h>
int sigsuspend(const sigset_t *sigmask);
                                    返回值:-1,并将errno设置为 EINTR

    sigsuspend 函数将进程的信号屏蔽字设置为 sigmask 指向的值。在捕捉到一个信号或发生了一个会终止该进程的信号之前,该进程被挂起。如果捕捉到一个信号而且从该信号处理程序返回,则sigsuspend返回,在返回之前,将进程的信号屏蔽字设置为调用sigsuspend之前的值。
    注意,此函数没有成功返回值。如果它返回到调用者,则总是返回-1,并将 errno 设置为EINTR(表示一个被中断的系统调用)。

2.实例代码 1 (对原文代码稍有修改)
下面的程序显示了保护临界区,使其不被特定信号中断的方法。

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>

static void sig_int(int);
static void sig_usr2(int);

void pr_mask(const char *str)
{
        sigset_t sigset;
        int errno_save;

        errno_save = errno; /* we can be called by signal handlers */
        if (sigprocmask(0, NULL, &sigset) < 0)
                perror("sigprocmask error");

        printf("mask: %s", str);
        if (sigismember(&sigset, SIGINT)) printf("SIGINT ");
        if (sigismember(&sigset, SIGQUIT)) printf("SIGQUIT ");
        if (sigismember(&sigset, SIGUSR1)) printf("SIGUSR1 ");
        if (sigismember(&sigset, SIGUSR2)) printf("SIGUSR2 ");
        if (sigismember(&sigset, SIGALRM)) printf("SIGALRM ");

        /* remaining signals can go here */

        printf("n");
        errno = errno_save;
}

int main(void)
{
        sigset_t newmask, oldmask, waitmask;

        pr_mask("program start: ");
        if (signal(SIGINT, sig_int) == SIG_ERR)
                perror("signal(SIGINT) error");

        if (signal(SIGUSR2, sig_usr2) == SIG_ERR)
                perror("signal(SIGUSR2) error");

        sigemptyset(&waitmask);
        sigaddset(&waitmask, SIGUSR1);
        sigemptyset(&newmask);
        sigaddset(&newmask, SIGINT);
        sigaddset(&newmask, SIGUSR2);

        /*
         * Block SIGINT and save current signal mask.
         */

        if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
                perror("SIG_BLOCK error");

        /*
         * Critical region of code.
         */


        pr_mask("in critical region: ");

        /*
         * Pause, allowing all signals except SIGUSR1.
         */


        if (sigsuspend(&waitmask) != -1)
                perror("sigsuspend error");
   
        pr_mask("after return from sigsuspend: ");

        /*
         * * Reset signal mask which unblocks SIGINT.
         * */


        if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
                perror("SIG_SETMASK error");

        /*
         * * And continue processing ...
         * */

        pr_mask("program exit: ");

        exit(0);
}

static void sig_int(int signo)
{
        printf("***************************************n");
        pr_mask("start sig_int: ");
        raise(SIGUSR2);
        pr_mask("exit sig_int: ");
        printf("***************************************n");
}

static void sig_usr2(int signo)
{
        pr_mask("in sig_usr2: ");
}


编译后运行,结果如下:

[liumin@localhost sigsuspend_1]$ ./m
mask: program start:
mask: in critical region: SIGINT SIGUSR2 //程序停在这里,然后键入中断字符

***************************************
mask: start sig_int: SIGINT SIGUSR1
mask: in sig_usr2: SIGINT SIGUSR1 SIGUSR2
mask: exit sig_int: SIGINT SIGUSR1
***************************************
mask: after return from sigsuspend: SIGINT SIGUSR2 //从sigsuspend返回后,信号屏蔽字恢复为调用sigsuspend之前的值。

mask: program exit:
[liumin@localhost sigsuspend_1]$






实例代码 2:
使用 sigsuspend 函数,等待一个信号处理程序设置一个全局变量。下面的程序用于捕捉中断信号和退出信号,但是希望仅当捕捉到退出信号时,才唤醒主例程。

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

volatile sig_atomic_t quitflag; /* set nonzero by signal handler */


 /* one signal handler for SIGINT and SIGQUIT */
static void sig_handler(int signo)
{
        if (signo == SIGINT)
                printf("ninterruptn");
        else if (signo == SIGQUIT)
                quitflag = 1; /* set flag for main loop */
}

int main(int argc, char *argv[])
{
        sigset_t newmask, oldmask, zeromask;

        if (signal(SIGINT, sig_handler) == SIG_ERR)
                perror("signal(SIGINT) error");
        if (signal(SIGQUIT, sig_handler) == SIG_ERR)
                perror("signal(SIGQUIT) error");

        sigemptyset(&newmask);
        sigemptyset(&zeromask);
        sigaddset(&newmask, SIGQUIT);

        /* Block SIGQUIT and save current signal mask */
        if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) != 0)
                perror("sigprocmask SIG_BLOCK error");

        while (quitflag == 0)
                sigsuspend(&zeromask);

        quitflag = 0;

        /* Reset signal mask which unblocks SIGQUIT */
        if (sigprocmask(SIG_SETMASK, &oldmask, NULL) != 0)
                perror("sigprocmask SIG_SETMASK error");

        exit(0);
}


编译运行结果:

[liumin@localhost sigsuspend_2]$ ./m
                                               // Ctrl + C
interrupt
                                               // Ctrl + C
interrupt
                                               // Ctrl + C
interrupt                                      // Ctrl + 退出
[liumin@localhost sigsuspend_2]$



阅读(2466) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~