OS/Common

간단하고 명료하게 설명된 Unix/Linux의 signal 발생 원인

장피디 2017. 1. 13. 10:06
반응형


참조    : http://ssambback.tistory.com/entry/Unix-or-Linux-%EB%B3%84-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EC%97%90%EB%9F%AC%EB%93%A4


프로그램 에러 시그널들 (SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGABRT) - 매우 중요 ★★★★★

다음의 시그널들은 심각한 프로그램의 에러가 운영체제나 컴퓨터 자체에 의해 검출되었을 때 발생 된다. 
일반적으로, 이들 시그널 모두는 당신의 프로그램이 심각하게 깨져있고, 에러가 포함된 그 실행을 계속할 아무런 방법이 없음을 지적한다.


어 떤 프로그램들은 프로그램의 에러 시그널로 인해서 종료되기전에 그들을 깨끗하게 처리한다. 예를 들어, 터미널 입력의 반향을 끈(tnun off) 프로그램들은 다시 반향을 켤 목적으로 프로그램 에러 시그널들을 처리할 것이다. 핸들러는 시그널을 위한 디폴트 동작을 정하고 그 동작을 함으로써 끝날 것이다. 만일 프로그램이 시그널 핸들러를 가지지 않았다면, 프로그램은 그 시그널로 인해서 종료될 것이다.

SIGFPE 시그널은 심각한 산술적 에러를 보고한다. 그 이름이 "floating-point exception"에서 유래된것이라 할지라도, 이 시그널은 실제로는 모든 산술적 에러들에 작용한다. 만일 어떤 프로그램이 어떤 위치에 정수 데이터를 저장하고 그 데이터에 플로팅-포인트 명령을 사용한다면, 이것은 그 프로세서가 데이터를 플로팅-포인트 수로써 인식할 수 없기 때문에 종종 "유용하지 않은 연산"의 원인이 된다.

SIGILL 시그널의 이름은 "비합법적인 명령(illegal instruction)"에서 유래되었다
그것은 쓸모없거나 특권이 부여된 명령어를 실행하려 했다는 의미이다. 
오직 유용한 명령어만이 발생된 C 컴파일러에서, SIGILL은 전형적으로 실행 가능 파일이 훼손되었거나, 당신이 데이터를 실행하려 시도했다는 것을 지적한다. 

후자의 상황이 발생되는 일반적 상황으로는 함수를 위한 포인터가 있을 것이라고 예상된 곳에서 유용하지 않은 오브젝트를 파싱하거나, 자동 배열의 끝을 넘어서 기록을 하고( 또는 자동 변수를 위한 포인터와 유사한 문제들) 스택 프레임의 반환 어드레스 처럼 스택에서 
다른 데이터의 훼손과 같은 문제들이 있다.

SIGSEGV 시그널은 할당된 메모리의 범위를 벗어나는곳에서 읽거나, 쓰기를 시도할 때 발생 된다. 
(실제로, 그 시그널들은 프로그램이 충분한 영역을 할당받지 못할 때 시스템 메모리 보호 메커니즘에 의해서 발생한다.) 

그 이름은 "segmentation violation"의 약자이다. 
SIGSEGV 상황이 발생되는 가장 일반적인 방법은 비참조 되는 널( defeferencing a null) 이나 초기화되지 않은 포인터에 의한 것이다. 

널 포인터는 주소 0으로 참조되고, 대부분의 운영체제는 이 주소가 정확하게 유용하지 않음을 확실히 
하기 때문에 
비참조 널 포인터는 SIGSEGV가 발생될 것이다. 
(어떤 운영체제는 주소가 0인 메모리도 유용하고, 비참조 널 포인터는 그들 시스템상에서는 시그널을 발생하지 않는다.) 
비초기화된 포인터에서는, 유용하지 않거나, 유용하더라도 임의의 주소들을 갖게된다. 
SIGSEGV 상황이 얻어지는 다른 일반적 방법은 배열에 포인터를 사용했을 때 그 배열의 끝을 체크하기를 실패했을 때이다. 

SIGBUS 시그널은 유용하지 않은 포인터가 비참조되었을 때 발생 된다. 
SIGSEGV 처럼, 이 시그널은 초기화되지 않은 포인터를 비참조 한 것의 결과이다. 
두 시그널의 차이점은 SIGSEGV는 유용한 메모리에서 유용하지못한 억세스를 지적하고, 
SIGBUS는 유용하지못한 주소를 억세스 하는 것을 지적한다. 
특별하게, SIGBUS 시그널은 4개로 나누어지지 않은 주소에 4-단어 정수로 참조하는것처럼, 
부적당한 포인터가 비참조 됨으로써 발생한다. 
(각종 시스템은 주소 정렬은 위한 자신만의 필요조건을 갖는다.) 이 시그널의 이름은 "bus error"의 약자이다.

