Linux에서 인터럽트를 처리하는 방법은 무엇입니까?

Linux에서 인터럽트를 처리하는 방법은 무엇입니까?

내가 아는 전부는 그것이 프로세서 핀 Interrupt이라는 것뿐입니다. hardware signal assertion하지만 Linux 운영 체제가 이를 어떻게 처리하는지 알고 싶습니다.
중단이 발생하면 어떻게 되나요?

답변1

이는 낮은 수준의 처리에 대한 높은 수준의 보기입니다. 저는 단순하고 일반적인 아키텍처를 설명하고 있습니다. 실제 아키텍처는 더 복잡하거나 여러 면에서 다를 수 있지만 이 정도의 세부 수준에서는 문제가 되지 않습니다.

언제방해하다이런 일이 발생하면 프로세서는 인터럽트가 마스크되었는지 확인합니다. 그렇다면 마스크가 벗겨지기 전까지는 아무 일도 일어나지 않습니다. 인터럽트가 마스크되지 않은 경우 프로세서는 보류 중인 인터럽트가 있으면 하나를 선택합니다.

그런 다음 프로세서는 메모리의 특정 주소로 분기하여 인터럽트를 수행합니다. 해당 주소의 코드는 다음과 같습니다.인터럽트 핸들러. 프로세서가 거기에서 분기하면 인터럽트를 마스크하고(인터럽트 처리기가 독점 제어권을 가지게 됨) 일부 레지스터의 내용을 어딘가(일반적으로 다른 레지스터)에 저장합니다.

인터럽트 핸들러는 일반적으로 데이터를 보내거나 받기 위해 인터럽트를 트리거한 주변 장치와 통신하여 수행해야 하는 작업을 수행합니다. 타이머에 의해 인터럽트가 발생하면 핸들러는 운영 체제 스케줄러를 트리거하여 다른 스레드로 전환할 수 있습니다. 핸들러는 실행을 완료하면 저장된 레지스터를 복원하고 인터럽트 마스크를 해제하는 특수 인터럽트 반환 명령을 실행합니다.

인터럽트 핸들러는 다른 인터럽트가 실행되는 것을 방지하므로 빠르게 실행되어야 합니다. Linux 커널에서 인터럽트 처리는 두 부분으로 나뉩니다.

  • "상반부"는 인터럽트 핸들러입니다. 이는 일반적으로 하드웨어와 통신하고 커널 메모리 어딘가에 플래그를 설정하는 등 필요한 최소한의 작업을 수행합니다.
  • "하위 절반"은 프로세스 메모리에 데이터 복사, 커널 데이터 구조 업데이트 등과 같은 기타 필요한 처리를 수행합니다. 인터럽트가 활성화된 상태에서 실행 중이므로 시간이 걸릴 수 있으며 시스템의 다른 부분을 기다리는 것이 차단될 수도 있습니다.

평소와 같이 이 주제에 대한 자세한 내용을 보려면 다음을 읽어보세요.리눅스 장치 드라이버;제10장중단에 관한 것입니다.

답변2

자일스는설명하다일반적인 인터럽트에 관해서는 다음 사항이 특히 Intel 아키텍처 기반 Linux 2.6에 적용됩니다(일부는 Intel 사양을 기반으로 함).

인터럽트는 프로세서가 명령을 실행하는 순서를 변경하는 이벤트입니다.
인터럽트에는 두 가지 유형이 있습니다.

  • 동기화 중단(예외)명령어를 처리할 때 CPU에서 생성됨
  • 비동기 인터럽트(인터럽트)다른 하드웨어 장치에서 발행됨

프로그래밍 오류로 인해 예외가 발생했습니다(fe나눗셈 오류,페이지 오류,과다)은 커널에 의해 처리되어야 합니다. 그는 프로그램에 신호를 보내고 오류 복구를 시도합니다.

