본 글은 The Linux Kernel 을 정리한 것이며, 출처를 밝히지 않은 모든 이미지는 원글에 속한 것입니다.
중앙 처리 장치(Central Processing Unit, CPU)
- 프로세서(Processor) 또는 마이크로프로세서(Microprocessor)
- 기계어 코드를 실행하는 하드웨어, 어셈블리어 1줄은 실행되는 가장 작은 단위의 명령어
- 아래 그림은 Hello World 를 출력하는 바이너리 파일의 어셈블리 코드
- 0000000100003f60 <_main> 섹션의 첫번째 명령어 pushq %rbp 부터 실행 (기계어 코드 0x55)
- 사칙 연산과 논리 연산(>, <, =) 뿐만 아니라 "메모리 위치 X에 있는 내용을 레지스터 Y로 읽어들여라" 같은 단순한 명령어를 실행
- 기계어 코드는 16진수로 표현되며, 어셈블리어 문법은 CPU 아키텍처마다 다름 (프로그램은 16진수로 작성되어 있음)
레지스터(Register)
- 어셈블리어를 실행할 때, 데이터를 저장하고, 연산하기 위해 사용하는 CPU 내부에 있는 저장소 (위 그림의 R0 ~ Rn, PC)
- CPU는 바로 메모리에 값을 쓰거나, 메모리로부터 값을 가져올 수 없으며, 반드시 레지스터를 거쳐야 메모리에 접근 가능
- 레지스터의 크기와 개수 및 종류는 CPU 아키텍처마다 다름
- 일반 목적 레지스터와 특수 목적 레지스터 2가지 유형이 있음
- 특수 목적 레지스터는 반드시 다음과 같은 3개를 포함
- 프로그램 카운터(Program Counter, PC) CPU가 다음에 실행할 명령어의 주소, 명령어를 실행할 때마다 값이 증가
- 프로세서 상태(Processor Status, PS) 논리 연산처럼 명령어 실행 후 결과가 나오는 경우 그 값을 저장할 때 사용 또는 CPU의 현재 상태를 나타내는 정보도 포함(커널 모드 vs 유저 모드)
- 스택 포인터(Stack Pointer, SP) 스택에 데이터를 저장할 주소
- 스택: CPU가 프로그램을 실행할 때 데이터를 임시로 저장하기 위한 메모리(RAM)의 공간
- 스택은 LIFO(Last-In-First-Out) 구조로, 마지막에 삽입한 값을 먼저 가져올 수 있음
- 스택은 메모리 주소가 감소하는 방향으로 증가하며, 어셈블리어로 push 명령어를 실행하면 메모리 주소가 감소하면서 값이 삽입되고, pop 명령어를 실행하면 메모리 주소가 증가하면서 값을 가져옴
메모리(Memory)
- 메인 메모리(Main Memory) RAM이라는 CPU 외부에 있는 저장 공간
- 캐시 메모리(Cache Memory) CPU 내부에 있는 소량의 메모리로, 메인 메모리보다 접근 속도가 빠르고 비쌈
- L1 캐시 메모리 하나의 캐시에 명령어와 데이터를 같이 저장하거나, 명령어와 데이터를 별도로 저장
- L2 캐시 메모리 메인 메모리의 내용을 임시로 보관할 때 사용하며, L1 보다 용량이 큼
- L3 캐시 메모리 멀티코어 시스템에서 코어간 작업 속도를 향상시키기 위해 여러 코어끼리 공유하는 메모리
- CPU에서 L1, L2, L3 순서대로 멀리 있고 속도는 L1이 가장 빠르고 L3가 가장 느림
- 일치성: CPU는 메인 메모리에 접근하기 전에, 캐시에 필요한 데이터가 있는지 먼저 확인하며 데이터가 없을 때 메인 메모리에 접근, 캐시와 메인 메모리는 동일한 데이터에 대해 같은 값을 유지해야 함
- 캐시에서 바로 값을 가져다 쓰는 것보다, 값이 없어서 메모리에서 캐시로 값을 가져와서 쓰는 것이 더 느림
- 시간 지역성: 자주 참조하는 데이터를 보관, 읽고 쓸 때마다 데이터의 참조 카운트가 증가
- 공간 지역성: 자주 사용하는 데이터의 인접한 데이터들까지 보관 (그 주변도 자주 사용할 것이라는 가정)
- 캐시가 동작하는 아주 구체적인 원리
- 2차원 행렬 M[256][256] 을 연산할 때, r을 행 인덱스, c를 열 인덱스라고 하자. 같은 행에 있는 원소는 인접하기 때문에 메모리에서 캐싱할 때 같은 행에 있는 원소들을 캐시 메모리로 가져올 것이고, for(c = 0; ...; c++) for(r = 0 ...; r++) 순서로 중첩 반복문을 작성하는 것보다 for(r = 0; ...; r++) for(c = 0; ...; c++) 순서로 작성하는 것이 캐시 히트(cache hit)를 높게 함
- The impact of cache locality on performance in C through matrix multiplication
버스(Bus)
- 메인 보드에 있는 각 구성 요소들은 여러 개의 버스로 연결되어 있음
- 시스템 버스
- 데이터 버스(data bus) 양방향(CPU로 읽어들이거나 CPU에서 쓸 때)으로 전송되는 데이터를 가지고 있는 버스
- 주소 버스(address bus) 데이터를 전송할 메모리의 위치(=주소)를 가지고 있는 버스
- 제어 버스(control bus) 시스템 전체에 타이밍 신호와 제어 신호를 전달하는 선들을 가지며, ISA나 PCI 버스가 주변장치를 시스템에 연결하는 대중적인 방법으로 사용되는 버스 (모든 장치가 제어 버스에 데이터를 송신, 제어 버스로부터 데이터를 수신)
컨트롤러와 주변장치
- 주변장치 메인 보드에 있는 장치 또는 메인 보드에 꽂힌 카드에 있는 컨트롤러 칩에 의해 제어되는 장치
- 컨트롤러 하드웨어 장치를 제어하는 CPU와 비슷한 하나의 프로세서이지만, CPU는 시스템 전체를 제어한다는 점에서 차이가 있음
- 컨트롤러는 여러 종류의 버스(요즘은 ISA 버스, PCI 버스를 사용)를 통해 CPU 및 다른 컨트롤러들과 상호 연결되어 있음
- 모든 컨트롤러는 CPU가 제어할 수 있도록 제어 레지스터를 제공하며, CPU에서 실행되는 소프트웨어(=디바이스 드라이버)는 제어 레지스터를 읽고 쓸 수 있어야 함 (레지스터는 컨트롤러 종류에 따라 다름)
주소 공간
- CPU는 주변장치를 사용하기 위해 메인 메모리에 장치 관련 자료구조를 생성해야 되기 때문에, CPU와 메인 메모리를 연결하는 시스템 버스는 CPU와 다른 주변장치를 연결하는 버스와는 분리되어 있음
- 하드웨어 주변장치가 존재하고 있는 메모리 공간은 I/O 공간, 그 외 프로세스나 커널이 있는 메모리 공간은 시스템 메모리 공간
- CPU는 시스템 메모리 공간과 I/O 공간에 모두 직접적으로 접근 가능하나, 컨트롤러는 I/O 공간에만 접근 가능
- 컨트롤러가 CPU의 도움을 받아 시스템 메모리 공간에 간접적으로 접근할 수는 있음
- I/O 공간을 메인 메모리에서 분리 할 수도 있고, 메인 메모리 내부의 공간 일부를 할당할 수도 있음
- 일반적으로 CPU는 시스템 메모리 공간과 I/O 공간을 접근하는데 다른 명령어를 사용
- 예를 들어, "I/O 공간 0x3f0 주소에서 한 바이트를 읽어 레지스터 X에 저장하라"같은 명령이 있는 것인데, 이는 CPU가 I/O 공간에 있는 주변장치의 레지스터를 읽고 씀으로써, 하드웨어 주변장치를 제어하는 방법
- 컨트롤러가 메인 메모리에서 많은 양의 데이터를 읽어야 하거나, 메인 메모리로 많은 양의 데이터를 써야할 때, CPU의 도움 없이 직접 메모리 접근(Direct Memory Access, DMA)이라는 장치를 이용
- 단, DMA 컨트롤러를 사용할 때 CPU의 엄격한 제어와 감시가 이루어짐
타이머
- 모든 운영체제는 현재 시각을 알 필요가 있기 때문에, 요즘 PC들은 실시간 클럭(Real Time Clock, RTC)이라는 특수한 장치를 사용
- RTC는 자체 배터리를 가지고 있어 PC의 전원을 끄더라도 계속 동작하기 때문에 운영체제는 항상 정확한 날짜와 시간을 알 수 있음
'Operating System > Linux' 카테고리의 다른 글
리눅스 커널 - 프로세스간 통신(IPC) 메커니즘 (0) | 2021.06.03 |
---|---|
리눅스 커널 - 프로세스와 쓰레드 (0) | 2021.06.02 |
리눅스 커널 - 메모리 관리 2 (0) | 2021.06.01 |
리눅스 커널 - 메모리 관리 1 (0) | 2021.06.01 |
리눅스 커널 - 소프트웨어 (0) | 2021.05.31 |