Linux 애플리케이션 개발 및 신호 처리

Linux 애플리케이션 개발 및 신호 처리

현재 사용자들이 내 애플리케이션 종료에 대해 불만을 제기하는 데 문제가 있습니다. 일부(임의로 보이는) 조건 및 데스크톱 환경에서는 앱이 종료되지 않으며 재부팅 시 설정이 저장되지 않습니다. 관련 IRC 채널에 문의했는데 대부분 신호를 올바르게 처리하라는 지시를 받았습니다. 나는 터미널의 Ctrl-C에 대한 SIGINT와 "정상적인" 종료에 대한 SIGTERM을 알고 있습니다. 하지만 SIGHUP도 중요하다는 말을 들었습니다. 그래서 내 질문은 다음과 같습니다

제대로 작동하는 애플리케이션을 구축하려면 어떤 신호를 처리해야 합니까?

답변1

https://en.wikipedia.org/wiki/Unix_signal

표준 신호와 기본 동작 목록이 있습니다. 권한이 충분한 프로세스는 항상 사용자에게 신호를 보낼 수 있지만 프로세스(또는 프로세스를 통해 사용자)는 이를 수행해서는 안 됩니다.

당신은 kill당신의 프로세스를 사용하고 kill이를 기대해야 합니다.용어그리고 전송하려는 특수 신호를 대상이 처리한다는 것을 알지 못하는 한 환경(셸, 터미널 드라이버)에 의해 생성될 수 있는 여러 신호.

기본 신호를 동작별로 정렬할 수 있습니다.

코어덤핑 신호

ABRT TRAP SYS BUS FPE ILL SEGV   XFSZ XCPU QUIT

일부 특수 기능을 사용하여 사용자(TRAP, ABRT, SYS)에 의해 생성되거나 하드 오류 상태(BUS, FPE,ILL, SEGV)에 진입하여 생성됩니다. QUIT코어 덤프( )를 원하는 단말에서 사용자에 의해 생성된다 C+\.

이러한 항목을 기본 처리로 유지하고 싶을 수도 있습니다.

밖으로신호 종료:

HUP INT PIPE TERM ALRM POLL PROF USR1 USR2

당신은 기대해야

HUP INT PIPE TERM

다양한 상황에서 귀하의 환경에서:

HUP -- when the terminal hungs up or you become a stopped orphaned process
INT -- when the user at the terminal interrupts you with C-c
PIPE -- when a PIPE or socket you write into closes, e.g. by
        exiting before you finished writing to it 
       (`yourprogram | (exit)` will give you a `PIPE` 
        if yourprogram attempts to write to its STDOUT) 
TERM -- when a process ends you a normal termination request

사용자가 직접 설정한 경우에만 나머지 종료 신호를 수신해야 합니다.

죽이다그리고멈추다당신은 아무것도 할 수 없습니다.

생성된 터미널을 가로챌 수도 있습니다.신호 중지:

TTIN -- you read from the terminal and you're a backgrounded process
TTOU -- you write the terminal when you're a backgrounded process
        and the terminal is set to put you to sleep when you do
TSTP -- you're being put to sleep with `C-Z`

그러나 최악의 경우 상태를 손상시키지 않고 프로세스를 중지할 뿐입니다.

CHLD, CONT또는 을 처리해야 한다는 것을 알지 못하는 한 URG그렇지 않습니다.

요약:

기본적으로 일반적으로 사전 종료 정리를 수행하려는 경우 HUP, INT, PIPE 및 TERM을 처리(또는 무시)해야 한다고 생각합니다. 프로그램이 해당 신호를 사용하지 않거나 모든 상황에서 절대적으로 정리가 필요한 경우가 아니면 나머지는 그대로 둘 수 있습니다.

후자의 경우 처리되지 않은 모든 신호를 공백으로 차단할 수 있지만 신호 차단 마스크는 포크 및 execve 호출 전반에 걸쳐 상속되고 ILL과 같은 신호가 프로세스 실행에서 발생하여 전송되지 않은 경우 무시하거나 차단한다는 점에 유의하십시오. kill 또는 sigqueue를 사용하면 정의되지 않은 동작이 발생합니다.

더 자세히 알고 싶다면 맨페이지와 표준을 살펴보세요. 신호는 Unix에서 매우 큰 주제이며 이를 처리하는 것은 매우 까다로울 수 있습니다.

답변2

그런 식으로 진행한다면 아마도 그 중 하나가 프로그램을 종료하기 때문에 많은 신호를 무시하게 될 것입니다. 의견에서 silynx가 제안한 것처럼 가장 좋은 조치는 이러한 신호를 분석하고 신호의 출처를 이해하는 것입니다. 결국, 프로그램이 중단되는 데는 타당한 이유가 있을 수 있습니다.

