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

이렇게 하면 그 중 하나가 프로그램을 종료한다는 이유로 많은 수의 신호를 무시하게 될 수 있습니다. sblingx가 의견에서 제안한 것처럼 가장 좋은 방법은 이러한 신호를 분석하고 신호가 어디서 오는지 이해하는 것입니다. 결국, 귀하의 프로그램은 아마도 합당한 이유로 종료되었을 것입니다.

그렇게 말하면 다음을 살펴볼 수 있습니다.signals(7)프로세스 종료를 유발할 수 있는 신호 목록을 가져옵니다.

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

애플리케이션이 터미널에 연결하는 데 시간이 좀 걸린다면 처리하는 SIGINT것이 좋습니다(결국 Ctrl+는 매우 유명합니다). 또한 이는 여전히 기본적인 종료 신호이고 커널에서 사용되므로(예: 시스템이 종료될 때) 좋은 아이디어입니다. 아마도 코어 덤프를 유발하므로 처음 두 버전보다 "더 어려운" 버전일 것입니다. 이 메시지를 받으면 프로그램이 즉시 중단될 수 있습니다. 추가 정보를 받은 후 프로그램은 "혼란을 정리하고 사라집니다"(설정을 저장하고 적절하게 종료).CSIGTERMSIGQUIT

SIGILL, SIGFPE, SIGSEGVSIGPIPE은 프로그램 오작동과 관련된 신호입니다.세그멘테이션 오류아마도 가장 일반적인 경우일 것입니다. 그러나 궁극적으로 이러한 경우는 모두 오류로 간주될 수 있으며 신호를 잡는 것이 이러한 경우를 복구하는 가장 좋은 방법은 아니라고 생각합니다.

  • 대부분의 경우 컴파일러는 SIGILL이러한 일이 쉽게 발생하도록 허용하지 않습니다(여기에서 더 알아보기) 그러니 이건 따로 남겨두셔도 될 것 같아요.
  • 대부분의 s를 피하기 위해 절대로 0으로 나누지 마십시오 SIGFPE. 그 외에는 프로그램이 수학에 능숙하고 숫자에 열중하지 않는지 확인하세요.
  • SIGSEGVgdb이는 여러 가지 이유(불법적인 메모리 액세스, 불법적인 역참조)로 인해 발생할 수 있으며, 이를 위해 프로그램이 실행되는 동안 프로그램을 모니터링하고 불쾌한 명령에 대한 스택 추적을 사용하는 것이 좋습니다 .gdb
  • 마지막으로 SIGPIPE주로 데이터 흐름(파일 읽기, 연결...)과 관련됩니다. 프로그램 I/O 스트림이 실행 중에 종료될 가능성이 있는 경우 프로그램이 사용하기 전에 해당 설명자를 확인하고 해당 스트림에서 발생하는 모든 I/O 이벤트를 처리하는지 확인해야 합니다(예: 또는 .select 여기에서도 유용할 수 있습니다.pollgdb

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

이로 인해 캡처되지 않을 수 있는 SIGHUP및 이 남게 됩니다 .SIGKILL

  • SIGHUP예를 들어, 터미널에서 프로세스를 시작한 다음 프로세스를 분리( disown또는 사용 )하지 않고 해당 터미널을 닫는 경우 nohup이런 일이 발생할 수 있습니다 . 프로그램이 터미널에서 시작되어 데몬으로 실행되는 경우 이중 분기 등을 통해 프로그램을 셸에서 분리하는 것을 잊지 마세요. 이 특정 신호는 프로그램이 GUI에서 시작될 수 있거나 시작 시 제어 터미널이 "닫힐" 가능성이 없는 경우 관련성이 적습니다.

  • SIGKILL아시다시피 이것은 보편적 기호입니다. 이것은 커널이 "저리 가세요!"라고 말하는 방식입니다. 해당 신호를 받으면 프로그램에서 신호를 처리하는 방법이 아니라 신호를 보내는 내용에 집중해야 합니다.

마지막으로 신호를 분석하고 디버깅 도구를 사용하는 것이 이러한 문제를 해결하는 가장 쉬운 방법일 수 있습니다. 프로그램에 문제가 있을 때 커널이 신호를 트리거하면 gdb문제를 찾는 데 도움이 됩니다. 이 경우 신호는 잊어버리고 오류에 대해 알려주는 내용에만 집중하세요.

신호가 "외부"에서 오는 경우 송신기를 찾는 것이 아마도 최선의 조치일 것입니다.(정말 못찾으시면이것kill(2)시스템 호출은 최후의 수단일 수 있음). 그런 다음 무시할 것인지( SIG_IGN) 고려할 것인지 결정할 수 있습니다. 자동 실행 프로그램도 좋은 옵션이 될 수 있습니다.

관련 정보