SIGABRT 시그널은 프로그램 그 자체와 abort가 호출되었음을 보고함으로써 발생되는 에러를 지적한다.

2. 종료 시그널 (SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGKILL) - 중요 ★★★★

이들 시그널들은 이런 저런 방법으로 프로세스를 종료함을 알리기위해 사용된다. 
그들은 완전히 다른 목적을 위해 사용되기 때문에 다른 이름을 가졌고, 프로그램은 그들은 다르게 취급하기를 원할 것이다.
이들 시그널들은 처리하기 위한 이유는 보통 당신의 프로그램이 실제로 종료되기전에 적당하게 처리할 수 있도록 하기 위한 것이다. 
예를 들어, 당신은 상황정보를 저장하고, 임시 파일들을 지우고, 이전의 터미널 모드를 반환하기를 원할수도 있다. 
그와 같이 핸들러(handler)는 발생된 시그널을 위한 디폴트 동작을 지정하고 그리고 그 시그널을 다시 발생시킴으로써 종료할 것이다. 
이것은 만일 프로그램이 핸들러를 가지지 않았더라도, 그 시그널로 인해서 프로그램이 종료될 것이다.

SIGHUP ("hang-up") 시그널은 사용자 터미널의 단절을 보고하기 위해 사용되어지는데, 
아마도 네트웍이나 전화선 연결이 끊어졌기 때문이다. 

SIGINT("program interrupt") 시그널은 사용자가 INTR 문자를 (보통 C-c)을 입력했을 때 보내어진다. 

SIGQUIT 시 그널은 다른 키_QUIT 문자, 보통 C-\_에 의해서 제어된다는 것을 제외하고는 SIGINT와 유사하고, 그 프로세스가 종료 될 때 프로그램 에러 시그널처럼 코어 파일을 작성한다. 당신은 사용자에 의해 "검출된" 프로그램 에러 상황으로 이들을 생각할 수 있다. 

SIGTERM 시그널은 프로그램을 종료하는데 사용하는 포괄적인 시그널이다. SIGKILL과 달리, 이 신호는 블록되어진고, 처리되어지고 무시되어질 수 있다.

SIGKILL 시그널은 즉각적인 프로그램 종료를 일으키기 위해서 사용되어진다. 이 시그널은 처리되거나, 무시되거나 할 수 없고, 그 결과는 항상 치명적이 된다. 이 시그널은 블록하는것도 불가능하다. 

3. 알람 시그널 (SIGALRM, SIGVTALRM, SIGPROF) - 알아도 그만.. 몰라도 그만..  ^^;;

그들 시그널은 타이머의 경과를 지적하는데 사용되어진다. 
그들 시그널을 위한 디폴트 동작은 프로그램을 종료를 일으키는 것이다. 
이 디폴트 동작은 거의 유용하지 않다. 
그 들 시그널을 사용하는 대부분의 방법은 어느 경우에 맞는 핸들러 함수들을 요구하는 것이다.

SIGALRM 시그널은 전형적으로 실제또는 클럭 시간을 계산한 타이머의 경과를 지적한다. 
예를 들어 alarm 함수에의해 사용되어진다. 

SIGVTALRM 시그널은 전형적으로 현재 프로세스에 의해 사용된 CPU시간을 계산하는 타이머의 경과를 지적한다. 
그 이름은 "virtual time alarm"의 약자이다.

SIGPROF 시그널은 현재의 프로세스에 의해 사용된 CPU 시간과, 
프로세스를 대신하여 시스템에의해 사용된 CPU시간의 둘을 계산한 타이머의 경과를 지적하는데 사용된다. 
타이머가 자원의 프로파일링을 위한 도구로써 사용되어지므로, 시그널의 이름이 SIGPROF이다.

4. 비동기 입/출력 시그널 (SIGIO, SIGURG)

이 절에 설명된 시그널들은 비동기 입/출력 도구들과 함께 사용되어진다. 
당신은 어떤 특정한 파일 기술자가 그들 시그널을 발생시키도록 하기 위해서 fcntl을 호출함으로써 명백한 동작을 취하도록 해야한다.

SIGIO 시그널은 파일기술자가 입력 또는 출력을 수행할 준비가 되어있을 때 보내어진다. 
대부분의 운영체제에서, 터미널과 소켓만이 SIGIO를 발생시킬 수 있다. 
보통의 파일들을 포함한 다른 종류들은 당신이 그들에게 요청했을지라도 SIGIO신호를 발생시키지 않는다.

SIGURG 시그널은 소켓에 도착한 데이터가 "긴급"하거나 범위를 벗어 났을 때 보내어진다.

5. 작업 제어 시그널 (SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU) - 중요 ★★★★

