>운영 및 유지보수 >리눅스 운영 및 유지 관리 >Linux 사용자 공간과 커널 공간에 대한 자세한 설명

Linux 사용자 공간과 커널 공간에 대한 자세한 설명

藏色散人
藏色散人앞으로
2020-12-08 17:01:104371검색

추천: "Linux 비디오 튜토리얼"

1. 소개

  • Linux 운영 체제와 드라이버는 커널 공간에서 실행되고, 애플리케이션은 사용자 공간에서 실행됩니다. 둘은 단순히 포인터를 사용하여 데이터를 전송할 수 없습니다. Linux에서 사용하는 가상 메모리 메커니즘으로 인해 사용자 공간 데이터가 교체될 수 있습니다. 커널 공간이 사용자 공간 포인터를 사용하는 경우 해당 데이터가 메모리에 없을 수 있습니다. 사용자 공간의 메모리 매핑은 세그먼트 페이지 유형을 채택하지만 커널 공간에는 자체 규칙이 있습니다. 이 기사에서는 커널 공간의 주소 매핑을 탐색하는 것을 목표로 합니다.
  • os는 각 프로세스에 독립적이고 연속적인 가상 주소 메모리 공간을 할당하며, 크기는 일반적으로 4G(32비트 운영 체제, 즉 2의 32승)이며, 여기에는 주소 값이 높은 메모리 공간이 할당됩니다. os가 점유하면 linux os는 1G를 점유하고 window os는 2G를 점유합니다. 나머지 메모리 주소 공간은 프로세스에 할당됩니다.
  • 보통 32비트 Linux 커널 가상 주소 공간은 사용자 공간인 0~3G와 커널 공간인 3~4G로 구분됩니다(커널이 사용할 수 있는 선형 주소는 1G에 불과합니다). 이는 32비트 커널 주소 공간 분할이고 64비트 커널 주소 공간 분할은 다릅니다.

  • 프로세스 주소 지정 공간 0~4G
  • 프로세스는 사용자 모드에서 0~3G에만 접근할 수 있고, 커널 모드에 들어갈 때는 3G~4G에만 접근할 수 있습니다.
  • 프로세스는 다음을 통해 커널 모드에 들어갑니다. 시스템 호출
  • 각 프로세스의 가상 공간 중 3G~4G 부분은 동일합니다.
  • 사용자 모드에서 커널 상태로 진입하는 프로세스는 CR3에는 변경이 발생하지 않지만 스택에는 변경이 발생합니다

2. Linux 커널 고급 메모리

1. Origin

커널 모듈 코드 또는 스레드가 메모리에 액세스할 때 코드의 메모리 주소는 모두 논리 주소이며 실제 물리적 메모리 주소에 해당하는 일대일 매핑입니다. 예를 들어 논리 주소 0xc0000003에 해당하는 물리 주소는 0×3, 0xc0000004에 해당하는 물리 주소는 0×4,..., 논리 주소와 물리 주소의 관계는 물리적 주소 = 논리 주소 – 0xC0000000: 이는 커널 주소 공간의 주소 변환 관계입니다. 커널의 가상 주소는 "상위"에 있지만 이에 매핑된 물리적 메모리 주소는 하위에 있습니다. .

논리 주소물리적 메모리 주소0xc00000000xc00000010xc0000002 0xc0000003…

위의 단순 주소 매핑 관계에 따라 커널 논리 주소 공간 액세스는 0xc0000000 ~ 0xffffffff이고 해당 물리 메모리 범위는 0×0 ~ 0×40000000입니다. 즉, 1G 물리 메모리만 액세스할 수 있습니다. 8G의 물리적 메모리가 머신에 설치된 경우 커널은 첫 번째 1G의 물리적 메모리에만 액세스할 수 있으며 커널의 주소 공간이 모두 물리적 메모리 주소 범위 0×에 매핑되었기 때문에 후속 7G의 물리적 메모리에는 액세스할 수 없습니다. 0 ~ 0×40000000. 8G 물리 메모리가 설치되어 있어도 커널은 물리 주소 0×40000001의 메모리에 어떻게 접근하나요? 코드에는 메모리 논리 주소가 있어야 합니다. 0xc0000000 ~ 0xffffffff의 주소 공간이 모두 사용되었으므로 물리 주소 0×40000000 이후의 메모리에는 액세스할 수 없습니다.

