CPU에는 리소스를 보호하기 위해 OS를 지원하는 메커니즘이 있습니다. x86 칩의 예제를 사용합시다. eax
과 같은 "범용"레지스터는 보호되지 않습니다. 그러나 디버그 레지스터 (예 : DR0
)가 있습니다.
OS가 실행 중일 때 CPU는 "ring 0"또는 일반 용어를 사용하기 위해 "시스템 모드"라고하는 사람들이 실행 중입니다. 프로그램은 x86에서 "ring 3"을 실행하거나 사람들이 "사용자 모드"라고 부르는 것을 실행합니다.
실행이 링 3에서 링 0으로 바뀌면 (자세한 내용은 나중에 설명합니다) CPU가 사용자 모드의 보호 기능을 중단합니다. 이것이 OS가 디버그 레지스터를 변경할 수있게 해줍니다.
그러나 OS가 보호하는 가장 중요한 것은 메모리 위치와 장치 입력/출력입니다. 이러한 이유 때문에 in
과 out
명령어는 권한이 있으며 링 3에서는 실행되지 않을 수 있습니다.
메모리는 TLB를 통해 보호되며 사용자 모드에서 볼 수있는 가상 메모리 (VM) 주소 레인저를 정의하는데도 사용됩니다 프로세스. 각 프로세스에서 볼 수있는 메모리 공간을 제어하는 것은이 테이블입니다. TLB 자체는 링 0 운영 체제 만 수정할 수있는 메모리에 저장됩니다. 유사하게, 인터럽트 벡터 및 임의의 메모리 - 맵 장치는 OS만이 액세스 할 수있는 메모리 범위에 할당된다.
실행하면 예 :, mov [eax], 3
, eax가 참조하는 주소는 TLB에서 조회됩니다. CPU는 명령이 메모리에 합법적으로 액세스하는지 여부를 TLB의 액세스 비트 (예를 들어, NOEXEC 비트)로부터 결정한다.
OS 스케줄러에 의해 프로세스가 스왑 될 때, eax
과 같은 범용 레지스터는 OS가 유지 관리하는 스레드 단위 메모리 영역에 저장됩니다. 전환 된 스레드는 이전 레지스터 값의 메모리 이미지에서 복원됩니다.
OS가 모든 기계 명령어를 방해하면 컴퓨터의 속도가 매우 느려질 수 있습니다. 특히, 일반 레지스터에 대한 액세스는 가능한 한 빨리 유지되어야합니다. 메모리 액세스에 대한 TLB 룩업은 캐시되고 메모리 액세스 자체보다 느리지는 않습니다.
링 3에서 링 0으로 전환하려면 소프트웨어 인터럽트가 생성됩니다. 이것은 "시스템 호출"인터럽트입니다. 인터럽트는 링 0에서 실행되며 첫 번째 프로세스가 시작되기 전에 OS에 의해 구성됩니다. 시스템 호출 인터럽트는 제어를 OS 코드로 넘깁니다. 실행이 인터럽트 서비스 루틴에서 돌아 오면 CPU는 링 3으로 되돌아갑니다.
CPU는 어셈블리를 이해하지 못합니다. 이것은 중간 형태이다. CPU는 기계 명령어를 이해합니다. 또한 시스템 호출을 어셈블리에 사용할 수 없다고 생각하는 이유는 무엇입니까? –
그 점을 이해합니다. 그러나 레지스터를 사용하는 어셈블리 요청 권한이나 메모리 액세스/쓰기 권한 또는 CPU 작업을 수행 할 수있는 권한을 보지 못했습니다. 그러나 아래의 응답을 기반으로 커널은 커널이 할당 한 리소스 내에서 수행하는 작업을 보장합니다. 새로운 질문은 모든 명령이 커널을 거쳐야한다는 것입니까? – Dmitry
무엇이든 수행하고 어셈블리를 컴파일하는 C 프로그램을 작성하면 액세스하려는 모든 것을 액세스하는 "어셈블리 프로그램을"볼 수 있습니다. 컴파일러와 어셈블러 사이의 어셈블리 단계를 "쳐다 보지"않은 경우 잘못된 권한 (응용 프로그램 공간에서 커널 코드를 실행하려고 시도)을 사용하면 더 이상 작동하지 않습니다. (대부분의 컴파일러, gcc는 확실히 어셈블리로 컴파일 한 다음 어셈블리로 저장하므로 모든 프로그램의 어셈블리 코드를 저장하고 저장할 수 있습니다). –