Program Tip

POSIX 스레드 및 신호

programtip 2020. 10. 17. 12:03
반응형

POSIX 스레드 및 신호


POSIX 스레드와 POSIX 신호가 상호 작용하는 방식의 복잡성을 이해하려고 노력해 왔습니다. 특히 다음 사항에 관심이 있습니다.

  • 신호가 전달되는 스레드를 제어하는 ​​가장 좋은 방법은 무엇입니까 (처음에는 치명적이지 않다고 가정)?
  • 다른 스레드 (실제로 사용 중일 수 있음)에 신호가 도착했음을 알리는 가장 좋은 방법은 무엇입니까? (나는 이미 신호 처리기에서 pthread 조건 변수를 사용하는 것이 좋지 않다는 것을 알고 있습니다.)
  • 신호가 발생한 정보를 다른 스레드로 전달하는 것을 어떻게 안전하게 처리 할 수 ​​있습니까? 이것이 신호 처리기에서 발생해야합니까? (일반적으로 다른 스레드를 죽이고 싶지는 않습니다. 훨씬 더 미묘한 접근 방식이 필요합니다.)

내가 이것을 원하는 이유에 대한 참조로 TclX 패키지를 스레드를 지원 하도록 변환 하거나 분할하고 적어도 유용한 부분이 스레드를 지원하도록 만드는 방법을 연구 하고 있습니다. 신호는 특히 흥미로운 부분 중 하나입니다.


  • 신호가 전달되는 스레드를 제어하는 ​​가장 좋은 방법은 무엇입니까?

@ zoli2k가 지적했듯이, 처리하려는 모든 신호를 처리 할 단일 스레드 (또는 특정 신호 책임이있는 스레드 집합)를 명시 적으로 지정하는 것은 좋은 기술입니다.

  • 신호가 도착했음을 다른 스레드 (실제로 사용 중일 수 있음)에 알리는 가장 좋은 방법은 무엇입니까? [...]
  • 신호가 발생한 정보를 다른 스레드로 전달하는 것을 어떻게 안전하게 처리 할 수 ​​있습니까? 이것이 신호 처리기에서 발생해야합니까?

"최고"라고 말하지 않겠습니다.하지만 여기에 권장 사항이 있습니다.

main모든 스레드가 해당 신호 마스크를 상속하도록 에서 원하는 모든 신호를 차단합니다 . 그런 다음 특수 신호 수신 스레드를 신호 구동 이벤트 루프로 만들어 새로 도착한 신호를 다른 스레드 내 통신으로 전달 합니다.

이 작업을 수행하는 가장 간단한 방법은 스레드가 사용 루프에서 신호를 수신하는 것입니다 sigwaitinfosigtimedwait . 그런 다음 스레드는 어떤 식 으로든 신호를 변환합니다. 아마도를 브로드 캐스팅하고 pthread_cond_t, 더 많은 I / O를 사용하여 다른 스레드를 깨우고, 응용 프로그램 별 스레드 안전 대기열에 명령을 넣습니다.

또는 특수 스레드를 사용하면 신호를 처리 할 준비가 된 경우에만 전달을 위해 마스크를 해제하여 신호 처리기에 신호를 전달할 수 있습니다. (처리기를 통한 신호 전달은 sigwait패밀리 를 통한 신호 수용보다 오류가 더 발생하기 쉽습니다 .)이 경우 수신자의 신호 처리기는 sig_atomic_t플래그 설정 , 호출 sigaddset(&signals_i_have_seen_recently, latest_sig), write() 바이트 와 같은 간단한 비동기 신호 안전 작업을 수행합니다. 비 - 블로킹 자기 파이프 등 그리고, 다시 메인 마스크 루프 스레드는 상기 다른 스레드에 신호의 수신을 통신한다.

( 업데이트 @caf는 sigwait접근 방식이 우수하다는 것을 올바르게 지적합니다 .)


