Linux에서 신호는 어떻게 "전달"됩니까?

Linux에서 신호는 어떻게 "전달"됩니까?

Linux 신호를 설명하는 데 사용되는 용어가 혼란스럽습니다. 대부분의 텍스트에서는 "신호가 프로세스에 전달되었습니다" 또는 "신호가 스레드에 전달되었습니다"라고 말합니다.

내가 이해하는 바에 따르면, 커널이 해당 핸들러를 호출할 때 신호는 프로세스에 있는 신호 핸들러로 "전달"됩니다. 프로세스 자체는 비동기적으로 실행되며 이 "전달" 프로세스는 CPU가 인터럽트 핸들러를 호출하는 것과 유사합니다. 인터럽트 처리기(신호 처리기)는 프로세스 스레드도 아니고 해당 프로세스에서 실행되는 스레드도 아닙니다. 그렇죠? 커널에 의해 시작되는 별도의 스레드입니다.

따라서 신호는 스레드나 프로세스에 전달되는 것이 아니라 프로세스에 상주하고 특정 스레드와 반드시 연관될 필요가 없는 신호 처리기에 전달됩니다. 이것이 잘못된 경우 예를 들어 "신호가 pthread에 전달됩니다"라는 용어를 정당화하는 신호 처리기와 pthread 간의 상관 관계를 알려주십시오.

답변1

신호 처리기는 주어진 프로세스의 주소 공간에 있는 함수일 뿐입니다. 이 기능은 신호가 수신될 때마다 실행됩니다. 여기에는 특별한 것이 없으며(일부 작업은 신호 처리기에서 수행되어서는 안 되지만) 특수 스레드에 상주하지도 않습니다.

신호는 종종 소프트웨어 인터럽트로 설명되지만 실제로는 비동기적이지 않습니다. * 신호가 프로세스로 전송되면 커널은 이를 프로세스의 보류 중인 신호 세트에 추가합니다. 즉시 아무 일도 일어나지 않습니다. 이 신호는 실제로는하다다음 컨텍스트의 모든 항목은 다시 사용자 공간으로 전환됩니다(시스템 호출이 반환되거나 스케줄러가 프로세스로 전환). 어떤 이유로 프로세스가 커널에서 사용자로 전환되지 않으면 신호는 보류 중인 신호 집합에 남아 실행되지 않습니다.

프로세스가 신호 처리기를 생성할 때 커널에 함수의 주소를 제공합니다. 프로세스가 신호를 수신하려고 할 때 커널 공간에서 사용자 공간으로의 다음 컨텍스트 전환은 프로세스가 커널에 들어가기 전에 가졌던 실행 컨텍스트를 복원하지 않습니다. (일반적으로 컨텍스트는 커널에 들어갈 때 저장되고 커널을 종료할 때 복원됩니다. ). 대신, 신호 처리기 위치에서 실행을 "재개"합니다. 신호 처리기가 반환되면 호출 코드를 실행합니다.rt_sigreturn(), 복원됩니다.진짜프로세스가 중단된 지점부터 계속되도록 허용하는 실행 컨텍스트입니다.

프로세스에 여러 스레드가 있는 경우(즉, 특정 스레드 그룹에 여러 프로세스가 있는 경우) 신호는 스레드 그룹의 스레드 중 하나로 무작위로 전송됩니다. 이는 스레드가 메모리와 기타 많은 리소스를 공유하고 동일한 코드를 실행하는 경우가 많기 때문입니다.

* 하드웨어 관점에서는 비동기식은 아니지만 사용자 공간 애플리케이션에 관한 한 실제로는 비동기식입니다. 이것이 때때로 소프트웨어 인터럽트라고 불리는 이유입니다.

† 컨텍스트 전환을 언급할 때는 특권을 의미합니다.또는프로세스 전환(즉, 동일한 프로세스 내에서 커널과 사용자 간의 간단한 모드 전환 및 프로세스 또는 커널 스레드 간의 "실제" 컨텍스트 전환)

답변2

인터럽트 처리기(신호 처리기)는 프로세스 스레드도 아니고 해당 프로세스에서 실행되는 스레드도 아닙니다. 그렇죠?

커널은 신호 처리기를 실행하기 위해 새 스레드를 시작하지 않습니다. 기존 스레드에서 신호 처리기를 실행합니다. 신호가 특정 스레드에 전달된다고 말할 수 있습니다. 기본적으로 스레드는 이전에 수행하던 모든 작업을 포기하고 신호 처리기를 실행합니다. 신호 처리기가 반환된 후 이전에 수행하던 작업으로 돌아갑니다. (포리스트의 대답은 커널이 이 작업을 어떻게 예약하는지에 대해 더 자세히 설명합니다.) 그러나 이 작업과 일반 함수 호출의 주요 차이점은 언제 발생하는지 제어할 수 없다는 것입니다. 예를 들어, 32비트 액세스는 원자성이지만 64비트 액세스는 그렇지 않은 플랫폼에서 int64_t신호 처리기 호출이 발생할 때 스레드가 변수에 쓸 수 있습니다. 따라서 단일 스레드 프로그램에서도 신호 처리기는 "스레드가 자체적으로 경주하는 것"을 방지해야 합니다. 따라서 신호 처리기에서 안전하게 수행할 수 있는 작업 집합은 매우 제한적입니다.

신호를 보내는 사람은 호출 등을 통해 신호를 특정 스레드로 보내 tgkill거나 전체 프로세스를 대상으로 지정하도록 선택할 수 있습니다. 신호가 프로세스로 전송되면 커널은 신호를 전달할 프로세스의 스레드 중 하나를 선택합니다. 바라보다다중 스레드 Linux 프로세스가 신호를 받으면 어떻게 되나요?

신호의 동작이 수신기를 종료하는 것이라면(예를 들어 SIGKILL, 또는 SIGTERM기본 핸들러를 사용하는 경우) 특정 스레드로 지정하더라도 전체 프로세스가 종료됩니다.

답변3

Stack Overflow에 대한 매우 유사한 질문에 대한 답변이 있습니다.https://stackoverflow.com/questions/6949025/how-are-asynchronous-signal-handlers-executed-on-linux/6949377#6949377

신호 전달됨스레드로실행을 일시 중지하고, 실행 컨텍스트(레지스터 상태, 신호 마스크 등)를 ucontext_t스택에 푸시된 객체에 저장하고, 프로그램 카운터가 등록된 신호 처리기를 가리키도록 실행 컨텍스트를 수정하고, 프로그램의 그렇지 않으면 컨텍스트를 만듭니다. 기능 입력 및 실행 재개에 대한 ABI 요구 사항을 준수합니다. 반환 주소를 나타내는 컨텍스트 부분도 sigreturn저장된 개체에서 ucontext_t상태를 복원하기 위해 시스템 호출을 수행하는 코드를 가리키도록 수정되었습니다.

관련 정보