C语言中的跳转goto&&setjmp&&longjmp sigsetjmp siglongjmp

1、goto语句,函数内部的短转移

    goto语句只能跳转的到本函数内部的标签处,这个没得说,例子如下:

    #include <stdio.h> int main() { int i=0; loop: printf("do something %d/n",i); i++; if(i<6) goto loop; return 0; }

 2、setjmp 和 longjmp 实现长跳转

     函数原型如下:

     #include <setjmp.h>     

        int setjmp(jmp_buf envbuf);   

        void longjmp(jmp_buf envbuf, int val);

        其中 setjmp用来设置一个供longjmp调至的地址envbuf,初次执行setjmp返回0值,程序继续向下执行,

        当遇到longjmp调用返回到该处是,促使该函数返回val值,这也就是longjmp的第二个参数,通过这种方式

        使得longjmp在跳转的时候可以传递一定的信息给setjmp,可以用来分析跳转原因,方便程序按照不同的返

         回值进行不同的处理。

         #include <setjmp.h> #include <stdio.h> #include <signal.h> jmp_buf buf; void handler(int signal) { if(signal==SIGINT) printf("Recived SIGINT ,go back to main/n"); longjmp(buf,1); } int main() { signal(SIGINT,handler); if(setjmp(buf)) { printf("Back in main,infinite loop begins/n"); } else printf("infinite loop begins/n"); loop: goto loop; }

         上面的函数通过在信号捕捉函数中调用longjmp使得程序能返回到main函数继续执行,所以

         setjmp和longjmp的一个很显然的用途就是,从一些非致命行程序错误中返回,使得程序继续 

         执行。

         但是在上面的例子中存在一个问题,当进程第一次接受到SIG_INT信号(Ctrl+C)后成功返回main中,但是

         以后接受到SIG_INT信号却不做任何动作了。原因何在呢?因为:

         调用l o n g j m p时有一个问题。当捕捉到一个信号时,进入信号捕捉函数,此时当前信号被
         自动地加到进程的信号屏蔽字中。这阻止了后来产生的这种信号中断此信号处理程序。如果用
         l o n g j m p跳出此信号处理程序,则对此进程的信号屏蔽字会发生什么呢?一般实现是不会恢复

         原来的信号屏蔽字的,所以SIG_INT信号被屏蔽了,以后不再响应了。

             在4 . 3 + B S D下,s e t j m p和l o n g j m p保存和恢复信号屏蔽字。但是, S V R 4并不
             做这种操作。4 . 3 + B S D提供函数_ s e t j m p和_ l o n g j m p,它们也不保存和恢复信号屏
             蔽字。
        为了允许两种形式并存, P O S I X . 1并没有说明s e t j m p和l o n g j m p对信号屏蔽字的作用,而是
        定义了两个新函数s i g s e t j m p和s i g l o n g j m p。在信号处理程序中作非局部转移时应当使用这两个
        函数。函数原型如下:

         #include <setjmp.h>

           int sigsetjmp( sigjmp_buf * env, int savemask );

 

 

 

 

 

 

 

           void siglongjmp ( sigjmp_buf * env, int val );

         如果调用sigsetjmp时 参数savemask 为非0,则siglongjmp 从信号处理函数返回时,将恢复进程调用sigsetjmp之前的信号屏蔽字。

        将上面的例子改成使用这对函数,就可以继续对SIG_INT信号进行捕捉和从其中返回main了。

        #include <setjmp.h> #include <stdio.h> #include <signal.h> sigjmp_buf buf; void handler(int signal) { if(signal==SIGINT) printf("Recived SIGINT ,go back to main/n"); siglongjmp(buf,1); } int main() { signal(SIGINT,handler); if(sigsetjmp(buf,1)) { printf("Back in main/n"); } else printf("infinite loop begins/n"); loop: goto loop; }

 

 

2011-04-14

 

 

你可能感兴趣的:(c,语言,Go,Signal)