모든 최신 CPU는 현재 실행중인 기계 명령 을 중단 할 수 있습니다. 아무 일도 없었던 것처럼 나중에 실행 을 재개 할 수 있도록 충분한 상태 (일반적으로 항상 스택에있는 것은 아님)를 저장 합니다 (중단 된 명령은 처음부터 처음부터 다시 시작됨). 그런 다음 인터럽트 처리기 실행을 시작합니다. 인터럽트 처리기 는 더 많은 머신 코드이지만 CPU가 미리 어디에 있는지 알 수 있도록 특별한 위치에 배치됩니다. 인터럽트 처리기는 항상 운영 체제 커널 의 일부입니다. 가장 큰 권한으로 실행되고 다른 모든 구성 요소의 실행을 감독하는 구성 요소입니다. 1,2
인터럽트는 동기식 일 수 있습니다 . 즉, CPU 자체에서 현재 실행중인 명령에 대한 직접 응답으로 트리거되거나 비동기식 일 수 있습니다. 즉, 네트워크에 도착하는 데이터와 같은 외부 이벤트로 인해 예기치 않은 시간에 발생합니다. 포트. 일부 사람들은 비동기 인터럽트에 대해 "인터럽트"라는 용어를 예약하고 대신에 동기 인터럽트 "트랩", "오류"또는 "예외"를 호출하지만 이러한 단어는 모두 다른 의미를 가지므로 "동기 인터럽트"를 고수 할 것입니다.
이제 대부분의 최신 운영 체제에는 프로세스 개념이 있습니다 . 기본적으로 이것은 컴퓨터가 동시에 여러 프로그램을 실행할 수있는 메커니즘이지만 운영 체제가 메모리 보호를 구성하는 방법의 주요 측면이기도합니다 . 아직도 모든 ) 현대 CPU를. 그것은 가상 메모리 와 함께 간다메모리 주소와 RAM의 실제 위치 간의 매핑을 변경하는 기능입니다. 메모리 보호를 통해 운영 체제는 각 프로세스에 전용 RAM 덩어리를 제공하여 액세스 할 수 있습니다. 또한 운영 체제 (일부 프로세스를 대신하여 작동)가 RAM 영역을 읽기 전용, 실행 가능, 협력 프로세스 그룹간에 공유 등으로 지정할 수 있습니다. 또한 메모리 만 액세스 할 수있는 메모리 덩어리가 있습니다. 핵심. 삼
각 프로세스가 CPU가 허용하도록 구성된 방식으로 만 메모리에 액세스하는 한 메모리 보호는 보이지 않습니다. 프로세스가 규칙을 어기면 CPU는 동기식 인터럽트를 생성하여 커널에게 항목을 정렬하도록 요청합니다. 프로세스가 실제로 규칙을 위반 하지 않았기 때문에 프로세스가 계속 진행되기 전에 커널 만 약간의 작업을 수행해야합니다. 예를 들어, RAM의 공간을 확보하기 위해 프로세스 메모리의 페이지를 스왑 파일로 "제거"해야하는 경우 커널은 해당 페이지를 액세스 할 수 없음으로 표시합니다. 다음에 프로세스가 프로세스를 사용하려고하면 CPU가 메모리 보호 인터럽트를 생성합니다. 커널은 스왑에서 페이지를 검색하여 원래 위치로 되돌리고 다시 액세스 가능으로 표시 한 후 실행을 재개합니다.
그러나 프로세스가 실제로 규칙을 어겼다 고 가정하십시오. RAM이 매핑되지 않은 페이지에 액세스하려고 시도했거나 머신 코드를 포함하지 않는 것으로 표시된 페이지를 실행하려고했습니다. 일반적으로 "Unix"로 알려진 운영 체제 제품군은 이 상황을 처리 하기 위해 신호 를 사용 합니다. 4 신호는 인터럽트와 유사하지만 하드웨어에 의해 생성되고 커널에 의해 필드 화되는 것이 아니라 커널에 의해 생성되고 프로세스에 의해 필드 화됩니다. 프로세스는 신호 핸들러를 정의 할 수 있습니다그들 자신의 코드로 커널에게 그들이 어디에 있는지 알려주십시오. 그런 다음 해당 신호 처리기가 실행되어 필요한 경우 정상적인 제어 흐름을 방해합니다. 신호는 모두 숫자와 두 개의 이름을 가지며, 하나는 암호 약어이고 다른 하나는 약간 덜 암호 문구입니다. 프로세스가 메모리 보호 규칙을 위반할 때 생성되는 신호는 (일반적으로) 번호 11이며 이름은 SIGSEGV
"세그먼트 폴트"입니다. 5,6
신호와 인터럽트의 중요한 차이점은 모든 신호에 기본 동작 이 있다는 것입니다 . 운영 체제가 모든 인터럽트에 대한 핸들러를 정의하지 못하면 OS의 버그이며 CPU가 누락 된 핸들러를 호출하려고하면 전체 컴퓨터가 충돌합니다. 그러나 프로세스는 모든 신호에 대한 신호 처리기를 정의 할 의무가 없습니다. 커널이 프로세스에 대한 신호를 생성하고 해당 신호가 기본 동작으로 남은 경우 커널은 기본값을 그대로 유지하면서 프로세스를 방해하지 않습니다. 대부분의 신호의 기본 동작은 "아무것도하지 않음"또는 "이 프로세스를 종료하고 코어 덤프를 생성 할 수도 있습니다." SIGSEGV
후자 중 하나입니다.
요약하자면 메모리 보호 규칙을 위반 한 프로세스가 있습니다. CPU가 프로세스를 일시 중단하고 동기 인터럽트를 생성했습니다. 커널은 해당 인터럽트를 SIGSEGV
처리하여 프로세스에 대한 신호를 생성했습니다 . 의는 않은 과정을 가정 해 봅시다 하지 위한 신호 처리기를 설정을 SIGSEGV
, 그래서 커널은 프로세스를 종료하는 기본 동작을 수행한다. 이것은 _exit
시스템 호출 과 동일한 효과를 갖습니다 . 열린 파일이 닫히거나 메모리가 할당 해제됩니다.
이 시점까지는 사람이 볼 수있는 메시지가 인쇄되지 않았으며 쉘 (또는 더 일반적으로 막 종료 된 프로세스 의 상위 프로세스 )은 전혀 관여하지 않았습니다. 부모가 아닌SIGSEGV
규칙을 어기는 프로세스로 이동합니다 . 그러나 순서 의 다음 단계는 상위 프로세스에 하위 프로세스가 종료되었음을 알리는 것입니다. 이것은 부모가 이미 중 하나를 사용하여,이 통지 될 때까지 대기하는 경우에 간단한이있는 여러 가지 방법에 일어날 수있는 시스템 호출 ( , , , 등). 이 경우 커널은 시스템 호출을 반환하고 상위 프로세스에 종료 상태 라는 코드 번호를 제공 합니다.wait
wait
waitpid
wait4
. 7 종료 상태는 부모에게 자식 프로세스가 종료 된 이유를 알려줍니다 . 이 경우 SIGSEGV
신호 의 기본 동작으로 인해 자식이 종료되었음을 알게됩니다 .
그런 다음 부모 프로세스는 메시지를 인쇄하여 이벤트를 사람에게보고 할 수 있습니다. 쉘 프로그램은 거의 항상 이것을합니다. 당신은 crsh
이 작업을 수행하는 코드를 포함하지 않지만 C 라이브러리 루틴이 있기 때문에, 어쨌든 발생하는 system
모든 기능을 갖춘 쉘 실행 /bin/sh
"후드"를. 이 시나리오 crsh
에서 조부모 입니다. 부모 프로세스 알림은으로 필드 화되어 /bin/sh
일반적인 메시지를 인쇄합니다. 그런 다음 /bin/sh
더 이상 할 일이 없으므로 자체 종료됩니다. C 라이브러리의 구현은 해당 종료 알림 을 system
수신 합니다 . 의 반환 값을 검사하여 코드에서 종료 알림을 볼 수 있습니다.system
; 그러나 손자 프로세스가 segfault에서 죽었다는 것을 알 수는 없습니다. 중간 쉘 프로세스에서 사용 되었기 때문입니다.
각주
일부 운영 체제는 커널의 일부로 장치 드라이버 를 구현하지 않습니다 . 그러나 모든 인터럽트 처리기는 여전히 커널의 일부 여야하며, 하드웨어는 커널 이외 의 다른 작업을 허용하지 않기 때문에 메모리 보호를 구성하는 코드도 마찬가지 입니다.
커널보다 더 많은 권한을 가진 "하이퍼 바이저"또는 "가상 머신 관리자"라는 프로그램이있을 수 있지만이 답변의 목적 상 하드웨어의 일부로 간주 될 수 있습니다 .
커널은 프로그램 이지만 프로세스 는 아닙니다 . 도서관과 비슷합니다. 모든 프로세스는 자체 코드 외에도 때때로 커널 코드의 일부를 실행합니다. 커널 코드 만 실행 하는 많은 "커널 스레드"가 있을 수 있지만 여기서는 신경 쓰지 않습니다.
유닉스의 구현으로 간주 될 수없는 더 이상 처리해야 할 유일한 OS 는 물론 Windows입니다. 이 상황에서는 신호를 사용하지 않습니다. (실제로 는 신호 가 없으며, Windows에서는 <signal.h>
인터페이스가 C 라이브러리에 의해 완전히 위조됩니다.) 대신 " 구조적 예외 처리 " 라는 것을 사용 합니다.
일부 메모리 보호 위반은 SIGBUS
대신 ( "버스 오류")를 생성 SIGSEGV
합니다. 둘 사이의 선이 지정되어 있지 않으며 시스템마다 다릅니다. 에 대한 핸들러를 정의하는 프로그램을 작성한 경우에 SIGSEGV
대해 동일한 핸들러를 정의하는 것이 좋습니다 SIGBUS
.
"세그먼트 결함"은 원래 Unix 를 실행 한 컴퓨터 중 하나 ( 아마 PDP-11)에 의해 메모리 보호 위반에 대해 생성 된 인터럽트의 이름입니다 . " 세그먼트 화 "는 메모리 보호의 한 유형 이지만, 현재 "세그먼트 화 오류 " 라는 용어 는 일반적으로 모든 종류의 메모리 보호 위반을 의미합니다.
부모 프로세스에 자식이 종료되었음을 알리는 다른 모든 방법은 결국 부모 호출 wait
및 종료 상태를 수신하게됩니다. 다른 일이 먼저 일어난다는 것입니다.
crsh
이런 종류의 실험에 좋은 아이디어입니다. 우리 모두와 그 배경에 대한 아이디어를 알려 주셔서 감사합니다.