다음 두 가지 예외가 분류됩니다.

  • 프로세서에서 예외가 감지되었습니다.비정상적인 상황이 감지되면 CPU에 의해 생성됩니다.잘못일반적으로 교정이 가능하며,이행보고,중단하다모든 심각한 실수.
  • 프로그래밍된 예외프로그래머가 요청하고 트랩처럼 처리됩니다.

인터럽트는 I/O 장치(키보드, 네트워크 어댑터 등), 간격 타이머 및 (다중 프로세서 시스템의 경우) 기타 CPU에서 발생할 수 있습니다. 인터럽트가 발생하면 CPU는 현재 명령어를 중지하고 새로 도착한 인터럽트를 실행해야 합니다. 그는 인터럽트를 처리한 후 (아마도) 복원하기 위해 이전에 중단된 프로세스 상태를 저장해야 합니다.

인터럽트 처리는 민감한 작업입니다.

  • 인터럽트는 언제든지 발생할 수 있으며 커널은 가능한 한 빨리 인터럽트를 제거하려고 시도합니다.
  • 인터럽트는 다른 인터럽트에 의해 중단될 수 있습니다.
  • 커널에는 절대 중단할 수 없는 영역이 있습니다.

두 가지 다른 인터럽트 수준이 정의됩니다.

  • 마스크 가능한 인터럽트I/O 장치에서 방출되며 차폐 또는 비차폐의 두 가지 상태가 될 수 있습니다. 마스크되지 않은 인터럽트만 처리됩니다.
  • 차폐 불가능 인터럽트;중요한 오류(예: 하드웨어 오류)는 항상 CPU에 의해 처리됩니다.

각 하드웨어 장치에는 고유한 IRQ(인터럽트 요청) 라인이 있습니다. IRQ는 0부터 번호가 매겨집니다. 모든 IRQ 라인은 PIC(Programmable Interrupt Controller)에 연결됩니다. PIC는 IRQ를 수신하고 이를 CPU에 할당합니다. 특정 IRQ 라인을 비활성화하는 것도 가능합니다.
최신 다중 처리 Linux 시스템에는 IRQ 요청을 CPU 간에 균등하게 분배하는 최신 APIC(Advanced PIC)가 포함되는 경우가 많습니다.

인터럽트 또는 예외와 해당 처리 사이의 중간 단계는 IDT(인터럽트 설명자 테이블)입니다. 이 테이블은 각 인터럽트 또는 예외 벡터(숫자)를 지정된 핸들러(fe나눗셈 오류함수 divide_error())에 의해 처리됩니다.

IDT를 통해 커널은 발생하는 인터럽트나 예외를 처리하는 방법을 정확히 알고 있습니다.


그렇다면 인터럽트가 발생하면 커널은 무엇을 할까요?

  • CPU는 각 명령어를 실행한 후 (A)PIC에서 IRQ를 확인합니다.
  • 그렇다면 IDT에 문의하여 수신된 벡터를 함수에 매핑하세요.
  • 승인된 소스에 의해 인터럽트가 발생했는지 확인하십시오.
  • 중단된 프로세스의 레지스터를 저장
  • 인터럽트를 처리하기 위해 해당 함수를 호출합니다.
  • 중단된 프로세스의 최근 저장된 레지스터를 로드하고 복원을 시도합니다.

답변3

인터럽트 처리에 관련된 첫 번째 참가자는 주변 하드웨어 장치, 인터럽트 컨트롤러, CPU, 운영 체제 커널 및 드라이버입니다. 주변 하드웨어 장치는 인터럽트 생성을 담당합니다. 운영 체제 커널의 주의가 필요할 때 인터럽트 요청 라인을 주장합니다. 이러한 신호는 인터럽트 신호 수집을 담당하는 인터럽트 컨트롤러에 의해 다중화됩니다. 또한 인터럽트 신호가 CPU에 전달되는 순서를 결정하는 역할도 담당합니다. 인터럽트 컨트롤러에는 특정 인터럽트 요청 라인(IRQL)을 일시적으로 비활성화하고 다시 활성화하는 기능(IRQL 마스킹)이 있습니다. 인터럽트 컨트롤러는 수집된 인터럽트 요청을 순차적으로 CPU에 전달합니다. 각 명령어가 실행된 후 CPU는 인터럽트 컨트롤러로부터 보류 중인 인터럽트 요청이 있는지 확인합니다. CPU가 대기 요청을 감지하고 내부 CPU 제어 레지스터에 인터럽트 활성화 플래그가 설정되면 CPU는 인터럽트 처리를 시작합니다. 리눅스 커널은 CPU의 인터럽트 플래그를 동작시키고 인터럽트 컨트롤러와 통신하여 인터럽트의 수용을 제어하는 ​​것을 볼 수 있다. 예를 들어 Linux는 특정 장치의 인터럽트 수락을 비활성화하거나 전혀 비활성화할 수 있습니다.