그렇게 말하면, 당신은 볼 수 있습니다signals(7)프로세스 종료를 유발할 수 있는 신호 목록을 얻으려면 다음을 수행하십시오.

SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, SIGFPE, SIGKILL, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM, SIGUSR1 및 SIGUSR2.

애플리케이션이 터미널에 연결되는 데 시간이 좀 걸린다면 처리하는 SIGINT것이 좋습니다( Ctrl+ C는 결국 꽤 유명합니다). SIGTERM이는 기본 종료 신호로 남아 있고 커널에서 사용되기 때문에(예: 시스템 종료 시) 좋은 생각이기도 합니다. SIGQUIT코어 덤프를 유발하므로 아마도 이전 두 버전보다 "가혹한" 버전일 것입니다. 그 메시지를 받으면 프로그램이 즉시 중단될 것으로 예상됩니다. 다른 항목 중 하나를 수신하면 프로그램은 "엉망진창을 정리하고 종료"(설정을 저장하고 적절하게 종료)해야 합니다.

SIGILL, SIGFPE, SIGSEGVSIGPIPE은 프로그램 오작동과 관련된 신호입니다.세그멘테이션 오류아마도 가장 반복되는 상황이겠지만, 결국 이 모든 경우는 버그로 취급될 수 있고, 신호를 잡는 것이 이러한 상황에서 회복하는 최선의 방법이라고 생각하지 않습니다.

  • 대부분의 경우 컴파일러는 SIGILL그렇게 쉽게 발생하도록 허용하지 않습니다(여기에 더) 그러니 그건 따로 치워두셔도 될 것 같아요.
  • 0으로 나누지 않도록 주의하세요. 그러면 대부분의 SIGFPEs를 피할 수 있습니다. 그 외에는 프로그램이 수학에 능숙하고 숫자에 너무 집착하지 않는지 확인하세요.
  • SIGSEGV이는 여러 가지 이유(불법적인 메모리 액세스, 불법적인 역참조)로 인해 발생할 수 있으며, 그런 경우에는 gdb프로그램이 실행될 때 프로그램을 감시하고 gdb의 스택을 사용하여 불쾌한 명령을 추적하는 데 사용하는 것이 좋습니다.
  • 마지막으로 SIGPIPE대부분 데이터 스트림(파일 읽기, 연결 등)과 관련이 있습니다. 프로그램 I/O 스트림이 실행 중 종료될 가능성이 있는 경우 프로그램을 사용하기 전에 설명자를 확인하고 (사용 시 select또는 poll예를 들어) 발생하는 모든 I/O 이벤트를 처리하는지 확인해야 합니다. gdb여기에서도 유용할 수 있습니다.

SIGABRT, SIGALRM, SIGUSR1SIGUSR2은 기본적으로 사용자 신호입니다. 당신이 그것을 받고 있다면 실제로 그런 일이 일어날 가능성이 있습니다.

이로 인해 잡히지 않을 수 있는 SIGHUP및 이 남게 됩니다 .SIGKILL

  • SIGHUP예를 들어 터미널에서 프로세스를 시작하고 나중에 프로세스를 분리하지 않고( disown또는 사용 nohup) 해당 터미널을 닫는 경우에 발생합니다. 프로그램이 터미널에서 시작되어 데몬으로 실행되는 경우 예를 들어 이중 분기를 통해 셸에서 자체적으로 분리되도록 하는 것을 잊지 마십시오. 이 특정 신호는 프로그램이 GUI에서 시작되거나 부팅 시 제어 터미널이 "닫힐" 가능성이 적은 경우 관련성이 적습니다.

  • SIGKILL아시다시피 신호의 전능자입니다. 이는 커널이 "sh*t up!"이라고 말하는 방식입니다. 이를 수신한다면 프로그램에서 신호를 처리하는 방법보다는 신호를 내보내는 항목에 주의를 집중해야 합니다.

결국 신호를 분석하고 디버깅 도구를 사용하는 것이 이러한 문제에 대한 가장 간단한 접근 방식일 것입니다. 프로그램이 오작동할 때 커널에 의해 신호가 트리거되면 gdb문제를 찾는 데 도움이 됩니다. 이 경우 신호는 잊어버리고 신호가 알려주는 버그에만 집중하세요.

신호가 "외부"에서 오는 경우 이미터를 찾는 것이 아마도 최선의 조치일 것입니다.(정말 못찾으시는 분들은트레이싱그만큼kill(2)시스템 호출은 최후의 수단이 될 수 있습니다). 그런 다음 무시할 것인지( SIG_IGN) 고려할 것인지 결정할 수 있습니다. 방출 프로그램을 음소거하는 것도 괜찮은 대안이 될 수 있습니다...

관련 정보