全部博文(71)
分类: LINUX
2008-04-15 21:06:13
11.
名称:: |
sigsuspend |
功能: |
|
头文件: |
#include |
函数原形: |
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 #include #include 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 |
函数原形: |
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从其中恢复保存的信号屏蔽字。
chinaunix网友2009-07-03 18:45:55
需要修改一下: sigemptyset(&newmask); /*初始化newmask信号集*/ sigaddset(&newmask, SIGINT);//add