분명히 커널 주소 공간 0xc0000000 ~ 0xfffffff는 간단한 주소 매핑에 사용할 수 없습니다. 따라서 x86 아키텍처는 커널 주소 공간을 ZONE_DMA, ZONE_NORMAL 및 ZONE_HIGHMEM의 세 부분으로 나눕니다. ZONE_HIGHMEM은 하이엔드 메모리 개념의 시초가 되는 하이엔드 메모리입니다.


x86 구조에서 세 가지 유형의 영역(3G에서 계산)은 다음과 같습니다.

ZONE_DMA     16MB 메모리 시작 부분

ZONE_NORMAL   16MB~896MB

Z ONE_HIGHMEM 896MB ~ 끝 (1G)

2. 이해

앞서 하이엔드 메모리의 유래에 대해 설명했습니다. Linux는 커널 주소 공간을 ZONE_DMA, ZONE_NORMAL 및 ZONE_HIGHMEM의 세 부분으로 나눕니다. 고급 메모리 HIGH_MEM 주소 공간의 범위는 0xF8000000에서 0xFFFFFFFF(896MB~1024MB)입니다. 그렇다면 커널은 어떻게 128MB 고급 메모리 주소 공간을 사용하여 모든 물리적 메모리에 액세스합니까? 커널이 896MB보다 큰 물리 주소를 가진 메모리에 접근하려고 할 때, 0xF8000000~0xFFFFFFFF 주소 공간 범위에서 해당 크기의 여유 논리 주소 공간을 찾아서 잠시 빌려옵니다. 이 논리 주소 공간을 빌려서 액세스하려는 물리적 메모리에 매핑합니다(즉, 커널 PTE 페이지 테이블을 채우고 잠시 동안 사용하고 사용 후 반환합니다. 이러한 방식으로 다른 사람들도 이 주소 공간을 빌려 다른 물리적 메모리에 액세스할 수 있으며, 제한된 주소 공간을 사용하여 모든 물리적 메모리에 액세스할 수 있습니다. 아래 그림과 같습니다.

예를 들어 커널은 2G부터 1MB의 물리적 메모리에 액세스하려고 합니다. 즉, 물리적 주소 범위는 0×80000000 ~ 0x800FFFFF입니다. 접근하기 전에 먼저 1MB의 여유 주소 공간을 찾는다. 발견된 여유 주소 공간은 0xF8700000 ~ 0xF87FFFFF라고 가정한다. 이 1MB 논리 주소 공간을 사용하여 물리적 주소 공간 0x80000000 ~ 0x800FFFFF에 매핑한다. 매핑 관계는 다음과 같습니다.

0×0
0 ×1
0×2
0×3
0xffffffff
0×40000000 ??
논리 주소 0×800000000×800000010×80000002
물리적 메모리 주소 0xF8700000
0x F87000 01
0xF8700002

커널은 0×80000000 ~ 0x800FFFFF 물리적 메모리에 액세스한 후 0xF8700000 ~ 0xF87FFFFF 커널 선형 공간을 해제합니다. 이런 방식으로 다른 프로세스나 코드도 0xF8700000~0xF87FFFFF 주소를 이용해 다른 물리 메모리에 접근할 수 있다.

위의 설명을 통해 하이엔드 메모리의 가장 기본적인 아이디어를 알 수 있습니다. 즉, 주소 공간의 섹션을 빌려 임시 주소 매핑을 설정하고, 이 주소 공간에 도달하면 해제합니다. 재활용이 가능하고 모든 물리적 메모리에 액세스할 수 있습니다.

이것을 보고 일부 사람들은 묻지 않을 수 없습니다. 커널 프로세스나 모듈이 특정 논리 주소 공간을 계속 점유하고 이를 해제하지 않으면 어떻게 되나요? 이러한 상황이 실제로 발생하면 커널의 고급 메모리 주소 공간이 점점 더 좁아지게 되며, 점유되어 해제되지 않으면 물리적 메모리에 매핑되지 않더라도 액세스할 수 없게 됩니다.

3. 분할

커널은 고급 메모리를 VMALLOC_START~VMALLOC_END, KMAP_BASE~FIXADDR_START 및 FIXADDR_START~4G의 세 부분으로 나눕니다.


고성능 메모리의 경우 alloc_page()나 다른 함수를 통해 해당 페이지를 얻을 수 있지만, 실제 물리적 메모리에 접근하려면 해당 페이지를 선형 주소로 변환해야 합니다(왜? MMU가 물리적 메모리에 액세스하는 방법을 생각해 보세요. 즉, 고급 메모리에 해당하는 페이지의 선형 공간을 찾아야 합니다. 이 프로세스를 고급 메모리 매핑이라고 합니다.

고급 메모리의 세 부분에 해당합니다. 고급 메모리 매핑에는 세 가지 방법이 있습니다.
"커널 동적 매핑 공간"(비연속 메모리 할당)에 매핑됩니다.
이 방법은 vmalloc을 통해 매우 간단합니다. (), "커널 동적 매핑"에서 메모리 "공간"을 적용하면 고급 메모리에서 페이지를 얻을 수 있으므로(vmalloc 구현 참조) 고급 메모리가 " 커널 동적 매핑 공간".

영구 커널 매핑
alloc_page()를 통해 하이엔드 메모리에 해당하는 페이지를 얻은 경우 이에 대한 선형 공간은 어떻게 찾나요?
커널은 고급 메모리 매핑을 위해 PKMAP_BASE에서 FIXADDR_START까지 이를 위한 선형 공간을 특별히 따로 설정합니다. 2.6 커널에서 이 주소 범위는 4G-8M과 4G-4M 사이입니다. 이 공간을 "커널 영구 매핑 공간" 또는 "영구 커널 매핑 공간"이라고 합니다. 이 공간은 다른 공간과 동일한 페이지 디렉토리 테이블을 사용합니다. 커널의 경우, 일반 프로세스의 경우 CR3 레지스터가 가리킵니다. 일반적으로 이 공간의 크기는 4M이므로 커널은 pkmap_page_table을 통해 이 페이지 테이블을 검색합니다. kmap()을 통해 이 공간에 페이지를 매핑할 수 있습니다. 이 공간의 크기는 4M이므로 동시에 최대 1024페이지를 매핑할 수 있습니다. 따라서 사용하지 않는 페이지는 적시에 이 공간에서 해제되어야 합니다(즉, 매핑 관계가 해제됨). kunmap()을 통해 페이지에 해당하는 선형 주소가 이 공간에서 해제될 수 있습니다.

임시 커널 매핑
커널은 특별한 요구를 위해 FIXADDR_START에서 FIXADDR_TOP 사이에 일부 선형 공간을 예약합니다. 이 공간을 "고정 매핑 공간"이라고 하며, 이 공간의 일부는 고급 메모리의 임시 매핑에 사용됩니다.

이 공간은 다음과 같은 특징을 가지고 있습니다.
(1) 각 CPU가 공간을 점유합니다.
(2) 각 CPU가 점유하는 공간은 여러 개의 작은 공간으로 나누어지며, 각 작은 공간은 1페이지이며, 각 작은 공간은 목적에 따라 사용됩니다. , 이러한 목적은 kmap_types.h의 km_type에 정의되어 있습니다.

임시 매핑을 수행하려면 매핑 목적을 지정해야 합니다. 매핑 목적에 따라 해당 작은 공간을 찾은 다음 이 공간의 주소를 매핑 주소로 사용하면 됩니다. 이는 임시 매핑으로 인해 이전 매핑이 덮어쓰여진다는 의미입니다. 임시 매핑은 kmap_atomic()을 통해 이루어집니다.

3. 기타

1. 사용자 공간(프로세스)에는 하이엔드 메모리 개념이 있나요?

사용자 프로세스에는 고급 메모리 개념이 없습니다. 높은 메모리는 커널 공간에만 존재합니다. 사용자 프로세스는 최대 3G의 물리적 메모리에만 액세스할 수 있는 반면, 커널 프로세스는 모든 물리적 메모리에 액세스할 수 있습니다.

2. 64비트 커널에 고성능 메모리가 있나요?

현재 현실에서는 64비트 Linux 커널에는 512GB 이상의 메모리를 지원할 수 있기 때문에 고급형 메모리가 존재하지 않습니다. 머신에 설치된 물리적 메모리가 커널 주소 공간을 초과하면 고급 메모리가 됩니다.

3. 사용자가 액세스할 수 있는 실제 메모리는 얼마나 되나요? 커널 코드가 액세스할 수 있는 실제 메모리는 얼마나 됩니까?

32비트 시스템 사용자 프로세스는 최대 3GB에 접근할 수 있으며, 커널 코드는 모든 물리적 메모리에 접근할 수 있습니다.

64비트 시스템 사용자 프로세스는 최대 512GB 이상에 액세스할 수 있으며, 커널 코드는 모든 물리적 메모리에 액세스할 수 있습니다.

4. 하이엔드 메모리와 물리주소, 논리주소, 선형주소는 어떤 관계인가요?

고급 메모리는 논리 주소에만 관련되어 있으며 논리 주소 및 물리 주소와는 직접적인 관계가 없습니다.

위 내용은 Linux 사용자 공간과 커널 공간에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 csdn.net에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제