POSIX 표준에 따르면 모든 스레드는 시스템에서 동일한 PID로 나타나야하며 사용 pthread_sigmask()하면 모든 스레드에 대한 신호 차단 마스크를 정의 할 수 있습니다.

PID 당 하나의 신호 처리기 만 정의 할 수 있기 때문에 모든 신호를 하나의 스레드에서 처리 pthread_cancel()하고 실행중인 스레드를 취소해야하는 경우 전송하는 것을 선호합니다 . pthread_kill()스레드에 대한 정리 기능을 정의 할 수 있기 때문에 선호되는 방법 입니다.

일부 구형 시스템에서는 적절한 커널 지원이 없기 때문에 실행중인 스레드가 부모 스레드의 PID와 다른 PID를 가질 수 있습니다. Linux 2.4 에서 linuxThreads를 사용한 신호 처리에 대한 FAQ를 참조하십시오 .


IMHO, Unix V 신호 및 posix 스레드는 잘 섞이지 않습니다. Unix V는 1970입니다. POSIX는 1980입니다.

취소 지점이 있으며 하나의 응용 프로그램에서 신호와 pthread를 허용하면 결국 각 호출 주위에 루프를 작성하게되어 놀랍게도 EINTR을 반환 할 수 있습니다.

그래서 내가 리눅스 나 QNX에서 멀티 스레드를 프로그래밍해야하는 (몇 안되는) 경우에서 한 것은 모든 (그러나 하나의) 스레드에 대한 모든 신호를 마스킹하는 것이었다.

Unix V 신호가 도착하면 프로세스는 스택을 전환합니다 (즉, 프로세스 내에서 얻을 수있는만큼 Unix V의 동시성).

여기에있는 다른 포스트가 암시 하듯이, 어떤 posix 스레드가 해당 스택 스위칭의 희생자가 될 것인지 시스템에 알리는 것이 가능할 수 있습니다.

일단 시그널 핸들러 스레드가 작동하도록 관리하면 시그널 정보를 문명화 된 것으로 변환하는 방법, 다른 스레드가 사용할 수있는 방법에 대한 의문이 남아 있습니다. 스레드 간 통신을위한 인프라가 필요합니다. 유용한 한 패턴은 액터 패턴으로, 각 스레드가 일부 처리중인 메시징 메커니즘의 대상이됩니다.

따라서 다른 스레드를 취소하거나 그것들 (또는 다른 이상한 것들)을 죽이는 대신 Signal 컨텍스트에서 Signal 핸들러 스레드로 Signal을 마샬링 한 다음 액터 패턴 통신 메커니즘을 사용하여 의미 론적으로 유용한 메시지를 해당 액터에게 보내야합니다. 신호 관련 정보가 필요한 사람.


지금까지 내가있는 곳 :

  • 신호는 다른 주요 클래스로 제공되며, 그중 일부는 일반적으로 어쨌든 프로세스를 종료해야하며 (SIGILL) 일부는 아무것도 할 필요가 없습니다 (SIGIO, 어쨌든 비동기 IO를 수행하는 것이 더 쉽습니다). 이 두 클래스는 조치가 필요하지 않습니다.
  • 일부 신호는 즉시 처리 할 필요가 없습니다. SIGWINCH와 같은 것은 편리 할 때까지 대기열에 넣을 수 있습니다 (X11의 이벤트처럼).
  • 까다로운 것들은 당신이하는 일을 방해하지만 스레드를 지우지 않고 그들에게 응답하고 싶은 것입니다. 특히, 대화 형 모드의 SIGINT는 반응 형을 유지해야합니다.

나는 아직도를 통해 정렬 할 수있어 signalsigaction, pselect, sigwait, sigaltstack, 등의 비트와 POSIX (비 POSIX) API 조각의 전체 무리.

참고 URL : https://stackoverflow.com/questions/2575106/posix-threads-and-signals

반응형