《C编程.高级C》5.协同程序

一个鲜为人知的事实是,大多数C实现都具有可用于协作式多任务/协同程序的内置基元。它们是setcontext和setjmp。

setjmp 

该函数setjmp用于longjmp将执行转移到代码中的不同点。它依赖于现有的jmp_buf声明。

#include  <setjmp.h>

int  main  (void )
{ 
  jmp_buf  buf1 ;
  
  if  (setjmp (buf1 ) ==  0 )
  { 
    / *此代码在第一次调用setjmp时执行。* /

    longjmp的(BUF1 , 1 ); 
  }  else  { 
    / *调用longjmp后执行此代码。* / 
  } 
  返回 0 ;  
}

setjmp()将当前执行点存储在内存中,只要包含的函数不返回,它就会保持有效。它最初返回0。使用原始和替换返回值调用控制返回到setjmp一次。 longjmpjmp_buf

请注意,jmp_buf在不使用address-of运算符的情况下传递给setjmp。

理解setjmp和longjmp的最简单方法是,setjmp存储cpu的状态,包括程序计数器,堆栈指针,所有寄存器,包括标志寄存器的位,在jmp_buf指向的位置,这是定义的一些LEN + 1,这是足够的字节来存储所涉及的任何CPU的寄存器。longjmp(buf)永远不会返回,因为它从之前调用setjmp先前设置的struct jmp_buf buf的内容中恢复CPU,因此执行从调用setjmp之后开始,但setjmp的返回值不是0,但是在longjmp的第二个参数中使用的值。这类似于fork()系统调用,它返回0到子进程,子进程的PID返回到父进程。

互联网建议协同例程对于在状态机协作时实现软件很有用,例如词法分析器处理输入文本和发出令牌,以便解析器可以决定存储令牌并请求下一个令牌,或者对其当前集合进行操作令牌。这不是多线程程序在数据上同步,如果一个bug忘记获取一个锁,但是使用setjmp和longjmp,可能是竞争条件似乎是合作进程,保证一次只运行一个进程,不用担心上下文切换唤醒休眠进程(使用单独的jmp_buf静态位置,每个进程可以调用setjmp用于自己的jmp_buf,如果返回零则在稍后调用longjmp,或者继续循环以处理非零返回的共享数据)。

猜你想读:《C编程.C以后》1.C的特殊性

THE END
分享