sourcecode

간단한 리눅스 신호 처리

copyscript 2023. 10. 16. 22:01
반응형

간단한 리눅스 신호 처리

가 를 .kill또는 프로세스를 종료할 수 있습니다.

여기 코드와 메인()의 모양이 있습니다.

static int terminate = 0;  // does this need to be volatile?

static void sighandler(int signum) { terminate = 1; }

int main() {
  signal(SIGINT, sighandler);
  // ...
  // create objects, spawn threads + allocate dynamic memory
  // ...
  while (!terminate) sleep(2);
  // ...
  // clean up memory, close threads, etc.
  // ...
  signal(SIGINT, SIG_DFL);  // is this necessary?
}

몇 가지 궁금한 점이 있습니다.

  1. 신호 처리가 필요합니까?
    나는 이 스레드에서 "Linux C catching kill signal for graceful termination"을 읽었는데, 분명히 OS가 나를 위해 정리를 처리할 것이라고 합니다.따라서 신호 처리기를 무한 루프로만 교체하고 OS가 스레드를 우아하게 종료하도록 하거나 메모리를 할당 해제하는 등의 작업을 수행할 수 있습니까?

  2. 클린 터미네이션과 관련하여 제가 신경 써야 할 다른 신호가 있나요?"SIGINT는 다른 종료 신호와 어떤 관계가 있습니까?"라는 스레드는 관련된 모든 신호를 나열하는 데 유용했지만 실제로 필요한 처리 수는 몇 개입니까?

  3. 제 예제의 종료 변수는 변동성이 있어야 하나요?저는 이 변수가 변동성이 큰 예와 그렇지 않은 예를 많이 봤습니다.

  4. 는 그 를.signal()는 이제 더 사용되지 합니다.sigaction() 에서 정말 ?signal()전화? 새로운 구조를 만들고 통과해야 하는 데 문제가 있고 모든 것이 어떻게 맞물려 돌아가는지에 문제가 있습니다.

  5. 는 ㅇsignal()꼭 필요한가요?
    요할 때해야 할 요?sigaction()?

분명히 말씀드리지만, 제가 이루고자 하는 모든 것은 메인 루프를 작동시키는 것입니다. 또는 전원이 차단되거나 정말 나쁜 일이 발생할 때까지 말이죠.

[Q-3] 다음은?terminate제 .volatile이 를 많이 저는 이 변수가 변동성이 큰 예와 그렇지 않은 예를 많이 봤습니다.

이.terminate 것입니다volatile sig_atomic_t:

왜냐하면 핸들러 함수는 비동기적으로 호출될 수 있기 때문입니다.의 어느 수될 수 있습니다.다두 개의 신호가 매우 짧은 간격 동안 도착하면 한 핸들러가 다른 핸들러 내에서 실행될 수 있습니다.다를 이 더 .volatile sig_atomic_t이 에 대한 합니다. , 합니다.volatile컴파일러에게 최적화하지 말고 레지스터에 넣으라고 합니다.(읽기:자세한 설명을 위해 원자 데이터 액세스신호 처리).
또 하나의 참고문헌: 24.4.7 Atomic Data Access and Signal Handling또한, 7.14.1.1-5의 C11 표준은 다음과 같은 객체만을 나타냅니다.volatile sig_atomic_t신호 처리기에서 액세스할 수 있습니다(다른 accessing는 정의되지 않은 동작을 갖습니다).

[Q-4] 읽어봤습니다.signal()는 이제 더 사용되지 합니다.sigaction() 에서 정말 ?signal()전화? 새로운 구조를 만들고 통과해야 하는 데 문제가 있고 모든 것이 어떻게 맞물려 돌아가는지에 문제가 있습니다.

아래 예(및 주석의 링크)가 도움이 될 수 있습니다.

// 1. Prepare struct 
struct sigaction sa;
sa.sa_handler =  sighandler;

// 2. To restart functions if interrupted by handler (as handlers called asynchronously)
sa.sa_flags = SA_RESTART; 

// 3. Set zero 
sigemptyset(&sa.sa_mask);

/* 3b. 
 // uncomment if you wants to block 
 // some signals while one is executing. 
sigaddset( &sa.sa_mask, SIGINT );
*/ 

// 4. Register signals 
sigaction( SIGINT, &sa, NULL );

