zz

来源:互联网 发布:手机上怎么改淘宝好评 编辑:程序博客网 时间:2024/06/11 01:08

#include <stdio.h>#include <signal.h>void checkset();void func();void main()




信号(signal)是一种进程间通信机制,它给应用程序提供一种异步的软件中断,使应用
程序有机会接受其他程序活终端发送的命令(即信号)。
应用程序收到信号后,有三种处理方式:忽略,默认,或捕捉。进程收到一个信号后,
会检查对该信号的处理机制。如果是SIG_IGN,就忽略该信号;如果是SIG_DFT,则会采用系
统默认的处理动作,通常是终止进程或忽略该信号;如果给该信号指定了一个处理函数
(捕捉),则会中断当前进程正在执行的任务,转而去执行该信号的处理函数,返回后再继续
执行被中断的任务。


sigsuspend




一、信号集(sigset_t)
信号集表示一个信号集合,可以将其传递给sigprocmask函数,指定阻塞哪些信号。下
面是操作信号集的函数:
#include <signal.h>
int sigemptyset(sigset_t *set);//清空信号集
int sigfillset(sigset_t *set);//填充信号集
int sigaddset(sigset_t *set, int signo);//向信号集中加入指定信号signo
int sigdelset(sigset_t *set, int signo);//从信号集中移除指定信号signo
All four return: 0 if OK, -1 on error
int sigismember(const sigset_t *set, int signo);//测试signo是否在信号集中
Returns: 1 if true, 0 if false, -1 on error

二、sigprocmask函数
sigprocmask函数可以用来设置进程的信号掩码,即指定哪些信号需要被阻塞;它也可
以用来获取当前进程的信号掩码。
int sigprocmask ( int how, const struct * set, struct * oset );
how指定sigprocmask的操作类型:
SIG_BLOCK     指定将set中的信号加入当前的信号掩码中,即添加需要阻塞的信号;
SIG_UNBLOCK   指定将set中的信号从当前的信号掩码中移除,即解除阻塞信号;
SIG_SETMASK   设置当前的信号掩码为set;
如果oset不为null,当前进程的信号掩码通过oset返回。
如果set为null,则当前信号掩码通过oset返回,how将被忽略。
如果调用sigprocmask时,有当前被挂起的信号被解除阻塞,则在sigprocmask返回之前
至少有一个信号被传递给进程。sigprocmask是为单线程的进程而设计的。


三、sigpending函数
    int sigpending ( sigset_t *set );
    通过set返回当前被阻塞而挂起的信号。


四、sigsuspend函数

    if(sigsuspend(&zeroset)!= -1)    
    {     
        printf("sigsuspenderror\n");  
        exit(0);  
    } 
sigsuspend 用实参 sigmask 指定的信号集代替调用进程的信号屏蔽, 
然后挂起该进程直到某个不属于 sigmask 成员的信号到达为止。
此信号的动作要么是执行信号句柄,要么是终止该进程。
如果信号终止进程,则 suspend 函数不返回。
如果信号的动作是执行信号句柄,则在信号句柄返回后,sigsuspend 函数返回,并使
进程的信号屏蔽恢复到 sigsuspend 调用之前的值。


sigsuspend的整个原子操作过程为:
(1) 设置新的mask阻塞当前进程;
(2) 收到信号,调用该进程设置的信号处理函数;
(3) 待信号处理函数返回后,恢复原先mask;
(4) sigsuspend返回。

清晰且可靠的等待信号到达的方法是先阻塞该信号(防止临界区重入,也就是在次期间
有另外一个该信号到达),然后使用sigsuspend 放开此信号并等待句柄设置信号到达标志
。如下所示, 等待 SIGUSR1 信号到来:


sigemptyset(&zeromask);
sigaddset(&newmask, SIGUSR1);
......


sigprocmask(SIG_BLOCK, &newmask, NULL);
while(flag)
 sigsuspend(&zeromask);
