이는 call로 호출되어 ret로 반환되어야하는 function call의 기계어의 단편화된 호출규약의 무결성을 강제한다고 이해하면 될것이다.
--> 반대로 goto문은 기계어로 jmp [label]과 같이 변환된다. 즉, function call과는 거리가 멀다.
이러한 제약을 탈피하여, 에러 핸들링 및 분기를 제어할 수 있는 방법은 setjmp와 longjmp를 이용하는 방법이 있다. 이를 이용하면 C++의 exception throw를 구현하는 것과 비슷한 효과를 얻을 수 있다.
다음의 내용을 읽어 보자.
1. setjmp는 반드시 longjmp보다 먼저 호출
2. 이때 setjmp를 호출하고 jmpb를 셋업하는 루틴은 계속 액티브
3. longjmp가 호출되기 전에는 복귀될 수 없다.
3-1 만일 복귀된다면 그 결과는 예측할 수 없다.
4. setjmp는 프로그램의 저수준 서브루틴에서 만난 에러와 예외를 취급하는데 유용
FUNCTION
스택에 저장되는 6가지의 register의 값을 저장할 수 있는 저장공간
jmp_buf
sigjmp_buf
6개의 register 값을 저장하는 명령어
setjmp
sigsetjmp
원래 호출 위치로 돌아가는 함수
이때, 저장되었던 register값이 복원된다.
longjmg
siglongjmp
=====================> C++의 Try Catch개념을 구현할 수 있다.
일반적인 경우
#includesignal을 이용하여 Interrupt를 발생시킬 경우void bar( void ) { longjmp( env, 2 ); } void foo( void ) { sleep(2); bar(); //longjmp( env, 1 ); // throw } jmp_buf env; // 스택을 관리하는 6개의 register를 저장한다. int main() { if( ( ret = setjmp(env) ) == 0 ) // try foo(); else if( ret == 1 ) // catch // exception 1; else if( ret == 2 ) // catch // exception 2; }
jmp에 관련된 명령어 들의 앞에 sig를 붙여 주면 된다.
#includevoid bar( void ) { siglongjmp( env, 2 ); } void foo( void ) { sleep(2); bar(); //siglongjmp( env, 1 ); // throw } jmp_buf env; // 스택을 관리하는 6개의 register를 저장한다. int main() { if( ( ret = sigsetjmp(env) ) == 0 ) // try foo(); else if( ret == 1 ) // catch // exception 1; else if( ret == 2 ) // catch // exception 2; }
※ 소스코드는 CentOS 5.3에서 작성되었습니다. ※
'MISCELLANEOUSNESS' 카테고리의 다른 글
How to use shared memory on linux (0) | 2010.06.24 |
---|---|
linux v2.6.11.5 kernel scheduler algorithm. (0) | 2010.06.23 |
PC FAN을 이용한 간단한 선풍기 만드는 방법. (2) | 2010.06.12 |