참조:

  1. 리눅스 프로그래밍 시작, 4판: 이 책에서 당신의 코드는 정확히 다음과 같이 설명되어 있습니다.sigaction()"11장: 프로세스와 신호"에서 멋지게.
  2. 예시(빠른 학습)를 포함한 서명 문서.
  3. IMT2000 3GPP - 신호처리
    *저는 1부터 시작해서 지금은 3 GNU 라이브러리를 읽고 있습니다.

[Q-5] 두 번째 통화는signal()꼭 필요한가요?요할 때해야 할 요?sigaction()?

프로그램 종료 전에 기본 액션으로 설정한 이유가 무엇인지 잘 모르겠습니다.저는 다음 단락이 여러분에게 답을 줄 것이라고 생각합니다.

신호 처리

Call to signal은 한 번의 신호 발생에 대해서만 신호 처리를 확립합니다.신호 처리 기능을 호출하기 전에 라이브러리가 신호를 재설정하여 동일한 신호가 다시 발생할 경우 기본 동작을 수행합니다.신호 처리를 재설정하면 신호 처리기에서 수행된 동작이 동일한 신호를 다시 발생시킬 경우 무한 루프를 방지하는 데 도움이 됩니다.신호가 발생할 때마다 핸들러를 신호에 사용하도록 하려면 핸들러 내에서 신호를 호출하여 복원해야 합니다.신호 처리를 복원할 때는 주의해야 합니다.예를 들어, 연속적으로 복원하는 경우SIGINT처리하면 프로그램을 중단하고 종료하는 능력을 잃을 수 있습니다.

signal()function은 다음 수신 신호의 핸들러만 정의하며, 그 후에는 기본 핸들러가 복원됩니다.따라서 신호 처리기가 전화를 걸 필요가 있습니다.signal() 프로그램이 기본값이 아닌 핸들러를 사용하여 신호를 계속 처리해야 하는 경우.

자세한 참조를 위해 토론을 읽어 보십시오.신호 처리기를 다시 활성화하는 시기.

[Q-1a] 신호 처리가 필요합니까?

네, 리눅스가 정리를 해줄 겁니다.예를 들어 파일이나 소켓을 닫지 않으면 리눅스가 프로세스가 종료된 후 정리를 수행합니다.그러나 Linux는 즉시 정리를 수행할 필요가 없을 수 있으며 시간이 걸릴 수 있습니다(시스템 성능을 높게 유지하거나 다른 문제가 발생할 수 있음).예를 들어, TCP 소켓을 닫지 않고 프로그램이 종료되는 경우 커널이 소켓을 즉시 닫지 않고 모든 데이터가 전송되었는지 확인하는 경우 TCP는 가능한 경우 전송을 보장합니다.

[Q-1b] 따라서 무한 루프만으로 신호 핸들러를 교체하고 OS가 스레드를 우아하게 빠져나가게 하고 메모리를 할당 해제하는 등의 작업을 하면 됩니까?