프로세서가 인터럽트 요청을 받으면 어떻게 되나요? 첫째, CPU는 인터럽트 플래그를 재설정하여 자동으로 인터럽트를 비활성화합니다. 인터럽트 처리가 완료되면 다시 활성화됩니다. 동시에 CPU는 CPU를 사용자 모드에서 커널 모드로 전환하는 데 필요한 최소한의 작업을 완료하여 중단된 코드 실행을 재개할 수 있습니다. CPU는 제어가 전달될 코드 주소를 찾기 위해 Linux 커널에 의해 채워진 특수 CPU 제어 구조를 참조합니다. 이 주소는 Linux 커널의 일부인 인터럽트 핸들러의 첫 번째 명령어 주소입니다.

인터럽트 처리의 첫 번째 단계로 커널은 수신된 인터럽트 벡터를 식별하여 시스템에서 어떤 종류의 이벤트가 발생했는지 식별합니다. 인터럽트 벡터는 Linux가 이를 처리하기 위해 취할 조치를 정의합니다. 두 번째 단계에서 Linux는 중단된 프로그램에서 사용될 수 있는 나머지 CPU 레지스터를 저장합니다(CPU는 이를 자동으로 저장하지 않습니다). 이는 Linux가 중단된 프로그램에 대해 투명하게 인터럽트를 처리할 수 있도록 하기 때문에 매우 중요한 작업입니다. 세 번째 단계에서 Linux는 커널 환경을 설정하고 필요한 CPU 상태를 설정하여 커널 모드로의 전환을 완료합니다. 마지막으로 벡터와 관련된 인터럽트 핸들러가 호출됩니다. (x86 아키텍처 관련 예제에 대한 자세한 내용은 arch\x86\kernel\entry_32.S의 BUILD_INTERRUPT3 매크로를 확인하세요.) 주변 장치의 경우 이는 do_IRQ() 루틴입니다. (아치\x86\kernel\irq.c 참조)

벡터 관련 인터럽트 핸들러는 일반적으로 irq_enter() 및 irq_exit()를 호출하여 래핑됩니다. 이러한 함수 쌍에 포함된 코드 영역은 다른 영역에 대해 원자적이며 cli/sti 쌍에 대해서도 원자적입니다. irq_enter() 및 irq_exit()도 인터럽트 처리와 관련된 일부 통계를 캡처합니다. 마지막으로 커널은 수신된 인터럽트 벡터에 할당된 irq 번호를 찾기 위해 vector_irq 테이블을 살펴보고 (arch\x86\kernel\irq_32.c에서) handler_irq()를 호출합니다.

이 시점에서 Linux에서 인터럽트 처리의 일반적인 부분은 종료됩니다. 커널은 장치 드라이버에 의해 설치된 장치 관련 인터럽트 처리 루틴을 irq 설명자의 일부로 보고 이를 호출하기 때문입니다. 드라이버가 이러한 핸들러를 설치하지 않으면 커널은 인터럽트 컨트롤러의 인터럽트를 승인하고 일반 인터럽트 핸들러를 종료합니다.

인터럽트 처리가 완료된 후 커널은 이전에 중단된 프로그램의 상태를 복원하고 프로그램 실행을 재개합니다.

관련 정보