UNIX环境高级编程读书笔记(十)—信号 (5)

11.

名称::

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来暂时替代信号屏蔽集,然后阻塞当前进程,收到信号时调用信号处理函数函数对信号进行处理,处理后返回。

       下面是函数的一个例子:

/*10_10.c*/

#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); /*初始化zeromask信号集*/

sigemtyset(&newmask); /*初始化newmask信号集*/

if(sigprocmask(SIG_BLICK,&newmask,&oldmask)<0) /*把信号集newmask设置为信号屏蔽集*/

    perror(“SIG_BLOCK error”);

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

if(sigsuspend(&zeromask)!=-1) /*用zeromask代替信号屏蔽集,然后阻塞信号,如果有信号来通过signal调用处理函数,最后返回*/

    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信号。

12.

名称::

sigsetjmp/siglongjmp

功能:

save stack context for non-local goto

头文件:

#include <setjmp.h>

函数原形:

int sigsetjmp(sigjmp_buf env,int savemask);

void siglongjmp(sigjmp_buf env,int val);

参数:

 

返回值:

若直接调用则为0,若从sigsetjmp调用返回则为非0。

这两个函数和setjmp,longjmp之间的唯一区别是sigsetjmp增加了一个参数。如果savemask非0,则sigsetjmp在env中保存进程的当前信号屏蔽字。调用siglongjmp时。如果带非0 savemask的sigsetjmp调用已经保存了env,则siglongjmp从其中恢复保存的信号屏蔽字。

你可能感兴趣的:(linux,读书笔记,apue)