Unix(Posix) 프로세스가 신호를 받으면 신호 처리기가 실행됩니다.
다중 스레드 프로세스에서는 어떤 일이 발생합니까? 어떤 스레드가 신호를 수신합니까?
나는 이 문제를 처리하기 위해 신호 API를 확장해야 한다고 생각합니다(즉, 신호 처리기의 스레드를 결정할 수 있어야 함). 그러나 온라인으로 정보를 검색해 보니 Linux 커널 메일링 목록과 다른 포럼에서 1년이 넘는 논쟁이 있었습니다. . 내가 이해하는 한, Linus의 개념은 Posix 표준과 다르며 일부 호환성 계층이 먼저 구축되었지만 이제 Linux는 posix 모델을 따릅니다.
현재 상황은 어떻습니까?
답변1
POSIX의 항목"신호 생성 및 전송"는 "기본: 시스템 인터페이스 일반 정보"에서 언급되었습니다.
프로세스에 대해 생성된 신호는 하나의 스레드에만 전달됩니다. 따라서 여러 스레드가 신호를 수신할 수 있는 경우 하나의 스레드를 선택해야 합니다. 스레드의 선택은 전적으로 구현에 달려 있으며, 가능한 한 가장 광범위하고 일관된 구현을 허용하고 구현이 "가장 쉬운" 스레드에 신호를 전달할 수 있는 자유를 제공합니다(전달 용이성이 스레드마다 다른 경우).
~에서signal(7)
Linux 시스템 매뉴얼:
전체 프로세스에 대해 신호가 생성(따라서 일시 중지)될 수 있습니다(예: 다음을 사용하는 경우).
kill(2)
) 또는 특정 스레드(예: 특정 기계어 명령어의 실행으로 인해 생성된 SIGSEGV 및 SIGFPE와 같은 특정 신호는 특정 스레드에 대한 신호와 마찬가지로 스레드 지향적입니다.pthread_kill(3)
). 프로세스 제어 신호는 현재 신호를 차단하지 않는 모든 스레드에 전달될 수 있습니다. 여러 스레드의 신호가 차단되지 않으면 커널은 신호를 전달할 스레드를 선택합니다.
그리고pthreads(7)
:
스레드에는 서로 다른 대체 신호 스택 설정이 있습니다. 그러나 새 스레드의 백업 신호 스택 설정은 스레드를 생성한 스레드에서 복사되므로 스레드는 처음에 백업 신호 스택을 공유합니다(커널 2.6.16에서 수정됨).
~에서pthreads(3)
OpenBSD 시스템 매뉴얼(대체 접근 방식의 예):
신호 처리기는 일반적으로 현재 실행 스레드의 스택에서 실행됩니다.
(현재 다중 프로세서 시스템에서 여러 스레드가 동시에 실행될 때 이를 처리하는 방법을 모르겠습니다.)
POSIX 스레드의 이전 LinuxThread 구현에서는 서로 다른 개별 스레드만 신호의 대상이 되도록 허용했습니다. ~에서pthreads(7)
Linux 시스템의 경우:
LinuxThreads는 프로세스 지향 신호 개념을 지원하지 않습니다. 신호는 특정 스레드에만 보낼 수 있습니다.
답변2
더 실용적인 관점을 갖기 위해 받아 들여진 대답을 확장하여 내가 찾은 것여기.
본질은 다음과 같습니다.
신호 처리기는 프로세스별로 처리되지만 신호 마스크는 스레드별로 처리됩니다.
- 따라서 신호 처리기를 설치/제거하면(사용하여신호()또는시그액션())모든 스레드에서는 모든 스레드에 영향을 미칩니다.
- 프로세스가 신호를 받으면 핸들러는 단일 스레드에서만 실행됩니다. 스레드는 그 중에서 의사 무작위로 선택되며 해당 스레드의 신호 마스크가 이를 수락합니다.내 실험에 따르면 항상 PID가 가장 작은 스레드인 것으로 나타났습니다.*
- 스레드로 전송된 신호는 기본 프로세스로 전송된 신호로 간주됩니다. 따라서 한 스레드가 신호를 받으면 다른 스레드가 핸들러를 실행할 가능성이 높습니다. 스레드( s로 식별, 스레드 ID)가 보호된 프로세스( s로 식별)
tid
로 처리되고 a로 전송된 신호 가 해당 로 전달되는 것을 확인하면 .pid
tid
pid
- 신호 처리기 실행을 위해 주어진 신호 번호는 신호 마스크에 자동으로 마스크됩니다. 이는 스택된 신호 처리기가 신호 버스트에서 실행되는 것을 방지하기 위한 것입니다. 이는 이라는
SA_NODEFER
플래그를 통해 변경할 수 있습니다sigaction(...)
. - (3)과 (4)의 결과는 신호 버스트의 경우 시스템이 신호 처리 절차를 가장 병렬적인 방식으로 배포할 수 있다는 것입니다.
- 그러나 sigaction 을 설정
SA_NODEFER
하면항상 동일한 스레드가 신호를 수신하고 스택됩니다..
* 댓글에는 먼저 생성된 스레드일 수도 있다고 나와 있습니다. 둘 다 posix 규격이므로 코드에서 신뢰하지 마세요.