시그널을 이용한 프로그램에 대해서...
글쓴이: 익명 사용자 / 작성시간: 목, 2001/09/27 - 10:27오전
다음은 책의 본문중에 있는 내용입니다. 주석을 달아주세요.... ^^;
"시그널에서 주용한 문제는 '시스템 호출 과정에서 시그널이 발생한다면 어떻게 될까?'이다. 해답은 다소 복잡하게 '의존적'이라는 점이다. 일반적으로 터미널로부터 읽어들이는 것과 같이 '느린' 시스템 호출에 대해서만 걱정하면된다. 이런 경우에는 대기 상태에서 시그널이 발생한다면 시스템 호출이 에러를 반환할 것이다. 프로그램에서 시그널을 사용하기 시작하다면 시그널이전달되어 일부 시스템 호출이 실패할 수 있다는 사실을 주의할 필요가있다."
"Beginning Linux Programming - 2nd Edition, 정보문화사, p513"
Forums:
Re: 시그널을 이용한 프로그램에 대해서...
signal 때문에 system call 이 실패할 수도 있다는 이야기 같네요..
"운영체제" 책에 나와있는 얘기지만 system call 은 프로세스가 운영체제
(커널) 에게 특권이 필요한 행동(예를들면 디스크에 뭔가를 기록해야 하는
행동) 을 요청할 수 있도록 운영체제에서 정의한 함수입니다.
쉽게 볼 수 있는게 write() 나 read() 같은 것들이죠...
시스템 콜은 유저 모드(맞는지..^^) 이 아닌 커널 모드에서 수행되며, 작업
이 끝나면 다시 유저 모드로 바뀌어서 시스템 콜을 호출한 프로세스가 계속
수행됩니다. 문제는 시스템 콜 중간에 시그널이 발생하면 어떻게 처리하는가..
인데 보통은 바로 시그널 핸들러가 작동하며 시스템 콜은 에러코드를 반환하며 즉시
중단됩니다.
자세한 부분은 운영체제 책을 참고하시길... 참고로 스티븐이 쓴
Advanced Programming in the Unix Environment 책에도 이 문제가 비교적
상세히 나와 있네요..
시그널..
void (*signal (int sig, void (*disp)(int)))(int);
이 시그널 함수의 형식이 궁금합니다.
void형을 리턴하는 함수 포인터라는 것은 알겠습니다.
어떠한 함수가 있는데..
그 함수는 void형을 리턴 하고..
인자로는 int 형과 함수 포인터를 갖는다.
예 이해가 잘됩니다.
그런데 저어기 마지막에 붙은 (int) 이것은 이해가 되질 않습니다.
저건..왜 붙어 있는 것 일까요?
void (*signal (int sig, void (*disp)(int)))(int);
void (*signal (int sig, void (*disp)(int)))(int); 복잡하게 보이지만
간단합니다.
int sig, void (*disp)(int)) 이부분은 signal함수가 int형과 함수포인터를
인자로 받는다는 것이고 앞의 void와 젤 뒤의 int는 signal함수가
리턴하는 값이 int를 인자로 가지는 함수의 포인터라는것입니다.
복잡하게 보이지만 분석해보시면 간단할겁니다^^
10년후의 나와 인사하자!!
system call을 man 해보면 ERRORS 항목에 EINTR 이
system call을 man 해보면 ERRORS 항목에 EINTR 이 나오는 경우가 있습니다. 대표적인 예로 man 2 read 해보세요.
이게 바로 이 system call을 사용하는 경우 block이 될 수 있고(이게 책에서 표현하는 느린 시스템 호출입니다) 이때 signal이 발생하면 이 system call이 return하고(대부분 -1) errno가 EINTR로 setting된다는 의미입니다.
이런 경우가 발생할 수 있기 때문에 대부분의 느린 시스틈 호출을 사용하는 경우에 다음과 같이 코딩합니다.
man 해보았을 때 ERROS 항목에 EINTR이 있다면 대부분 위와 비슷한 방식으로 코딩해야 합니다.
우리 모두 리얼리스트가 되자. 그러나 가슴에 이룰 수 없는 꿈을 가지자
프로그램을 하다보면 꼭 시그널처리에 대해 이해하고 넘어가야 합니다.예
프로그램을 하다보면 꼭 시그널처리에 대해 이해하고 넘어가야 합니다.
예를 들면 최소한 SIGSEGV 에 대해서는 처리해야 하겠지요.
signal (SIGSEGV, sig_catch) ;
signal (SIGTERM, sig_catch) ;
그런데 이렇게 시그널핸들러를 쓰게 되면
반드시 프로세스가 그 시그널을 만난다고 생각하시는게 맞습니다.
따라서 시스템콜에 대해 실패하고 나면 반드시 errno == EINTR 인지를 확인해야 합니다.
그런데 모든 경우에 다 체크할수는 없을것입니다.
예를들면
이런것까지 다 체크하실 필요는 없겠지요.
모두다 체크하지 않더라도 꼭 체크해야 할 시스템콜들은 블락되는 명령들입니다.
예를들면 read() 와 select() 와 msgrcv() 와 wait() 가 있습니다.
단, 비블럭킹 모드로 작동하는 경우에는 시그널만날 확률이 매우 낮습니다.
(비블럭킹모드 예 msgrcv(,,, IPC_NOWAIT) <--- 이런경우에는 메세지큐에서 읽을것이 없으면 곧바로 리턴하므로 시그널을 만나지 않을것임)
이런 명령들은 명령이 끝날때까지 블락된 상태로 계속 대기해야 하기 때문에 시그널을 꼭 만나게 됩니다.
내 자식들도 나처럼 !!
댓글 달기