아니요, 운영체제는 프로그램이 종료된 후에만 정리를 수행합니다.프로세스가 실행되는 동안 해당 프로세스에 할당된 리소스는 OS에서 할당되지 않습니다. (OS는 프로세스가 무한 루프에 있는지 여부를 알 수 없습니다. 이는 해결할 수 없는 문제입니다.프로세스가 종료된 후 OS에서 정리 작업을 수행하도록 하려면 (프로세스가 신호에 의해 비정상적으로 종료된 경우에도) 신호를 처리할 필요가 없습니다.

[Q]제가 이루고자 하는 모든 것은 메인 루프를 작동시키는 것입니다. 또는 전원이 차단되거나 정말 나쁜 일이 발생할 때까지 말이죠.

아니요, 한계가 있습니다!모든 신호를 잡을 수는 없습니다.다와 신호는 할 수 SIGKILL그리고.SIGSTOP둘 다 종료 신호입니다인용:

— : intSIGKILL

SIGKILL신호는 즉시 프로그램 종료를 유도하기 위해 사용됩니다.처리하거나 무시할 수 없기 때문에 항상 치명적입니다.또한 이 신호를 차단할 수 없습니다.

따라서 중단할 수 없는 프로그램(중단되지 않는 프로그램)을 만들 수 없습니다!

확실하지는 않지만, 윈도우 시스템에서 TSR(커널 모드 후킹의 일종)을 작성하면 이와 같은 작업을 수행할 수 있을지도 모릅니다.논문 작성 당시 일부 바이러스는 작업 관리자로부터도 종료할 수 없었던 것으로 기억하지만 관리자 권한으로 사용자를 속이는 것으로 생각합니다.

이 답변이 당신에게 도움이 되길 바랍니다.

.sigaction대신 다음과 같은 함수를 사용할 수 있습니다.

/*
 * New implementation of signal(2), using sigaction(2).
 * Taken from the book ``Advanced Programming in the UNIX Environment''
 * (first edition) by W. Richard Stevens.
 */
sighandler_t my_signal(int signo, sighandler_t func)
{
    struct sigaction nact, oact;

    nact.sa_handler = func;
    nact.sa_flags = 0;
    # ifdef SA_INTERRUPT
    nact.sa_flags |= SA_INTERRUPT;
    # endif
    sigemptyset(&nact.sa_mask);

    if (sigaction(signo, &nact, &oact) < 0)
        return SIG_ERR;

    return oact.sa_handler;
}

1. 신호 처리가 필요합니까?

  • 당신이 올린 링크의 특정한 경우에는 그렇습니다.네트워크와 관련된 소프트웨어의 실행은 소켓의 실행을 방해하지 않기 위해 예를 들어 클라이언트에게 소켓의 폐쇄를 경고하는 것처럼 특정 작업이 필요합니다.
  • 특정한 경우에는 프로세스를 깔끔하게 처리하기 위해 신호를 처리할 필요가 없습니다. OS가 대신 처리해 줍니다.

2. 클린 터미네이션과 관련하여 제가 신경 써야 할 다른 신호가 있나요?

  • 먼저, 그의 페이지를 보세요: GNU 라이브러리 신호 종료 신호는 여러분이 돌보는 것입니다.하지만 SIGUSR1과 SIGUSR2는 디버깅 목적을 제외하고는 어떤 소프트웨어에서도 찾을 수 없을 지라도 한 번 살펴보시기 바랍니다.

  • 소프트를 갑자기 종료하지 않으려면 이 모든 종료 신호를 처리해야 합니다.

3. 제 예제의 종료 변수는 변동성이 있어야 하나요?

  • 절대로 그렇지 않아요.

그 4개를 읽었습니다. 읽었습니다.signal()는 이제 더 사용되지 합니다.sigaction()

  • Sigaction()신호는 C 표준인 반면 POSIX입니다.

  • Signal()저는 괜찮지만, 당신이 원하는 예가 있다면: IBM

이를 위해 신호를 사용할 필요는 없습니다.표준 종료는 적발할 필요가 없습니다.사용자가 이 문제를 해결해야 할 이유가 있겠지만, 이는 O/S가 요구하는 것보다 사용자의 애플리케이션에 달려 있습니다.

일반적으로 신호의 관점에서 요즘은 신호가 아닌 신호를 사용해야 하는데, 표준화 문제를 둘러싼 것입니다.

신호 처리기를 다시 입력하려면 기록해야 합니다.이것은 종료 변수가 변동성이 있을 필요는 없지만 사용 방법에 따라 변동성이 있을 수 있습니다.

W. Richard Stevens의 저서 "유닉스 환경에서의 고급 프로그래밍"은 신호를 처리하는 이유와 방법에 대한 좋은 예를 보여줍니다.

아니요, 애플리케이션이 종료되기 전에 기본 핸들러를 되돌릴 필요는 없습니다. 핸들러는 애플리케이션에만 유효하므로, 애플리케이션을 삭제하는 경우에는 필요하지 않습니다.

무엇보다도, 만약 여러분이 모른다면, 어떤 신호라도 처리해야 하는지, 아마 모르실 것입니다.신호는 소켓을 닫거나, 종료하기 전에 연결된 다른 프로세스로 일부 메시지를 보내거나, write()에서 SIGPIPE 신호를 처리하는 등 특정한 경우에 처리가 필요합니다.

- 로 - while (!terminate) sleep(2);별로 좋지 않습니다. 최악의 경우 사용자(또는 시스템)가 2초를 기다려 프로그램에 SIGKILL을 보내야 하는 것을 참을 수 없게 만들 수 있습니다.

여기서 IMHO의 가장 좋은 해결책은 signalfd와 select를 사용하는 것이므로 2초를 기다리지 않고 프로그램을 종료할 수 있습니다.

언급URL : https://stackoverflow.com/questions/17942034/simple-linux-signal-handling

반응형