setjmpandを使用して状態を保存した後、C プログラムで複数の関数を切り替えようとしてlongjmpいますが、コンテキストを保存できる関数は 1 つだけで、他の 2 つの関数では保存できません。それに対する可能な解決策は何でしょうか。コードに必要な変更が必要かどうかを提案してください。のo/p状態でfun1()は に正常に保存されenv1、元に戻すことができますが、 の場合fun2()、fun3()状態は に保存されませenv2んenv3。
サンプル o/p:
i=0,j=999
i=1,j=998
i=2,j=997
i=3,j=996
ch=a
ch=b
ch=c
ch=d
a=0
a=-1
a=-2
a=-3
i=4,j=995/*The previous value of i is preserved*/
i=5,j=996
i=6,j=994
i=7,j=993
ch=<garbagevalue> /*The previous value of ch is lost*/
ch=<garbagevalue>
ch=<garbagevalue>
ch=<garbagevalue>
a=<garbagevalue> /*The previous value of ch is lost*/
a=<garbagevalue>
a=<garbagevalue>
a=<garbagevalue>
i=8,j=992
and so on..
コードは次のとおりです。
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include<setjmp.h>
#define INTERVAL 5000
void fun1();
void fun2();
void fun3();
void timer_handler(int );
struct itimerval it_val;
jmp_buf env1,env2,env3;
int count=0;
void timer_handler (int signum)
{
if(count==0){
count++;
fun1();
}
if(count==1){
count++;
fun2();
}
if(count==2){
count++;
fun3();
}
L1:
if(count==3){
count++;
siglongjmp(env1,7);
}
if(count==4){
count++;
siglongjmp(env2,7);
}
if(count==5){
count++;
siglongjmp(env3,7);
}
count=3;
goto L1;
}
void fun1()
{
struct sigaction sa;
int i=0,j=999;
/* Install timer_handler as the signal handler for SIGVTALRM. */
memset (&sa, 0, sizeof (sa));
sa.sa_flags=SA_NODEFER;
sa.sa_handler = &timer_handler;
/* Configure the timer to expire after 250 msec... */
it_val.it_value.tv_sec = INTERVAL/1000;
it_val.it_value.tv_usec = (INTERVAL*1000) % 1000000;
it_val.it_interval.tv_sec = INTERVAL/1000;;
it_val.it_interval.tv_usec=(INTERVAL*1000) % 1000000;
sigaction (SIGALRM, &sa, NULL);
setitimer (ITIMER_REAL, &it_val, NULL);
while (1) {
while(sigsetjmp(env1,3)==0){
sleep(1);
printf("i=%d,j=%d\n",i,j);
i++;
j--;
}
}
}
void fun2()
{
struct sigaction sa;
char ch='a';
/* Install timer_handler as the signal handler for SIGVTALRM. */
memset (&sa, 0, sizeof (sa));
sa.sa_handler = &timer_handler;
sa.sa_flags=SA_NODEFER;
sigaction (SIGALRM, &sa, NULL);
/* Configure the timer to expire after 250 msec... */
it_val.it_value.tv_sec = INTERVAL/1000;
it_val.it_value.tv_usec = (INTERVAL*1000) % 1000000;
/* ... and every 250 msec after that. */
it_val.it_interval.tv_sec = INTERVAL/1000;;
it_val.it_interval.tv_usec=(INTERVAL*1000) % 1000000;
/* Start a virtual timer. It counts down whenever this process is*/
setitimer (ITIMER_REAL, &it_val, NULL);
/* Do busy work. */
while (1) {
while(sigsetjmp(env2,2)==0) {
sleep(1);
printf("ch=%c\n",ch);
if(ch=='z')
ch='a';
ch++;
}
}
}
void fun3()
{
struct sigaction sa;
int a=0;
/* Install timer_handler as the signal handler for SIGVTALRM. */
memset (&sa, 0, sizeof (sa));
sa.sa_handler = &timer_handler;
sa.sa_flags=SA_NODEFER;
sigaction (SIGALRM, &sa, NULL);
/* Configure the timer to expire after 250 msec... */
it_val.it_value.tv_sec = INTERVAL/1000;
it_val.it_value.tv_usec = (INTERVAL*1000) % 1000000;
/* ... and every 250 msec after that. */
it_val.it_interval.tv_sec = INTERVAL/1000;;
it_val.it_interval.tv_usec=(INTERVAL*1000) % 1000000;
/* Start a virtual timer. It counts down whenever this process is*/
setitimer (ITIMER_REAL, &it_val, NULL);
/* Do busy work. */
while (1){
while(sigsetjmp(env3,1)==0){
sleep(1);
printf("a=%d\n",a);
a--;
}
}
}
int main ()
{
timer_handler(1);
return 0;
}