rax
레지스터레지스터 : CPU 내부에 있는 가장 빠르고 작은 고속 저장 공간.
CPU는 메인 메모리(RAM)에 있는 데이터를 직접 처리하지 않고 필요한 데이터를 메인 메모리에서 레지스터로 가져와 연산을 수행한 뒤, 그 결과를 다시 메인 메모리에 저장.
PintOS와의 연관성
시스템 콜을 구현할 때, 유저 프로그램은 커널에게 "어떤 서비스를 원하는지"와 "그 서비스에 필요한 데이터가 무엇인지"를 알려줘야 함. 이 정보를 전달하는 가장 효율적인 방법이 레지스터를 사용하는 것.
x86-64 아키텍처의 ABI 규약에 따르면
- rax
레지스터 : 시스템 콜 번호(System Call Number)를 저장하는 용도.
예를 들어, exit
시스템 콜을 1번으로 정했다면, 유저 프로그램은 rax
레지스터에 1을 넣고 시스템 콜을 호출해야 함.
- rdi
, rsi
, rdx
, r10
, r8
, r9
레지스터 : 시스템 콜에 필요한 인자들을 순서대로 저장하는데 사용.
예를 들어, write(fd, buffer, size)
시스템 콜을 호출한다면, fd
는 rdi
에, buffer
의 주소는 rsi
에, size
는 rdx
에 저장됨.
메인 메모리 : 프로그램의 코드와 데이터가 실행 중에 저장되는 넓은 작업 공간
PintOS에서는 이 메모리 공간을 커널만 접근할 수 있는 커널 공간과 유저 프로그램이 사용하는 유저 공간으로 엄격하게 분리
유저 스택 : 유저 공간 안에 있는 특별한 메모리 영역. 함수가 호출될 때마다 지역 변수, 복귀 주소, 그리고 함수에 전달되는 인자들이 이 스택에 저장.
PintOS와의 연관성
"echo hello"
를 실행하면, 커널은 echo
프로그램을 메모리에 올린 후, 이 프로그램의 유저 스택에 문자열 "echo"
와 "hello"
를 직접 써넣어줘야 함. 이 작업을 통해 echo
프로그램의 main
함수는 자신의 인자들을 스택에서 찾아 사용할 수 있게 됨.0x12345678
이라는 주소(포인터)를 커널에 전달했을 때, 커널은 이 주소가 유효한 유저 공간에 속하는지, 그리고 실제로 할당된 페이지인지 반드시 검사해야 함. 이 검사 없이 주소에 접근했다가는 커널이 보호해야 할 다른 메모리 영역을 침범해 시스템 전체가 멈출 수 있음.가상 메모리 : OS는 각 프로세스에게 실제 물리 메모리(RAM)와는 독립적인 자신만의 가상 주소 공간(Virtual Address Space)을 제공.
이를 통해, 프로세스는 메모리 전체를 독차지하는 것처럼 느낌. 모든 프로세스는 0번지부터 시작하는 자신만의 주소 공간을 가지며, 이 가상 주소는 CPU의 메모리 관리 장치(MMU)를 통해 실제 물리 주소로 변환.
가상 메모리 사용 목적
1. 프로세스 격리 : 한 프로세스가 다른 프로세스의 메모리를 절대 침범할 수 없어 시스템이 매우 안정적으로 보호됨.
2. 효율적인 메모리 관리 : 프로그램의 일부만 실제 메모리에 올려놓고 실행하는 것(요구 페이징)이 가능해져, 실제 RAM보다 더 큰 프로그램도 실행할 수 있음.
PintOS와의 연관성
exec
시스템 콜 구현 시, 이 가상 주소 공간에 프로그램의 코드를 적재하는 과정을 흉내 내게 됨. Virtual Memory에서 이 개념을 본격적으로 다루게 됨.
캐시 : CPU와 메인 메모리(RAM) 사이에 위치하는, 레지스터보다는 느리지만 메인 메모리보다는 훨씬 빠른 소규모 메모리. CPU는 자주 사용될 것으로 예상되는 데이터를 메인 메모리에서 미리 캐시에 복사. 그 후 CPU가 데이터를 필요로 할 때, 느린 메인 메모리까지 갈 필요 없이 빠른 캐시에서 데이터를 바로 가져와 시스템 전체의 성능을 크게 향상시킴.
PintOS와의 연관성
캐시를 직접 제어하거나 관리할 필요가 없음. 대부분 하드웨어가 자동으로 처리하기 때문.
다만, 내가 작성한 코드가 하드웨어에서 어떻게 더 빠르게 동작할 수 있는지 원리를 이해하는 것은 중요.
예를 들어, 반복문에서 동일한 메모리 영역에 계속 접근하는 코드는 캐시의 효율을 극대화(캐시 히트율 증가)해 더 좋은 성능을 낼 수 있음.
File System에서는 버퍼 캐시(Buffer Cache)라는 소프트웨어적 캐시를 직접 구현하는데, 이 하드웨어 캐시의 원리가 큰 도움이 될 것.
동시성 : 여러 작업이 동시에 실행되는 것처럼 보이게 하는 것. 실제로는 하나의 CPU 코어가 여러 작업을 매우 빠르게 번갈아 가며 실행(Context Switching)하는 것.
경쟁 상태 : 여러 프로세스나 스레드가 공유된 자원(예 : 전역 변수, 파일)에 동시에 접근하려 할 때 실행 순서에 따라 결과가 달라지는 예측 불가능한 오류가 나타나는데 이것이 발생할 수 있는 상태를 경쟁 상태라고 함.
OS 커널은 수많은 인터럽트와 프로세스들이 동시에 공유 데이터에 접근하는 환경이므로, 경쟁 상태를 방지하는 것이 안정성의 핵심. intr_disable()
같은 동기화 기법(예 : 뮤텍스, 세마포어)을 사용해 한 번에 하나의 실행 흐름만 공유 데이터에 접근하도록 보장해야 함.