一个鲜为人知的事实是,大多数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
一次。 longjmp
jmp_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的特殊性