flag = 0;
......
sigprocmask(SIG_UNBLOCK, &newmask, NULL);

列子:
#ifndef SIGSUSPEND


#include <stdio.h>
#include <signal.h>
void checkset();


void main()
{
    // 定义
    sigset_t blockset;
    // 初始化
    sigemptyset(&blockset);
    // 加入信号集
    sigaddset(&blockset,SIGINT);
    sigaddset(&blockset,SIGTSTP);


    checkset();
/* 
当这样调用函数sigprocmask(0,NULL,&oldset);时,当前的信号掩码会复制一份到oldset。
1)SIG_BLOCK:把set中的信号加到当前信号掩码中。
2)SIG_UNBLOCK:把set中的信号从当前信号掩码中除掉。
3)SIG_SETMASK:把set的信号付给信号掩码。
**/
    sigprocmask(SIG_SETMASK,&blockset,NULL);
    checkset();


    /* blockset所有加到信号掩码中 */
    sigaddset(&blockset,SIGTERM);
    sigprocmask(SIG_BLOCK,&blockset,NULL);
    checkset();


    sigdelset(&blockset,SIGTERM);
    /* blockset所有从信号掩码中减去 */
    sigprocmask(SIG_UNBLOCK,&blockset,NULL);
    checkset();
}


void checkset()
{
    sigset_t set;
    printf("checkset start:\n");


/* 
当这样调用函数sigprocmask(0,NULL,&oldset);时,当前的信号掩码会复制一份到oldset。
**/
    if(sigprocmask(0,NULL,&set)<0)
    {
        printf("checksetsigprocmask error!!\n");
        exit(0);
    }


    if(sigismember(&set,SIGINT))
        printf("sigint\n");
    if(sigismember(&set,SIGTSTP))
        printf("sigtstp\n");
    if(sigismember(&set,SIGTERM))
        printf("sigterm\n");
    printf("checkset end\n");
}
#else


#include <stdio.h>
#include <signal.h>
void checkset();
void func();
void main()
{     
    sigset_t blockset,oldblockset,zeroset,pendmask;     
    printf("pid:%ld\n",(long)getpid());  
    signal(SIGINT,func);  
    sigemptyset(&blockset); 
    sigemptyset(&zeroset);  
    sigaddset(&blockset,SIGINT); 
    sigprocmask(SIG_SETMASK,&blockset,&oldblockset); 
    checkset();
    // 获取被阻塞的信号 到pendmask中
    sigpending(&pendmask);  
    if(sigismember(&pendmask,SIGINT))      
        printf("SIGINT pending\n");
/*  
sigsuspend 用实参 sigmask 指定的信号集代替调用进程的信号屏蔽, 
然后挂起该进程直到某个不属于 sigmask 成员的信号到达为止。
此信号的动作要么是执行信号句柄,要么是终止该进程。
如果信号终止进程,则 suspend 函数不返回。
如果信号的动作是执行信号句柄,则在信号句柄返回后,sigsuspend 函数返回,并使
进程的信号屏蔽恢复到 sigsuspend 调用之前的值。
**/
    if(sigsuspend(&zeroset)!= -1)    
    {     
        printf("sigsuspenderror\n");  
        exit(0);  
    }    
    printf("afterreturn\n");   
    sigprocmask(SIG_SETMASK,&oldblockset,NULL);   
    printf("SIGINTunblocked\n");
}
void checkset()
{    
    sigset_t set;     
    printf("checksetstart:\n");   
    if(sigprocmask(0,NULL,&set)<0)   
    {     
        printf("checksetsigprocmask error!!\n"); 
        exit(0);    
    }    
    if(sigismember(&set,SIGINT))  
        printf("sigint\n");   
    if(sigismember(&set,SIGTSTP))
        printf("sigtstp\n");    
    if(sigismember(&set,SIGTERM))  
        printf("sigterm\n");    
    printf("checksetend\n");
}
void func()
{    
    printf("hellofunc\n");
}
#endif


  
0 0