이들 시그널은 작업 제어를 지원하기 위해서 사용되어진다. 
만일 당신의 시스템이 작업 제어를 지원하지 않는다면 시그널들은 발생되어지거나, 처리될 수는 없지만 매크로들은 정의되어있다. 
당신이 실제로 작업이 어떻게 제어되는지를 이해할 수 없다면 그들 시그널을 그대로 방치할 것이다.

SIGCHLD 시그널은 자식 프로세스들중의 하나라도 종료되거나 멈출 때마다 부모 프로세스에게 보내어진다. 
이 시그널을 위한 디폴트 동작은 그것을 무시하는 것이다. 

당신은 프로세스가 계속되도록 하기 위해서 SIGCONT 신호를 보낼 것이다.
SIGCONT 시그널을 위한 디폴트 동작은 만일 그 프로세스가 멈추었다면 그 프로세스를 계속하도록 만드는 것이고 
그렇지 않다면 그것을 무시하는 것이다. 
대부분의 프로그램에서는 SIGCONT를 처리할 아무런 이유가 없다. 
그들은 전에 멈추었었음을 인식함이 없이 계속 실행되고 있다고 가정한다. 

SIGSTOP 시그널은 프로세스를 멈춘다. 그것은 처리되거나, 무시되거나 블록될 수 없다.

SIGTSTP 시그널은 상호 작용하는 멈춤 신호이다. SIGSTOP와는 달리 이 신호는 처리되거나 무시되어질 수 있다. 
당신의 프로그램에서 프로세스가 멈추었을 때 파일이나 시스템 테이블을 안전한 상황으로 만들어놓을 특별한 필요가 있다면 
이 신호를 처리할 수 있다.

한 프로세스가 배경 작업으로써 실행되고 있는 동안 사용자의 터미널로부터 읽을 수 없다. 
배경 작업에 속한 어느 프로세스가 터미널로부터 읽으려 시도할 때, 그 작업에 속한 모든 프로세스는 SIGTTIN 신호를 받는다. 
이 시그널을 위한 디폴트 동작은 그 프로세스를 멈추는 것이다. 

SIGTTOU 시그널은 배경 작업에 속한 프로세스가 터미널에 출력하려 시도하거나 그 터미널 모드를 설정하려 시도할 때 발생 된다. 
다시 말하면 디폴트 동작은 그 프로세스를 멈추는 것이다. 
프로세스가 멈추어있을 동안, SIGKILL 시그널과 SIGCONT시그널을 제외하고는 어느 다른 시그널들은 배달되어질 수 없다.

SIGKILL 시그널은 항상 프로세스의 종료를 유발하고 블록되거나 무시될 수 없다. 
당신이 SIGCONT 시그널을 무시하거나 블록할 수 있지만, 그것은 만일 그 프로세스가 멈추어져있다면 프로세스가 계속되도록 한다. 
프로세스에게 보낸 SIGCONT 시그널은 아직 미해결인채로 남아있는 멈춤 시그널을 프로세스가 버리도록 한다. 
이와 비슷하게, 어떤 프로세스에서 아직 미해결인채로 남아있는 SIGCONT 시그널은 멈춤 시그널이 도착했을 때 버려진다. 
고아가 되어버린 프로세스 그룹에 있는 한 프로세스에게 SIGTSTP, SIGTTIN, 또는 SIGTTOU 시그널을 보내면 그것은 처리되지도 않고, 
그 프로세스는 멈추어 지지도 않는다. 
그것을 계속할 아무런 방법이 없는 부당하게 되어버린 프로세스를 멈추게 하라. 
운영체제에 의존하지 말고당신이 무언가를 사용해서 멈추게 하라. 어떤 시스템은 아무런 일도 하지 않을 것이다. 
다른 시스템들은 대신에 SIGKILL 또는 SIGHUP와 같은 시그널들을 배달할 것이다. 

6. 잡다한 시그널 (SIGUSR1 ~ SIGUSR22)

그들 시그널은 다양한 다른 상활들을 보고하기 위해서 사용되어진다. 이들의 디폴트 동작은 프로세스가 종료되도록 하는 것이다.

SIGPIPE 시그널은 읽는 프로세스가 없는 상황에서의 PIPE에 대한 쓰기시 발생한다.

SIGUSR1 과 SIGUSR22 시그널들은 당신이 원하는 어떤 방법을 사용하지 못하도록 한다. 그들은 프로세스간 통신을 위해서 유용하다. 

그들 시그널을 보통 심각하기 때문에 당신은 그 시그널을 받은 프로그램에서 그들은 위한 시그널 처리를 해야할 것이다.



출처: http://ssambback.tistory.com/entry/Unix-or-Linux-별-프로그램-에러들 [Rehoboth.. 이곳에서 부터]

반응형