커널 공간과 사용자 공간의 차이점은 무엇입니까? 커널 공간, 커널 스레드, 커널 프로세스 및 커널 스택이 같은 의미입니까? 또한 왜 이러한 차별화가 필요한가?
답변
정말 간단한 대답은 커널이 커널 공간에서 실행하고, 일반 프로그램은 사용자 공간에서 실행됩니다. 사용자 공간은 기본적으로 샌드 박싱의 한 형태입니다. 사용자 프로그램을 제한하여 다른 프로그램이나 OS 커널이 소유 한 메모리 (및 기타 리소스)를 엉망으로 만들 수 없습니다. 이로 인해 기계 충돌과 같은 나쁜 일을 할 수있는 능력이 제한되지만 (일반적으로 완전히 제거되는 것은 아닙니다).
커널은 운영 체제의 핵심입니다. 일반적으로 모든 메모리 및 시스템 하드웨어 (및 시스템의 다른 모든 항목)에 대한 전체 액세스 권한이 있습니다. 컴퓨터를 가능한 한 안정적으로 유지하려면 일반적으로 가장 신뢰할 수 있고 테스트를 거친 코드 만 커널 모드 / 커널 공간에서 실행하려고합니다.
스택은 메모리의 또 다른 부분이므로 당연히 나머지 메모리와 함께 분리됩니다.
답변
랜덤 액세스 메모리 (RAM)을 논리적으로, 즉 두 가지 영역으로 나눌 수 있습니다 -. 커널 공간과 사용자 공간 ( 물리적 주소 램의 실제로 나누어되지 않은 경우에만 가상 주소 , 모든이에 의해 구현 MMU )
커널은 권한이있는 메모리 부분에서 실행됩니다. 커널은 메모리의 모든 부분에 액세스 할 수있는 반면 일반 사용자의 프로세스는이 부분의 메모리에 직접 액세스 할 수 없습니다. 커널의 일부에 액세스하려면 사용자 프로세스가 호출 즉, 미리 정의 된 시스템을 사용할 필요는 open
, read
, write
등 또한, C
같은 라이브러리 함수 printf
호출 시스템 호출 write
차례입니다.
시스템 호출은 사용자 프로세스와 커널 프로세스 사이의 인터페이스 역할을합니다. 사용자가 무심코 커널을 엉망으로 만드는 것을 막기 위해 커널 공간에 액세스 권한이 부여됩니다.
따라서 시스템 호출이 발생하면 소프트웨어 인터럽트가 커널로 전송됩니다. CPU는 제어를 관련 인터럽트 핸들러 루틴으로 일시적으로 넘길 수 있습니다. 인터럽트에 의해 중단 된 커널 프로세스는 인터럽트 핸들러 루틴이 작업을 완료 한 후 재개됩니다.
답변
커널 공간과 가상 공간은 가상 메모리의 개념입니다. 램 (실제 메모리)이 커널과 사용자 공간으로 나뉘어 진 것은 아닙니다. 각 프로세스에는 가상 메모리가 주어지며 커널과 사용자 공간으로 나뉩니다.
“임의 액세스 메모리 (RAM)는 커널 공간과 사용자 공간의 두 가지 영역으로 나눌 수 있습니다.” 잘못되었습니다.
“커널 공간 대 사용자 공간”에 관한 것
프로세스가 생성되고 가상 메모리가 사용자 공간과 커널 공간으로 나뉘어지면 사용자 공간 영역에는 데이터, 코드, 스택, 프로세스 힙 및 커널 공간이 포함되며 프로세스의 페이지 테이블과 같은 것들이 포함됩니다. 커널 공간 코드를 실행하려면 제어는 커널 모드 (시스템 호출에 0x80 소프트웨어 인터럽트 사용)로 전환해야하며 커널 스택은 기본적으로 현재 커널 공간에서 실행중인 모든 프로세스간에 공유됩니다.
답변
CPU 링은 가장 분명한 차이점입니다
x86 보호 모드에서 CPU는 항상 4 개의 링 중 하나에 있습니다. Linux 커널은 0과 3 만 사용합니다.
- 커널의 경우 0
- 사용자를위한 3
이것은 커널과 사용자 영역 중 가장 어렵고 빠른 정의입니다.
Linux가 링 1과 2를 사용하지 않는 이유 : CPU Privilege Rings : 링 1과 2가 사용되지 않는 이유는 무엇입니까?
전류 링은 어떻게 결정됩니까?
현재 링은 다음의 조합으로 선택됩니다.
-
글로벌 디스크립터 테이블 : GDT 엔트리의 메모리 내 테이블이며, 각 엔트리는
Privl
링을 인코딩 하는 필드 를 갖는다 .LGDT 명령어는 주소를 현재 설명자 테이블로 설정합니다.
-
세그먼트는 GDT에서 엔트리의 인덱스를 가리키는 CS, DS 등을 등록한다.
예를 들어,
CS = 0
GDT의 첫 번째 항목이 현재 실행 코드에 대해 활성화되어 있음을 의미합니다.
각 반지는 무엇을 할 수 있습니까?
CPU 칩은 물리적으로 다음과 같이 구성됩니다.
-
링 0은 무엇이든 할 수 있습니다
-
링 3은 여러 명령을 실행할 수 없으며 여러 레지스터에 쓸 수 있습니다.
-
자신의 반지를 변경할 수 없습니다! 그렇지 않으면 자체가 링 0으로 설정 될 수 있으며 링은 쓸모가 없습니다.
즉, 현재 링을 결정하는 현재 세그먼트 디스크립터를 수정할 수 없습니다 .
-
페이지 테이블을 수정할 수 없습니다 : x86 페이징은 어떻게 작동합니까?
즉, CR3 레지스터를 수정할 수 없으며 페이징 자체가 페이지 테이블 수정을 방지합니다.
이것은 보안 / 편의 프로그래밍의 이유로 하나의 프로세스가 다른 프로세스의 메모리를 보지 못하게합니다.
-
인터럽트 핸들러를 등록 할 수 없습니다. 메모리 위치에 쓰면 구성되며 페이징으로도 방지됩니다.
처리기는 링 0에서 실행되며 보안 모델을 손상시킵니다.
즉, LGDT 및 LIDT 명령어를 사용할 수 없습니다.
-
같은 IO 지침을 할 수 없어
in
하고out
, 따라서 임의의 하드웨어 액세스가 있습니다.그렇지 않으면, 예를 들어, 프로그램이 디스크에서 직접 읽을 수있는 경우 파일 권한이 쓸모가 없습니다.
Michael Petch 덕분에 더 정확하게 는 OS가 링 3에서 IO 명령을 허용하는 것이 실제로 가능하며, 이는 실제로 작업 상태 세그먼트에 의해 제어됩니다 .
불가능한 것은 링 3이 처음에 그것을 가지고 있지 않은 경우 링 3에 권한을 부여하는 것입니다.
리눅스는 항상 그것을 허용하지 않습니다. 참고 : Linux가 TSS를 통해 하드웨어 컨텍스트 스위치를 사용하지 않는 이유는 무엇입니까?
-
프로그램과 운영 체제는 링간에 어떻게 전환됩니까?
-
CPU가 켜질 때, 링 0에서 초기 프로그램을 실행하기 시작합니다 (좋은 종류이지만 근사치입니다). 이 초기 프로그램을 커널이라고 생각할 수 있습니다 (그러나 일반적으로 링 0으로 커널을 호출하는 부트 로더입니다 ).
-
유저 랜드 프로세스가 커널이 파일에 쓰는 것과 같은 일을하기를 원할 때, 커널과 같은 인터럽트를 발생 시키
int 0x80
거나syscall
신호를 보내는 명령을 사용합니다 . x86-64 Linux syscall hello world 예제 :.data hello_world: .ascii "hello world\n" hello_world_len = . - hello_world .text .global _start _start: /* write */ mov $1, %rax mov $1, %rdi mov $hello_world, %rsi mov $hello_world_len, %rdx syscall /* exit */ mov $60, %rax mov $0, %rdi syscall
컴파일하고 실행하십시오.
as -o hello_world.o hello_world.S ld -o hello_world.out hello_world.o ./hello_world.out
이 경우 CPU는 부팅시 커널이 등록한 인터럽트 콜백 핸들러를 호출합니다. 다음은 핸들러를 등록하고 사용 하는 구체적인 베어 메탈 예제입니다 .
이 핸들러는 링 0에서 실행되며,이 커널은 커널이이 조치를 허용하는지, 조치를 수행하고, 링 3에서 userland 프로그램을 다시 시작할 것인지 결정합니다. x86_64
-
때
exec
시스템 호출을 사용하는 (또는 경우 커널 시작한다/init
), 커널은 레지스터와 메모리를 준비하고 , 새로운 유저 기반 프로세스를 다음의 엔트리 포인트로 점프 링 (3)에 CPU 스위치 -
프로그램이 금지 된 레지스터 또는 메모리 주소에 쓰기 (페이징 때문에)와 같은 잘못된 작업을 시도하면 CPU는 링 0에서 일부 커널 콜백 핸들러를 호출합니다.
그러나 사용자 영역이 좋지 않기 때문에 커널은 이번에 프로세스를 종료하거나 신호와 함께 경고를 줄 수 있습니다.
-
커널이 부팅 될 때 일정한 고정 주파수로 하드웨어 클록을 설정하여 주기적으로 인터럽트를 생성합니다.
이 하드웨어 클럭은 링 0을 실행하는 인터럽트를 생성하고 어떤 사용자 프로세스가 깨어날 지 예약 할 수 있습니다.
이런 식으로 프로세스가 시스템 호출을하지 않더라도 스케줄링이 발생할 수 있습니다.
여러 개의 고리가있는 점은 무엇입니까?
커널과 사용자 영역을 분리하면 두 가지 주요 이점이 있습니다.
- 하나는 다른 하나를 방해하지 않을 것이기 때문에 프로그램을 만드는 것이 더 쉽습니다. 예를 들어, 한 사용자 프로세스는 페이징으로 인해 다른 프로그램의 메모리를 덮어 쓰거나 다른 프로세스에 대해 하드웨어를 유효하지 않은 상태로 만드는 것에 대해 걱정할 필요가 없습니다.
- 더 안전합니다. 예를 들어 파일 권한과 메모리 분리는 해킹 앱이 은행 데이터를 읽지 못하게 할 수 있습니다. 이것은 물론 커널을 신뢰한다고 가정합니다.
어떻게 놀아?
링을 직접 조작하는 좋은 방법이어야하는 베어 메탈 셋업을 만들었습니다 : https://github.com/cirosantilli/x86-bare-metal-examples
불행히도 userland 예제를 만들려는 인내심은 없었지만 페이징 설정까지 진행 했으므로 userland가 가능해야합니다. 풀 요청을보고 싶습니다.
또는 Linux 커널 모듈은 링 0으로 실행되므로이를 사용하여 권한있는 작업을 시도 할 수 있습니다 (예 : 제어 레지스터 읽기 : 프로그램에서 제어 레지스터 cr0, cr2, cr3에 액세스하는 방법)? 세그먼테이션 결함 얻기
다음은 편리한 QEMU + Buildroot 설정 으로 호스트를 종료하지 않고 사용해 볼 수 있습니다.
커널 모듈의 단점은 다른 kthread가 실행 중이고 실험을 방해 할 수 있다는 것입니다. 그러나 이론적으로 커널 모듈로 모든 인터럽트 핸들러를 인수하고 시스템을 소유 할 수 있습니다. 실제로는 흥미로운 프로젝트입니다.
네거티브 링
음수 링은 실제로 인텔 설명서에서 참조되지 않지만 실제로 링 0보다 더 많은 기능을 가진 CPU 모드가 있으므로 “음의 링”이름에 적합합니다.
한 가지 예로 가상화에 사용되는 하이퍼 바이저 모드가 있습니다.
자세한 내용은 다음을 참조하십시오.
- /security/129098/what-is-protection-ring-1
- /security/216527/ring-3-exploits-and-existence-of-other-rings
팔
ARM에서는 링을 예외 수준이라고하지만 주요 아이디어는 동일하게 유지됩니다.
ARMv8에는 다음과 같이 일반적으로 사용되는 4 가지 예외 수준이 있습니다.
-
EL0 : 유저 랜드
-
EL1 : 커널 (ARM 용어에서 “감독자”).
Linux 시스템 호출을 수행하는 데 사용되는 명령 인 이전 통합 어셈블리
svc
로 알려진 명령 (SuperVisor Call) 과 함께 입력되었습니다 . Hello world ARMv8 예제 :swi
안녕하세요 .S
.text .global _start _start: /* write */ mov x0, 1 ldr x1, =msg ldr x2, =len mov x8, 64 svc 0 /* exit */ mov x0, 0 mov x8, 93 svc 0 msg: .ascii "hello syscall v8\n" len = . - msg
Ubuntu 16.04에서 QEMU를 사용하여 테스트하십시오.
sudo apt-get install qemu-user gcc-arm-linux-gnueabihf arm-linux-gnueabihf-as -o hello.o hello.S arm-linux-gnueabihf-ld -o hello hello.o qemu-arm hello
다음은 SVC 핸들러 를 등록하고 SVC 호출을 수행하는 구체적인 베어 메탈 예제입니다 .
-
hvc
지침 (HyperVisor Call) 과 함께 입력했습니다 .하이퍼 바이저는 OS에 대한 것이며 OS는 사용자 영역에 있습니다.
예를 들어 Xen을 사용하면 동일한 시스템에서 Linux 또는 Windows와 같은 여러 OS를 동시에 실행할 수 있으며 Linux가 사용자 프로그램에 대해하는 것처럼 보안 및 디버그 용이성을 위해 OS를 서로 분리합니다.
하이퍼 바이저는 오늘날 클라우드 인프라의 핵심 부분입니다. 단일 서버에서 여러 서버를 실행하여 하드웨어 사용량을 항상 100 %에 가깝게 유지하고 많은 비용을 절약 할 수 있습니다.
-
EL3 : 또 다른 수준. TODO 예.
smc
지침 과 함께 입력 (보안 모드 호출)
ARMv8 아키텍처 참조 모델 DDI 0487C.a는 – 장 D1 일 – AArch64 시스템 레벨 프로그래머 모델 – 그림 D1-1 아름답게이 보여
ARMv8.1 ARM V8.1 (Virtualization Host Extensions) 의 등장으로 ARM 상황이 약간 바뀌 었습니다 . 이 확장을 통해 커널은 EL2에서 효율적으로 실행될 수 있습니다.
VHE는 KVM과 같은 Linux 내 커널 가상화 솔루션이 Xen보다 우위를 점했기 때문에 만들어졌습니다 (예 : 위에서 언급 한 AWS의 KVM으로 이동 참조). 대부분의 클라이언트는 Linux VM 만 필요하고 상상할 수 있듯이 모두 단일 KVM은 Xen보다 간단하고 잠재적으로 더 효율적입니다. 따라서 이제는 호스트 Linux 커널이 하이퍼 바이저 역할을합니다.
가늠자의 이점으로 인해 ARM이 음수 수준을 필요로하지 않고 x86보다 권한 수준에 대해 더 나은 명명 규칙을 갖는 방법에 유의하십시오. 0은 낮고 3은 높습니다. 높은 레벨은 낮은 레벨보다 자주 생성되는 경향이 있습니다.
현재 EL은 다음 MRS
명령 으로 쿼리 할 수 있습니다 . 현재 실행 모드 / 예외 수준 등은 무엇입니까?
ARM은 칩 영역을 절약하는 기능이 필요하지 않은 구현을 허용하기 위해 모든 예외 수준을 제시 할 필요는 없습니다. ARMv8 “예외 수준”에서는 다음과 같이 말합니다.
구현에 모든 예외 레벨이 포함되지 않을 수 있습니다. 모든 구현에는 EL0 및 EL1이 포함되어야합니다. EL2 및 EL3은 선택 사항입니다.
예를 들어 QEMU의 기본값은 EL1이지만 EL2 및 EL3은 명령 줄 옵션으로 활성화 할 수 있습니다. qemu-system-aarch64는 a53 전원을 에뮬레이션 할 때 el1을 입력합니다.
코드 스 니펫은 Ubuntu 18.10에서 테스트되었습니다.
답변
커널 공간과 사용자 공간은 권한있는 운영 체제 기능과 제한된 사용자 응용 프로그램을 분리 한 것입니다. 사용자 응용 프로그램이 컴퓨터를 가로 채지 못하도록하려면 분리해야합니다. 이전 사용자 프로그램이 임의의 데이터를 하드 드라이브에 쓰거나 다른 사용자 프로그램의 메모리 공간에서 메모리를 읽을 수 있으면 좋지 않습니다.
사용자 공간 프로그램은 시스템 자원에 직접 액세스 할 수 없으므로 운영 체제 커널이 프로그램을 대신하여 액세스를 처리합니다. 사용자 공간 프로그램은 일반적으로 시스템 호출을 통해 운영 체제에 요청합니다.
커널 스레드, 프로세스, 스택은 같은 의미가 아닙니다. 그것들은 사용자 공간에서 커널 공간과 비슷한 구조입니다.
답변
각 프로세스에는 페이지 테이블을 통해 실제 메모리에 매핑되는 자체 4GB의 가상 메모리가 있습니다. 가상 메모리는 주로 프로세스 사용에 3GB, 커널 사용에 1GB의 두 부분으로 나뉩니다. 생성 한 대부분의 변수는 주소 공간의 첫 부분에 있습니다. 이 부분을 사용자 공간이라고합니다. 마지막 부분은 커널이있는 곳이며 모든 프로세스에 공통입니다. 이를 커널 공간이라고하며이 공간의 대부분은 부팅시 커널 이미지가로드되는 실제 메모리의 시작 위치에 매핑됩니다.
답변
주소 공간의 최대 크기는 CPU의 주소 레지스터 길이에 따라 다릅니다.
32 비트 주소 레지스터가있는 시스템에서 주소 공간의 최대 크기는 2 32 바이트 또는 4GiB입니다. 마찬가지로 64 비트 시스템에서는 2 64 바이트를 처리 할 수 있습니다.
이러한 주소 공간을 가상 메모리 또는 가상 주소 공간 이라고 합니다 . 실제로 실제 RAM 크기와 관련이 없습니다.
Linux 플랫폼에서 가상 주소 공간은 커널 공간과 사용자 공간으로 나뉩니다.
작업 크기 제한 또는 아키텍처라는 특정 상수 TASK_SIZE
는 분할이 발생하는 위치를 나타냅니다.
-
0에서
TASK_SIZE
-1 까지의 주소 범위 가 사용자 공간에 할당됩니다. -
TASK_SIZE
최대 2 32 -1 (또는 2 64 -1) 의 나머지는 커널 공간에 할당됩니다.
예를 들어 특정 32 비트 시스템에서 사용자 공간은 3GiB, 커널 공간은 1GiB를 차지할 수 있습니다.
유닉스 계열 운영 체제의 각 응용 프로그램 / 프로그램은 프로세스입니다. 각각에는 Process Identifier (또는 단순히 Process ID , 즉 PID) 라는 고유 식별자가 있습니다. Linux는 프로세스 생성을위한 두 가지 메커니즘을 제공합니다. 1. fork()
시스템 호출 또는 2. exec()
호출.
커널 스레드는 간단한 프로세스이며 실행중인 프로그램입니다. 단일 프로세스는 동일한 데이터와 리소스를 공유하지만 프로그램 코드를 통해 다른 경로를 취하는 여러 스레드로 구성 될 수 있습니다. Linux는 clone()
스레드를 생성하기 위한 시스템 호출을 제공 합니다.
커널 스레드의 사용 예는 다음과 같습니다. RAM의 데이터 동기화, 스케줄러가 CPU간에 프로세스를 분배하는 데 도움이됩니다.