3.5. 시그널

시그널은 유닉스 계열 OS 세계에서 ``인터럽션 (interruption, 중단)"의 간단한 형태로 유닉스의 아주 오래된 부분이다. 프로세스는 다른 프로세스에 ``시그널"을 설정할 수 있으며 (kill(1) 또는 kill(2) 를 사용하여) 다른 프로세스는 비동기적으로 시그널을 받아 처리할 수 있다. 프로세스가 어떤 다른 프로세스에 시그널을 보내는 것이 허용되기 위해서는 그 프로세스가 루트 권한을 갖거나 실제 또는 유효 사용자 ID 가 시그널을 받는 프로세스의 실제 또는 유보된 (saved) set-user-ID 와 동일해야 한다. 그러나 몇몇 시그널은 다른 방법으로 보내질 수 있다. 특히 SIGURG 는 TCP/IP 의 out of band (OOB) 메시지를 통한 네트워크를 통해 전달될 수 있다.

시그널이 유닉스의 아주 오래된 부분임에도 불구하고 시그널은 여러가지 구현에서 다른 의미 체계를 갖는다. 기본적으로 "다른 시그널을 처리하는 동안 시그널이 발생하면 어떤 일이 생길까?" 하는 질문이 한 예가 될 수 있는데 새로운 GNU libc 라이브러리보다 오래된 리눅스 libc 5 는 어떤 시그널 연산에 대해 일련의 다른 의미 체계를 사용했다. 시그널 핸들러내에서 C 라이브러리 함수를 호출하는 것이 필수적으로 안전하지는 않은데 각 호출에 대해 문서를 조사할 필요가 있다. 더욱 자세한 정보는 glibc FAQ 를 보라 (어떤 시스템에서는 /usr/doc/glibc-*/FAQ 에서 얻을 수 있다).

새로운 프로그램에 대해서는 단지 POSIX 시그널 시스템 (BSD 에 기초한) 을 사용해라; 이는 널리 지원되고 있으며 오래된 시그널 시스템이 갖고 있던 문제가 없다. POSIX 시그널 시스템은 sigset_t 데이타 타입 사용에 기초하는데 sigemptyset(), sigillset(), sigaddset(), sigdelset() 과 sigismember() 들의 일련의 연산을 통해 조작될 수 있다. sigsetops(3) 에서 이에 대해 읽을 수 있는데 manipulate 시그널 핸들링을 설정하기 위해서는 sigaction(2), sigprocmask(2) 와 sigsuspend(2) 를 사용해라 (더욱 자세한 정보는 맨 페이지를 보라).

일반적으로 모든 시그널 핸들러는 매우 짧고 간단하게 만들고 경쟁 상태를 주의해서 찾아라. 시그널은 본질적으로 비동기적이기 때문에 쉽게 경쟁 상태를 야기할 수 있다.

서버에 대해 공통된 관례가 존재한다: SIGHUP 시그널을 받으면 모든 로그 파일을 닫고 설정파일을 다시 열어 다시 읽은 후 로그 파일을 다시 열어야 한다. 이를 통해 서버를 중지하지 않고 재설정할 수 있으며 데이타 손실없이 로그 순환 (rotation) 을 할 수 있다. 이러한 관례를 따라야 하는 서버를 작성하고 있다면 이를 지원하기 바란다.

Michal Zalewski [2001] 은 시그널 핸들러가 어떻게 악용되는가에 대한 훌륭한 지도서를 작성하였고 시그널 경쟁 문제를 제거하는 방법에 대한 권고를 하였다. 저자는 더욱 자세한 정보를 위해 요약을 보기를 권한다; 다음은 저자의 권고안으로 Michal 의 것과 유사한 것이다: