Skip to content

Latest commit

 

History

History
950 lines (774 loc) · 64.9 KB

06-OS.md

File metadata and controls

950 lines (774 loc) · 64.9 KB

운영체제, 커널, 시스템 콜, 인터럽트

운영체제란?
  • 사용자에게 편리한 인터페이스 환경을 제공하고 컴퓨터 시스템의 자원을 효율적으로 관리하는 일종의 소프트웨어입니다.
  • 예를 들어, 관리자 역할을 하는 운영체제의 커널이 프로그램을 메모리에 올려 프로세스로 만들면 일꾼인 CPU가 이를 처리합니다.

운영체제가 왜 필요할까요?
- 컴퓨터 자원을 보호하기 위해 필요합니다.
  - 운영체제를 통해 자원을 관리하고 접근합니다. 즉, 사용자가 자원에 직접적으로 접근하는 것을 막음으로써 보호합니다.
- 기능 추가 및 성능 향상을 위해 필요합니다.
  - 운영체제가 있으면 다양한 응용 프로그램을 사용할 수 있습니다. 예를 들어, 운영체제로 성능 향상을 위해 새로운 기능을 쉽게 추가할 수 있습니다.
- 편리한 인터페이스 환경을 제공받기 위해 필요합니다.
- 사용 규칙의 역할을 수행하기 위해 필요합니다.
  - 컴퓨터가 발전하면서 여러 작업을 동시에 할 수 있는 컴퓨팅 환경이 조성되어 사용 규칙이 필요해졌습니다.
운영체제의 역할이 무엇인가요?
- 자원 관리 : 효율성
  - 여러 응용 프로그램이 자원을 요청하면 적절한 순서로 배분하고 회수하여 자원을 효율적으로 관리합니다.
  - 예시 : 리소스 관리, I/O 시스템 관리, CPU 관리(스레드에 CPU를 시분할로 할당), 메모리 관리(모든 프로세스에 공평하게 메모리를 할당)
- 자원 보호 : 안정성
  - 사용자 및 응용 프로그램이 CPU, 메모리 등에 대해 직접 접근하는 것을 막습니다.
- HW 인터페이스 제공 : 확장성
  - 마우스, 키보드 등을 복잡한 과정없이 사용할 수 있도록 합니다.
- SW 인터페이스 제공 : 편리성
  - OS를 편리하게 사용하기 위해 제공됩니다.
  - Ex) Window GUI 등
운영체제 종류는 무엇이 있을까요?
- 운영체제는 앞단에 어떤 인터페이스를 두냐에 따라 GUI, CUI로 나뉠 수 있습니다.

- GUI (Graphical User Interface)
  - 그래픽을 사용하여 컴퓨터와 상호 작용하는 인터페이스입니다.
  - 즉, 사용자가 전자 장치와 상호 작용할 수 있도록 하는 사용자 인터페이스의 한 형태입니다.
  - 단순 명령어 창이 아닌 아이콘을 마우스로 클릭하는 등의 단순한 동작으로 컴퓨터와 상호 작용할 수 있도록 해줍니다.
  - Ex) windowOS, macOS 등의 현대의 OS
- CUI (Character Use Interface)
  - 사용자가 키보드만을 사용하여 문자를 기반으로 컴퓨터와 상호 작용하는 인터페이스입니다.
  - 즉, 그래픽이 아닌 명령어로 처리하는 인터페이스입니다.
  - Ex) MS-DOS (1994년 단종), chatGPT도 CUI라 할 수 있습니다.

커널이란 무엇인가요?
  • 운영체제의 핵심 부분이자 시스템 콜 인터페이스를 제공합니다.
  • 예를 들어, 보안, 메모리, 프로세스, 파일 시스템, I/O 디바이스, I/O 요청 관리 등 운영체제의 중추적인 역할을 합니다.

커널의 역할은 무엇이 있을까요?
- OS의 역할은 OS의 커널이 담당합니다. 즉, OS 역할이 커널 역할이라 할 수 있습니다.
  - CPU 스케줄링 및 프로세스 관리 : CPU를 어떤 프로세스 할당할 지, 혹은 프로세스 생성/삭제/자원 할당/반환을 관리합니다.
  - 메모리 관리 : 한정된 메모리를 어떤 프로세스에 얼만큼 할당할 지 관리합니다.
  - 디스크 파일 관리 : 디스크 파일을 어떤 방법으로 보관할 지 관리합니다.
  - I/O 디바이스 관리 : 마우스, 키보드 등과 같은 I/O 디바이스들과 컴퓨터 간에 데이터를 주고 받는 것을 관리합니다.
운영체제와 커널의 차이점은 무엇인가요?
- 운영체제는 시스템 전체를 관리하고 사용자와 응용 프로그램에 다양한 서비스를 제공합니다.
- 커널은 운영체제의 핵심 부분으로 하드웨어와 직접적으로 상호 작용하여 시스템 기능을 제공하고 관리합니다.
- 즉, 운영체제 전체가 컴퓨터 부팅 시 반드시 실행되어야 하는 것은 아니지만, 커널은 반드시 실행되어야합니다.
커널 함수란?
- 커널 내부에 있는 여러 함수들을 뜻하는 것으로 네이티브 함수를 말합니다.
- 이 커널 함수들은 System Call(호출)을 통해 사용자 프로그램이 커널 함수를 호출할 수 있습니다. 
- 예를 들어, 프로세스를 종료하는 kill() 함수를 호출 시, 시스템 콜을 거쳐 커널 함수가 호출되고 프로세스가 종료됩니다.
- 이처럼, 커널 함수는 운영 체제의 안정성과 기능에 큰 영향을 미칩니다.
커널 유형은 무엇이 있을까요?
- 단일형 구조 커널(모놀리식)
  - 초창기 OS 구조로 기능들이 단일의 모듈로 구성되어 있습니다.
  - 즉, 모든 시스템 서비스를 하나의 큰 프로세스 내에서 실행합니다.
  - Ex) MS-DOS, VMS, 초기 UNIX
  - 장점
    - 모듈 간의 통신 비용이 줄어 효율적인 운영이 가능합니다.
  - 단점
    - 버그나 오류를 처리하기 어렵습니다.
    - 기능 간 상호 의존성이 높아 작은 결함이 시스템 전체로 확산될 수 있습니다.
    - 수정이 어려워 이식성이 낮습니다.
    - 현대의 OS는 크고 복잡해 단일형으로 구현하기 어렵습니다.
- 계층형 구조 커널
  - 단일형 구조 커널의 발전된 형태로 비슷한 기능의 모듈을 하나의 계층으로 묶어 계층 간의 통신을 통해 OS를 구현한 커널입니다.
  - 장점
    - 버그나 오류가 생길 경우 해당 계층만 수정하면 되기 때문에, 디버깅이 쉽습니다.
    - Window를 비롯한 현대 OS는 이 구조로 구현되어 있습니다.
- 마이크로 구조 커널
  - 계층형 구조의 접근 방식과 반대로 개발된 커널로 가장 기본적인 기능만 제공합니다.
  - 즉, 최소한의 기능만을 제공하며 대부분 서비스가 사용자 영역에 구현되어 있으며, 
    각 모듈 간의 정보 교환은 프로세스 간 통신을 통해 이루어집니다.
  - 장점
    - 각 모듈이 독립적으로 작동하기 때문에, 하나의 모듈에 문제가 있어도 전체 OS가 멈추지 않습니다.
    - 커널이 가벼워 CPU 용량이 작은 시스템에도 적용이 가능합니다.

시스템 호출(System Call)이 무엇인지 설명해 주세요.
  • 시스템 콜은 OS가 커널에 접근하기 위한 인터페이스로 소프트웨어 인터럽트인 Trap의 한 종류입니다.
  • 예를 들어, 사용자 프로그램이 OS의 서비스를 받기 위해 커널 함수를 호출할 때, 시스템 콜을 거쳐 호출하도록 설계되어 있습니다.
    • 시스템 콜은 커널 영역의 기능을 사용자 모드가 사용 가능하게 해줍니다.
    • 프로세스가 하드웨어에 접근해서 필요한 기능을 할 수 있게 해줍니다.
    • Ex) 프로세스 관리(생성/삭제 등), 파일 관리, 디바이스 관리, 시간/날짜 관련 시스템, 프로세스 간 통신 등을 위해 시스템 콜을 거쳐 커널 함수 호출합니다.
  • 즉, OS는 다양한 서비스들을 수행하기 위해 하드웨어를 직접 관리하고 응용 프로그램은 OS가 제공하는 인터페이스인 시스템 콜을 통해서만 자원을 사용할 수 있습니다.

우리가 사용하는 시스템 콜의 예시를 들어주세요.
- 'open', 'close' : 파일을 열거나 닫는 시스템 콜입니다.
- 'fork', 'exit' : 프로세스를 생성하거나 종료하는 시스템 콜입니다.
- 'malloc', 'free' : 메모리를 할당하거나 해제하는 시스템 콜입니다.
시스템 콜의 장점은 ?
- 유저 프로그램이 복잡한 파일 시스템, 프로세스 관리 등의 내부 동작을 몰라도 됩니다.
  - 시스템 콜은 하나의 추상화 계층이기 때문에, 네트워크 통신이나, DB와 같은 낮은 단계의 영역 처리에 대한 부분을 많이 신경쓰지 않고 프로그램을 구현할 수 있습니다.
  - 즉, 유저 프로그램은 시스템 콜을 기반으로 커널과 분리 됩니다.
- 운영체제의 관리 하에 프로그램이 운영되므로 시스템의 안정성과 보안이 강화됩니다.
  - 예를 들어, 공격자가 만든 카메라 앱 프로그램이 아무런 제약 없이 접근 가능할 때, 카메라에 관련한 메모리 등이 오염되어 의도와는 상관없이 사생활이 노출될 수 있습니다.
  - 반대로, 시스템 콜은 유저 모드에서 시스템 콜로만 커널 모드에 진입할 수 있는 단 하나의 통로 역할을 하기 때문에, 컴퓨터 자원에 대한 직접적인 접근을 차단하여 보호할 수 있습니다.
시스템 콜이, 운영체제에서 어떤 과정으로 실행되는지 설명해 주세요.
1. 사용자 프로세스가 시스템 콜을 호출하면, trap이 걸리면서 mode bit 값이 1에서 0으로 바뀝니다. 즉, 유저모드에서 커널모드가 됩니다.
2. 이때, 커널은 내부적으로 시스템 콜을 구분하기 위해 기능별로 고유 번호를 할당하고 해당 번호에 제어 루틴의 정의하고 있기 때문에,
   커널은 요청받은 시스템 콜에 대응하는 고유 번호를 확인하고 그에 맞는 서비스 루틴을 호출합니다.
3. 작업 완료 후 다시 사용자 모드로 전환됩니다. 즉, mode bit도 0에서 1로 바뀝니다.
운영체제의 Dual Mode에 대해 설명해 주세요.
- 운영체제를 보호하기 위한 기법입니다. 예를 들어, 사용자에게 시스템 자원에 대한 제한을 걸지 않을 경우 사용자가 중요한 HW 자원을 망가뜨리 위험이 생기는데, 이를 보호하기 위한 기법입니다.
- 이는 `mode bit`를 참고해서 유저 모드와 커널 모드로 구분합니다. 이때, mode bit가 1이면 유저 모드이고 0이면 커널 모드입니다.
  - 유저 모드(mode bit 1) : 유저가 접근할 수 있는 영역을 제한적으로 둬서 컴퓨터 자원에 함수로 침범하지 못하는 모드입니다.
  - 커널 모드(mode bit 0) : 모든 컴퓨터 자원에 접근할 수 있는 모드입니다.  
시스템 콜 혹은 인터럽트가 발생했을 때, Dual Mode 흐름을 말해보세요.
1. 유저 모드에서 프로세스가 실행됩니다.
2. 실행 중 프로세스가 시스템 콜을 호출합니다.
3. 커널 모드로 전환됩니다.
4. 작업을 수행합니다.
5. 작업 완료 후 다시 유저 모드로 전환됩니다.
왜 유저모드와 커널모드를 구분해는 이유가 무엇일까요?
- 시스템을 보호하기 위해 구분합니다. 즉, 의도치 않거나 악의적으로 호출을 막아 시스템 내부 데이터를 보호하기 위해 구분합니다.
서로 다른 시스템 콜을 어떻게 구분할 수 있을까요?
- 커널은 내부적으로 각각의 시스템 콜을 구분하기 위해 고유한 이름, 매개변수, 시스템 콜 번호, 시스템 콜 번호에 해당하는 서비스 루틴 등을 가집니다.
  - 시스템 콜 이름(고유) : open, read, write와 같이 고유한 이름
  - 매개변수 : 매개변수의 종류와 값에 따라 시스템 콜이 어떤 동작을 수행하는 지 구분 가능합니다. (Ex) open: 파일 경로와 옵션을 매개변수로 전달, fork: 새로운 프로세스를 생성하는데 필요한 정보를 매개변수로 전달
우리가 사용하는 Java에서 시스템 콜을 어떻게 사용하는지 자유롭게 설명해주세요. (답변 부족)
- Java는 시스템 콜을 사용하기 위해 JNI를 통하여 네이티브 메서드를 활용하는 것으로 알고 있습니다.

인터럽트가 무엇인지 설명해 주세요.
  • 즉각적인 주의가 필요한 이벤트를 나타내는 외부 장치 혹은 SW 내부에서 CPU로 전송하는 신호를 말합니다. 신호를 받은 CPU에서 실행 중인 프로세스를 중단하고 임시로 미리 결정된 위치로 제어권을 전달합니다. 즉, 이벤트가 발생했을 때 CPU가 이에 응답할 수 있도록 합니다. 이는 폴링으로 주변 장치를 주기적으로 확인할 필요가 없어져서 프로세서의 효율성도 향상시킵니다.
  • 쉽게 말해, 인터럽트는 프로그램 실행 도중에 예기치 않은 상황이나 급한 작업이 발생할 경우, 현재 실행 중인 작업을 일시 중단 후, 발생된 상황을 우선처리한 후 실행 중이던 작업으로 복귀해 계속 처리하는 것을 말합니다. 즉, 현재 실행 중인 작업을 즉시 중단하고 발생한 상황에 대한 우선처리가 필요함을 CPU에 알리는 것입니다.

인터럽트가 왜 필요할까요?
- 대부분의 컴퓨터는 한 개의 CPU를 사용하므로 한 순간에는 하나의 일 밖에 처리할 수 없습니다.
- 때문에, 어떤 일을 처리하는 도중 우선 순위가 급한 일을 처리할 필요가 있을 때, 대처하기 위해 필요합니다.
트랩(Trap)이란?
- 트랩은 SW 인터럽트(=내부 인터럽트, 동기적 인터럽트)를 말합니다.    
- 이때 SW 인터럽트는 비자발적과 자발적인 System Call로 나뉩니다.
  - Exception(비자발적) : 오버플로, 언더플로, I/O 장치에 의한 인터럽트, 0으로 나눗셈한 경우 등
  - System Call(자발적) : 프로그램이 커널 함수를 호출하는 경우              
인터럽트 핸들러 함수(ISR; Interrupt Service Routine)란?
- 인터럽트 발생 시, 이를 핸들링하기 위함 함수를 말합니다.
- 이는 리눅스에서 `request_irq()`를 통해 인터럽트 핸들러 함수로 등록할 수 있습니다.
인터럽트는 어떻게 처리하나요?
1. 프로세스 실행 : CPU가 메모리에 있는 명령어를 순차적으로 실행하다가, 
2. 인터럽트 요청 : 중간에 HW 혹은 SW 이벤트에 의해 인터럽트 요청 시, 
3. 프로세스 중단 : CPU가 현재 실행 중인 프로세스를 중단하고 
4. 상태 보존 : PCB에 해당 작업 상태를 저장합니다.
5. 서비스 루틴 : Interrupt Vector에서 ISR(Intterrupt Handler)를 찾습니다.
6. 프로세스 인터럽트 : 찾은 ISR을 수행해 특정 명령어를 실행합니다.
7. 상태 복원 : 실행 완료 후 상태 복구 명령어가 실행되어 저장해둔 PCB 등을 복원하고 
8. 실행 재개 : CPU는 다시 메모리에 있는 명령어를 순차적으로 실행합니다. 이때, 이전에 실행 중이던 프로그램이 실행될 수도 있지만, Ready Queue의 가장 앞에 있던 프로그램이 다시 올라갈 수도 있습니다.
  
- PCB(Process Control Block) : 수행 중이던 PC, 메모리 주소, 레지스터, HW 상태 등이 저장됩니다.
- PC(Program Counter) : 다음에 실행할 명령어의 주소
- Interrupt Vector : 인터럽트 유발한 장치를 위한 ISR의 주소 배열. 즉, 인터럽트 핸들러 함수가 모여 있는 곳.
- ISR(Interrupt Handler Function) : 해당 인터럽트를 처리하기 위한 코드 집합. 즉, 인터럽트를 핸들링하기 위한 함수
  - 만약, ISR을 수행할 때, 우선순위가 더 높은 인터럽트 발생 시, 재귀적으로 과정을 수행합니다.
  - ISR 내에서는 다른 인터럽트가 발생하지 않도록 인터럽트 플래그를 사용해 중첩된 인터럽트를 방지합니다.
- Context : 프로세스와 관련된 정보의 집합
  - CPU Register Context : CPU(프로세서) 내부에 위치
  - Code & Data, Stack, PCB : 메모리에 위치.
Polling 방식에 대해 설명해 주세요.
- 폴링은 특정 주기를 갖고 해당 주기마다 처리를 위한 시그널이 들어왔는지 체크합니다. 따라서 커널과 같은 인터럽트 핸들러가 필요하지 않습니다.
- 단, 시스템 리소스를 많이 소비하기 때문에 구현 시, 시스템의 성능 저하 원인이 되기도 합니다. 따라서 오늘날의 다양한 프로세스를 처리하기에는 적합하지 않습니다.

- 인터럽트
  - CPU가 아닌 주변의 I/O 장치가 대신 I/O 해주는 방식입니다. 때문에 데이터의 I/O 이루어지는 동안 CPU는 다른 작업을 할 수 있습니다.
  - CPU의 작업과 저장장치의 데이터 이동을 독립적으로 운영할 수 있어서 시스템 효율을 높입니다.
  - 현대 운영체제는 인터럽트 기반의 시스템을 사용합니다.
HW/SW 인터럽트 혹은 외부/내부 혹은 비동기적/동기적 인터럽트에 대해 설명해 주세요.
- 인터럽트에는 HW 인터럽트와 SW 인터럽트가 있고 SW 인터럽트는 비자발적인 예외와 자발적인 System Call로 나뉩니다.

- HW 인터럽트 (=외부 인터럽트, 비동기적 인터럽트)
  - 일반적으로 인터럽트를 부르는 것으로 CPU 외부로부터 인터럽트 요구신호에 의해 발생되는 인터럽트를 말합니다. 때문에 외부 인터럽트라고도 합니다.
  - 다른 하드웨어 장치가 실행 중인 명령어와는 무관하게 생성하는 인터럽트이기 때문에 비동기적 인터럽트라고도 합니다.
  - Ex) 정전/전원의 이상, CPU의 기능 오류 및 기계의 착오, I/O 인터럽트(입출력 오류, I/O 디바이스의 데이터 전송 등), 외부 신호 인터럽트(I/O 장치가 아닌 오퍼레이터나 타이머에 의한 인터럽트)          
- SW 인터럽트 (=내부 인터럽트, 동기적 인터럽트, Trap)
  - 프로그램 내부에서 발생하는 것을 말합니다. 때문에 내부 인터럽트라고도 합니다.
  - 프로세스 오류/종료/시작 등을 기반으로 프로세스에서 발생하는 인터럽트를 말합니다. 즉, 프로세스가 실행 중인 명령어로 인해 발생하기 때문에 동기적 인터럽트라고도 부릅니다.
  - Ex) 잘못된 명령 및 잘못된 데이터 사용, Division By Zero, 오버플로우/언더플로우, 기타 프로그램 Exception 등
동시에 두 개 이상의 인터럽트가 발생하면, 어떻게 처리해야 하나요?
- 운영체제에서 사용되는 인터럽트 처리 메커니즘에 따라 정확한 동작이 달라질 수 있지만 주로 아래와 같은 동작으로 처리합니다.
  - 인터럽트 우선순위 할당 : 가장 높은 우선순위를 가진 인터럽트를 처리합니다.
  - 인터럽트 마스킹 : 인터럽트 처리 중 다른 인터럽트를 일시적으로 비활성화하여 우선순위를 선점하지 못하도록 방지할 수 있습니다.
  - 인터럽트 큐, 버터 : 받은 순서대로 대기 중인 인터럽트를 처리하고 처리 순서를 관리합니다.
HW 인터럽트와 SW 인터럽트 중 어떤 것이 우선순위가 높나요?
- 보통 HW 인터럽트가 높은 것으로 알고 있습니다.

1. 전원 이상
2. 기계 착오
3. 외부 신호
4. I/O
5. 명령어 에러
6. 프로그램 검사
7. SuperVisor Call

프로세스 & 스레드

프로세스와 스레드가 무엇인가요?
  • 프로세스
    • 컴퓨터의 메모리에 올라가 실행 중인 프로그램을 의미합니다.
    • 즉, 프로그램이 메모리에 올라가면 프로세스가 되는 인스턴스화가 일어나고 이후 OS의 CPU 스케줄링에 따라 CPU가 프로세스를 실행합니다.
  • 스레드
    • 스레드는 프로세스 내 작업의 실행 흐름 단위입니다. 즉, 프로세스의 실행 가능한 가장 작은 단위입니다.
    • 즉, 프로세스는 여러 스레드를 가질 수 있습니다.

프로그램과 프로세스, 스레드의 차이에 대해 설명해 주세요.
- 프로그램
  - 사용자가 원하는 일을 처리할 수 있도록 프로그래밍 언어를 사용해 올바른 수행절차를 표현해놓은 명령어들의 집합입니다.
  - 컴퓨터에서 어떤 작업을 위해 실행할 수 있는 정적인 상태의 파일로 메모리에 적재되기 전 상태의 파일입니다.
- 프로세스
  - 각 프로세스는 OS로부터 필요한 자원을 할당 받습니다. 즉, 운영체제가 메모리 등의 필요한 자원을 할당해준 실행 중인 프로그램을 말합니다.
  - 각 프로세스는 독립적으로 Code/Text, Data, Stack, Heap 영역을 관리합니다.
  - 독립적으로 관리하기 때문에, 동기화 문제 등은 발생하지 않지만, 다른 프로세스의 자원에 접근하기 위해 프로세스간 통신(IPC)을 사용해야 합니다.
- 스레드
  - 각 스레드는 프로세스가 할당받는 자원을 이용합니다. 즉 프로세스 내에서 작업을 수행하는 실행 단위로 하나의 프로세스에 여러 스레드가 있습니다.
  - 각 스레드는 Code/Text, Data(전역 변수 등), Heap 영역을 공유하고 Stack(지역 변수 등) 영역, 스레드 실행 환경 정보를 독립적으로 관리합니다.
  - 각 스레드는 메모리를 공유하지만, 이로 인해 동기화, 데드락 등의 문제가 발생할 수 있습니다.
PCB(Process Control Block)가 무엇인가요?
- CPU가 프로세스를 실행할 때 필요한 중요 정보들을 보관하는 자료구조입니다. 즉, 프로세스에 대한 메타데이터를 저장하는 블록입니다.
- 모든 프로세스는 고유한 PCB를 갖는데, 프로세스 생성 시 PCB도 함께 생성되고 프로세스 완료 시, PCB도 함께 삭제됩니다.

- PCB에 저장되는 정보 (구조)
  - 프로세스 상태 : New, Ready, Running, Wait, Terminated 등
  - 프로세스 구분자 (PID) : 각 프로세스의 고유 식별 변호
  - 프로그램 카운터 (PC) : 다음에 실행될 명령어의 위치 값. 예를 들어, Context Switching을 할 때, 어디부터 다시 실행해야하는 지 알려줍니다.
  - CPU 레지스터 및 일반 레지스터 정보 : 프로세스를 실행하기 위해 저장해야 할 레지스터 정보
  - CPU 스케줄링 정보 : 우선 순위, 최종 실행 시간, CPU 점유 시간 등의 정보
  - 메모리 관리 정보 : 프로세스 주소 공간 정보
  - I/O 상태 정보 : 프로세스에 할당된 I/O 장치 목록, 열린 파일 목록 등 
  - 프로세스 계정 정보 : Page Table, Scheduling Queue Pointer, 소유자, 부모 등
  - Stack Pointer : 부모/자식 프로세스에 대한 포인터, 프로세스가 위치한 메모리 주소에 대한 포인터, 할당된 자원에 대한 포인터 정보.
                    이는 함수 호출 시 스택의 가장 위쪽 데이터의 위치를 가리킵니다.
그렇다면, 스레드는 PCB를 갖고 있을까요?
- 스레드는 프로세스 내부에 있으므로 PCB를 가지지 않고 TCB(Thread Control Block)를 가집니다.
- TCB는 스레드와 관련된 정보만 가지기 때문에, PCB보다 적은 데이터를 가집니다.
- TCB는 스레드가 생성될 때마다 생성되고 스레드 종료 시, 해제됩니다.
- TCB는 보통 Linked List로 구현되어 있는 것으로 알고 있습니다.

- TCB에 저장되는 정보 (구조)
  - 스레드 ID (TID) : 각 스레드의 고유 식별 번호
  - 스레드 상태 : 순서열 레지스터, 스택 포인터, 프로그램 카운터 (PC)
    - 순서열 레지스터 : 명령의 진행 상태
    - 스택 포인터 : 스레드 함수 호출 시 저장되는 곳이 스택이라 실행 흐름을 저장하는 데 필요
    - 프로그램 카운터 (PC) : 스레드 내에서 실행될 다음 명령어의 주소
  - 스케줄링 정보
  - PCB에 대한 포인터 : 해당 스레드를 포함하는 프로세스에 대한 포인터
프로세스 상태에 대해 설명해주세요.
- Create/New (생성 상태)
  - 프로세스가 생성 중인 상태를 의미합니다.
  - 이때, 프로세스를 생성하기 위한 여러 작업(Ex: PCB 생성)과 장기 스케줄러 승인 등의 과정을 밟습니다.
  - Ex) `fork()`, `exec()`
- Ready (준비 상태)
  - 생성된 프로세스가 CPU 스케줄러로부터 CPU 소유권을 얻을 때까지 기다리는 상태입니다.
  - CPU가 하나인 경우 컴퓨터는 한 번에 하나의 프로세스만 실행할 수 있어서 기다리는 상태입니다.
  - 실제로 CPU 자원을 어떤 프로세스에게 줄 지에 대한 알고리즘도 다양합니다.
- Running (실행 상태)
  - 프로세스가 CPU를 얻어 실제 작업을 수행하는 상태입니다. (명령어들이 실행되고 있는 상태)
  - 즉, CPU 소유권을 얻고 메모리를 할당받아 수행 중인 상태로 `CPU Burst`가 일어났다고 합니다.
- Wait/Blocked (대기 상태)
  - 어떤 이벤트가 발생한 후 프로세스가 중단된 상태입니다. 즉, 프로세스가 어떤 이벤트가 발생하기를 대기하는 상태입니다.
  - 이는 작업의 효율성을 위해 OS에 추가된 상태로 CPU가 주어져도 당장 작업을 수행할 수 없는 상태입니다.
  - 예를 들어, 프린트 인쇄 버튼으로 인한 I/O 요청 인터럽트가 발생한 경우가 있습니다. 즉, 실행 상태의 프로세스가 I/O을 요구한 경우입니다.
- Terminated/Exit (완료 상태)
  - 프로세스가 작업을 마친 후 해당 프로세스에 대한 자원을 반납하고 PCB가 삭제되는 상태를 말합니다.
  - 종료는 자연스럽게 종료되는 상황도 있지만, 부모 프로세스가 자식 프로세스를 강제적으로 종료시켜 비자발적 종료되는 경우(Abort)도 있습니다. 

[상세]
- Ready Suspended (준비 중단 상태)
  - 메모리 부족으로 일시 중단된 상태입니다.
  - 즉, Ready Queue가 꽉찬 상태입니다.
- Blocked Suspended (일시 중단 상태)
  - 중단 상태에서 프로세스가 실행되려고 했는데, 또 다시 메모리 부족으로 일시 중단된 상태를 말합니다. 

[흐름 예시]
1. New -> Ready : 생성 완료 시, OS 커널에 존재하는 Ready Queue에 올라갑니다.
2. Ready -> Running : Ready Queue에 있는 프로세스들을 OS가 프로세스 스케줄링 알고리즘에 의해 Running 상태로 가야할 프로세스를 CPU로 할당합니다.
3. Running -> Waiting : 현재 Running 상태에 있는 프로세스 A에서 I/O 이벤트가 발생하여 프로세스 A가 대기합니다.
4. Running -> Ready : I/O 이벤트가 종료된 프로세스 A가 다시 Ready Queue에 올라갑니다. (이후 다시 2번으로)
5. Running -> Terminated : 프로세스 A의 작업이 완료됩니다.
6. Ready -> Waiting : 이 모든 과정에서 하나의 작업을 매우 짧은 시간 동안 처리 후 다른 작업으로 넘어가는 것을 반복합니다. 겉으로 보기엔 동시에 실행되는 것처럼 보입니다. (Cuncurrency)

리눅스에서 프로세스와 스레드는 각각 어떻게 생성될까요?
  • 부모 프로세스
    • 리눅스는 부팅될 때 부트로더에서 커널을 작동합니다.
      • 부트로더: OS가 시동되기 전에 미리 실행되면서 커널이 올바르게 시동되기 위해 필요한 관련 작업을 마무리하고 최종적으로 OS를 시동시키기 위한 목적을 가진 프로그램.
    • 작동된 커널이 init 프로세스를 실행합니다.
      • init 프로세스: 모든 프로세스의 부모 프로세스입니다.
  • 자식 프로세스
    • 대부분 fork() 혹은 exec() 시스템 콜 함수를 사용해 자식 프로세스를 생성합니다.
      • fork() : 부모 프로세스와 동일한 정보(PCB)를 갖는 자식 프로세스를 만드는 시스템 콜입니다.
      • exec() : 해당 함수로 호출된 부모 프로세스를 새로운 정보로 덮어버려 다른 작업을 하는 자식 프로세스를 만드는 시스템 콜입니다.
  • 스레드
    • pthread_create() 시스템 콜 함수를 사용해 생성합니다.
      • 같은 프로그램 내에서 작은 작업을 처리하는 데 fork()를 통해 부모와 동일한 자식 프로세스를 생성하는 것은 비용이 많이 발생합니다.
      • 반면, 스레드는 부모 프로세스의 PCB 정보를 가지고 있기 때문에, 해당 시스템 콜 함수로 부모 프로세스와 같은 정보에 적은 비용으로 접근해 필요한 작업만 처리가 가능합니다.

자식 프로세스가 상태를 알리지 않고 죽거나, 부모 프로세스가 먼저 죽게 되면 어떻게 처리하나요?
- 좀비 프로세스 (Zombie Process)
  - 자식 프로세스가 부모 프로세스에게 상태를 알리지 못하고 죽으면, 자식 프로세스는 좀비 프로세스가 됩니다. 
  - 이를 위해 커널은 자식 프로세스가 종료되어도 최소한의 정보(PID, 종료 상태 등)을 남겨두기 때문에, wait() 함수를 통해서 좀비 프로세스들을 회수할 수 있습니다.
  - 즉, 좀비 프로세스는 다른 말로 부모 프로세스가 wait()를 호출하지 못한 상태로 자식 프로세스가 먼저 죽은 상황이라고 할 수 있습니다.
  - 만약 부모 프로세스가 wait()를 오랫동안 호출하지 않아 메모리가 남아있는 경우 결국 자원 낭비를 야기하고 최악에는 리소스의 유출을 야기할 수 있으니 꼭 처리해야 합니다.
- 고아 프로세스 (Orphan Process)
  - 부모 프로세스가 자식 프로세스보다 먼저 죽은 경우 자식 프로세스들은 고아 프로세스가 됩니다. 즉, 고아 프로세스들은 종료 상태를 확인하거나 회수할 수 없습니다.
  - 하지만 다행히 OS는 고아 프로세스를 허용하지 않기 때문에, 부모 프로세스가 먼저 종료되면 자식 프로세스들은 새로운 부모 프로세스로 init이 설정됩니다.
  - 이 init 프로세스는 자식 프로세스가 종료될 때까지 기다린 후 wait 함수를 호출합니다. 즉, 고아 프로세스들이 좀비 프로세스가 되는 것을 방지합니다.
  - 고아 프로세스는 시스템이 프로세스가 종료될 때까지 추적해야해서 시스템 자원을 낭비할 수 있습니다. 즉, 성능 저하의 원인이 됩니다.
리눅스에서 데몬 프로세스(Daemon Process)에 대해 설명해 주세요.
- 서비스 요청에 대해 응답하기 위해 오랫동안 실행 중인 백그라운드 프로세스를 말하는 것으로 부팅 시 자동으로 생성됩니다.
- 즉, 백그라운드 프로세스 중 부모 프로세스의 고유 번호 즉, PPID가 1인 프로세스를 말합니다.
- 데몬 프로세스는 사용자와 상호작용하지 않고 주로 시스템의 특정 기능을 지속해서 실행하거나 관리하는 데 사용됩니다.

- 예시
  - 웹 서버, 네트워크 서비스, 로깅 서비스 등
  - 웹 서버: 서버에서 터미널을 통해 실행될 수 있지만 터미널을 통해 사용자와 대화할 필요는 없어서 백그라운드 프로세스로 만들어집니다.
- 특징
  - 백그라운드에서 실행됩니다.
  - 주기적으로 시스템 작업(백업, 로깅, 네트워크 통신 등)을 수행하거나 관리하고 특정 서비스를 제공합니다.
  - 무한 루프 실행하여 지속적으로 요청을 처리하거나 시스템을 모니터링합니다.
  - init 프로세스의 자식 프로세스로 시작됩니다. 즉, 시스템 부팅 시 init 프로세스에 의해 시작되고 관리됩니다.
포그라운드 프로세스와 백그라운드 프로세스 개념을 설명해주세요.
- 포그라운드 프로세스
  - 표준 I/O 장치를 통해 대화하는 프로세스를 말합니다.
  - 표준 I/O 장치 예시: 터미널, 키보드 
- 백그라운드 프로세스
  - 입력 장치에 대해 터미널과의 관계를 끊은 모든 프로세스를 말합니다.
  - 즉, 키보드를 통해 사용자에게 입력받지 않고 스스로 동작하는 프로세스입니다.
리눅스는 프로세스가 일종의 트리를 형성하고 있습니다. 이 트리의 루트 노드에 위치하는 프로세스에 대해 설명해 주세요.
- 루트 노드에 위치한 프로세스는 init 프로세스입니다. 즉, 모든 프로세스의 부모 프로세스로 PID는 항상 1입니다. 최근에는 systemd라고도 부릅니다.
- 이 init 프로세스는 리눅스가 부팅될 때 부트로더에서 작동된 커널이 실행시킵니다. 즉, 부팅 시 첫 번째로 생성되고 보통 종료될 때까지 Running 상태입니다.
- init 프로세스는 시스템의 초기화 및 관리를 담당합니다. 예를 들어, 시스템 서비스의 시작/중지, 사용자 로그인/로그아웃 등의 작업을 말합니다.
- 이 프로세스로부터 모든 시스템/사용자 프로세스가 파생됩니다.

- 부트로더
  - OS가 시동되기 전에 미리 실행되어 커널이 올바르게 시동되도록 필요한 모든 작업을 마무리합니다.
  - 최종적으로 OS를 시동시키기 위한 목적을 가진 프로그램입니다.

프로세스 주소 공간(프로세스 메모리 구조)에 대해 설명해 주세요.
  • 실행 중인 각 프로세스에 할당된 메모리 공간을 의미하는 것으로 각각 고유한 주소 공간을 가집니다.
  • 이 메모리 공간은 한정적이라 프로세스는 이 공간을 절약하기 위해 Stack, Heap, Data, Code(Text) 영역으로 할당합니다.
  • 반면, 스레드 같은 경우엔 프로세스 내에서 독립된 Stack 영역을 할당받고 나머지 영역은 공유합니다. 때문에, Data 영역(전역 변수)은 동시에 여러 스레드가 접근할 수 있어서 동기화가 필요합니다.

스레드의 주소 공간은 어떻게 구성되어 있을까요?
- 스레드는 프로세스 내에서 스택만 독립적으로 할당받고 나머지 영역은 공유합니다.
- 때문에, Data 영역의 자원은 동시에 여러 스레드가 접근할 수 있어서 동기화 처리가 필요합니다.
- 예를 들어, 한 스레드가 공유 데이터에 대한 접근을 마칠 때까지 다른 스레드가 공유 데이터에 접근하지 못하도록 제어해야 합니다.
프로세스의 각 영역을 설명해주세요.
- Stack 영역
  - 함수 호출 정보와 관계되는 지역 변수, 매개변수가 저장되는 영역으로 함수의 호출과 함께 할당되고 함수 완료 시, 소멸합니다.
  - 즉, 재귀 함수가 너무 깊게 호출되거나 함수가 지역변수를 너무 많이 가지고 있으면 스택 영역을 초과해 Stack Overflow 에러가 발생할 수 있습니다.
  - 메모리의 높은 주소에서 낮은 주소 방향으로 할당됩니다.
  - 이 영역은 대부분 컴파일 시 크기가 결정됩니다.(정적) 다만 재귀 함수 등에 의해 런타임 시 결정되기도 합니다.(동적)
- Heap 영역
  - 주로 클래스 등의 참조형 데이터가 할당되는 영역으로 사용자에 의해 공간이 동적으로 할당 및 해제됩니다. 즉, 런타임에 크기가 결정됩니다.
  - 메모리의 낮은 주소에서 높은 주소 방향으로 할당됩니다.
  - 대표적으로 C언어에서는 malloc()와 free() 함수로 메모리를 할당 및 해제합니다.
- Data 영역 (Data & BSS)
  - 전역 변수나 Static 변수 등 프로그램이 사용할 수 있는 데이터를 저장하는 영역으로 프로그램 시작과 함께 할당되며 프로그램 종료 시 소멸합니다.
  - 즉, 어떤 프로그램이 전역 혹은 Static 변수를 참조하는 코드가 존재하면 이 프로그램은 컴파일된 후 실행 시점에 Data 영역을 참조하게 됩니다.
  - 만약, 초기화 되지 않은 변수가 존재한다면 BSS 영역에 초기화되어 저장됩니다.
    - Data : 특정 값으로 할당된 변수들이 저장되는 곳
    - BSS : 초기화되지 않은 변수들이 저장되는 곳
- Code 영역 (Text 영역)
  - 프로그램 명령어가 저장되는 영역입니다. 즉, 프로그램이 실행될 수 있도록 CPU가 해석 가능한 기계어 코드가 저장되어 있는 영역입니다.
  - 이는 수정되면 안되므로 ReadOnly 상태로 저장되어 있습니다.
전역 변수 중 초기화 하지 않은 변수들은 어디에 저장될까요?
- 컴파일 시점에 데이터 영역의 BSS(Block Started by Symbol) 영역에 저장됩니다. 즉, 크기는 컴파일 단계에서 정해지고 변하지 않습니다.
- 참고로 초기화되지 않은 변수에 대해 메모리를 할당하지만, OS에 따라 정해진 기본값(보통 0)으로 변수를 초기화해주는 경우도 있습니다.
Stack과 Heap의 크기는 정해져 있나요? 그렇지 않다면 언제 결정되나요?
- 클래스 등과 같은 참조형 데이터들은 Stack이 아닌 Heap에서 관리됩니다. 예를 들어, Stack 영역에 등장하는 각 변수들은 
  Heap 영역에 위치한 객체의 참조를 가질 뿐 실제 객체 값은 Heap 영역에서 관리됩니다. 때문에, Stack 매우 클 필요는 없어서 크기에 제한을 가질 것이라 생각합니다.
  반면, Heap 실제 객체를 관리하는 만큼 Stack 영역과는 다르게 크기 정해져 있지 않고 동적으로 정해질 것 같습니다.
    
- Stack
  - 생성과 동시에 크기가 결정되고 웬만하면 바뀌지 않습니다. 물론 런타임 시에 변경될 수도 있습니다.
  - Heap 영여과 상관없이 크기의 제한을 가집니다.
- Heap
  - 런타임에 크기가 결정되고 동적으로 바뀝니다. 즉, 가변적 크기입니다.
Stack과 Heap 영역 중 접근 속도가 더 빠른 공간은 어디일까요?
- 접근 속도가 더 빠른 공간은 일반적으로 Stack 영역이라 생각합니다.

- Stack
  - 스택은 이미 생성되어 있는 영역의 값들에 대해 포인터의 위치만 바꿔주는 단순한 CPU instruction이라 생각합니다.
- Heap
  - 힙은 메모리 블록들이 흩어져 있을 수 있어 단편화 문제가 발생하는 등을 고려해야 하기 때문에 더 복잡한 CPU instruction이 필요하다 생각합니다.
스택과 힙 영역을 개발자가 아닌 사용자가 크기를 수정할 수 있나요?
- 스택과 힙 영역의 크기는 런타임에 결정됩니다. 즉, 실행 중 동적으로 크기가 필요에 따라 변합니다.
- 때문에, 프로그램 개발자가 아닌 사용자가 이 공간의 크기를 수정하는 것은 어렵다고 생각합니다.

- 웹 애플리케이션의 사용자 : 수정 불가능
- OS 개발자 혹은 JVM 개발자 : 수정 가능
"스택"영역과 "힙"영역은 정말 자료구조의 스택/힙과 연관이 있을까요?
- 결론부터 말씀드리면 관련이 있다고 생각합니다. 추가로 OS의 스택/힙은 특정 개념을 가리킵니다.

- Stack
  - 자료구조 : 후입선출(LIFO) 원칙을 따르는 선형 데이터 구조로 Push/Pop이 주요 작업입니다.
  - 운영체제 : 함수호출/지역 변수를 관리하는 영역으로 함수 호출 시, 새로운 스택 프레임에서 Push 되고 반환 시, Pop 됩니다. 
- Heap
  - 자료구조 : 트리와 유사한 구조로 구현되어 있고 삽입/삭제 등의 작업을 지원하며 메모리를 효율적으로 관리합니다.
  - 운영체제 : 동적 할당에 사용되는 메모리 영역을 의미하고 malloc(), new 등과 같은 명령어를 사용해 런타임에 메모리를 요청합니다.
다음과 같이 공간을 분할하는 이유가 있을까요?
- 결론 : 각 역할을 분배하고 필요에 따라 데이터를 공유하여 메모리 사용량을 줄이기 위함이라 생각합니다.

- 스택 영역 분리 이유
  - LIFO(후입선출) 구조를 이용해 함수 호출과 지역변수 관리가 쉽도록 설계되어 빠른 호출과 반환 작업이 가능합니다.
  - 또한 구조화된 형태와 고정된 할당 패턴은 메모리 조각화와 할당 관련 문제를 예방하는 데 도움됩니다.
  - 스택은 작고 메모리 엑세스 패턴이 예측 가능하기 때문에, 캐시에 저장해두고 쓰기 좋습니다.
- 힙 영역 분리 이유
  - 한 번의 함수 호출 범위를 넘어 지속되어야 하는 경우 동적 수명을 갖는 데이터를 관리하기 위해 필요합니다.
  - 예를 들어, 힙을 사용하면 데이터를 구조화되지 않은 방식으로 할당/해제할 수 있으므로 다양한 크기의 데이터 구조를 관리하는 데, 유연성을 제공합니다.
- 코드(텍스트) 영역 분리 이유
  - 같은 프로그램에선 모두 같은 내용이기 때문에, 따로 관리하여 공유합니다. 그리고 애초에 기계어만 들어있기 때문에, 다른 영역과 분리하는게 당연하다고 생각합니다.
- 스택 영역과 데이터 영역 분리 이유
  - 스택 구조의 특성과 전역변수의 활용성을 위해 분리되었다고 생각합니다. 예를 들어, 스택은 함수의 흐름을 관리하지만, 데이터는 전역 혹은 Static 변수를 관리합니다.
  - 또한 각 스레드는 독립된 Stack 영역을 갖지만 Data 영역은 공유합니다. 즉, 각 스레드가 동일한 Data 공유함으로써 메모리를 절약할 수 있습니다.
- Data 영역의 Data, BSS 분리 이유
  - 초기화된 변수는 영역과 값 모두 프로그램에 저장하고 있어야 하지만 초기화되지 않은 변수는 프로그램이 실행될 때 영역만 정해주면 됩니다.
  - 즉, BSS 영역은 변수들이 많아져도 프로그램의 실행 코드 사이즈를 늘리지는 않는 것으로 알고 있습니다.
정적 할당과 동적 할당에 대해 설명해주세요.
- 정적 할당
  - 정적 할당은 컴파일 단계에서 메모리가 할당되는 것을 말합니다.
  - 보통 정적 할당은 Data 영역의 Data/BSS와 Code(Text) 영역으로 나뉘어집니다.
- 동적 할당
  - 동적 할당은 런타임 단계에서 메모리가 할당되는 것을 말합니다.
  - 보통 동적 할당은 Stack 영역과 Heap 영역으로 나뉘어집니다.

프로세스 문맥 교환(Context Switching)이란 무엇인가요?
  • CPU에서 실행 중이던 프로세스/스레드가 다른 프로세스/스레드로 교체되는 것을 말합니다. 즉, PCB/TCB 교체 과정이라 할 수 있습니다.
  • 다시 말해, PCB/TCB를 기반으로 프로세스/스레드를 저장하고 다시 복원하는 과정을 말합니다.
  • 이는 한 프로세스에 할당된 시간이 끝났을 때, 프로세스가 종료될 때, I/O 요청에 의한 시스템 콜, 인터럽트 등에 의해 발생합니다.

Context Switching(문맥 교환) 시, 어떤 일들이 일어나나요? 흐름을 설명해주세요.
1. PCB/TCB에 현재 수행 중인 프로세스/스레드 상태를 저장 후 커널 모드로 전환됩니다.
2. 스케줄링 알고리즘을 통해 다음 실행할 프로세스/스레드를 결정합니다.
3. 결정된 프로세스/스레드의 PCB/TCB를 새로 생성하거나 불러옵니다.
4. 불러온 PCB/TCB에 해당하는 프로세스/스레드를 실행하기 위해 사용자 모드로 전환됩니다.
프로세스와 스레드는 컨텍스트 스위칭이 발생했을 때 어떤 차이가 있을까요?
- 결론적으로는 컨텍스트 스위칭은 스레드가 프로세스에 비해 오버헤드와 비용이 적어 더 빠르고 효율적입니다.

- 이유
  - 스레드는 스택 영역을 제외한 모든 영역을 공유하기 때문에 스택 및 PC 등 일부만 교환하면 됩니다. 즉, TCB가 PCB보다 가볍습니다.
  - 프로세스는 서로 다른 메모리 주소 공간을 가집니다. 때문에 새로 실행되는 프로세스가 기존 프로세스의 메모리 주소 공간을 침범하면 안됩니다.
    따라서, Page Table 교체와 TLB를 완전히 비워주는 작업, MMU 변경 등이 추가적으로 발생하여 더 많은 비용이 발생하게 되는 것입니다.

- PC (Program Counter)
  - 다음에 실행될 명령어의 위치 값입니다. 
  - 예를 들어, Context Switching을 할 때, 어디부터 다시 실행해야하는 지 알려줍니다.
- Page Table
  - 가상 메모리 주소와 물리 메모리 주소 간의 매핑을 저장하는 자료구조입니다.
- TLB (Table Lookaside Buffer)
  - 가상 메모리 주소를 물리적 주소로 변환하는 속도를 높이기 위해 사용하는 것으로 MMU에 위치한 캐시입니다.
  - CPU가 가상 주소로 메모리에 접근하려고 할 때, 먼저 TLB에 접근하고 없으면 Page Table에서 찾습니다.
- MMU (Memory Management Unit)
  - 가상 메모리 주소를 물리 메모리 주소로 매핑 시켜주는 역할을 수행하는 HW입니다.
  - 뿐만 아니라, 잘못된 주소에 접근하지 않도록 보호하는 역할도 합니다.
컨텍스트 스위칭이 발생할 때, 기존의 프로세스 정보는 커널 스택에 어떠한 형식으로 저장되나요? (답변 미작성)
컨텍스트 스위칭은 언제 일어날까요?
- 주어진 할당 시간(Time Slice)을 다 사용했을 때, I/O 작업을 해야할 때, 다른 리소스를 기다려야 할 때, 인터럽트 등 여러 이유로 발생합니다.
A 프로세스에서 인터럽트 혹은 시스템 콜로 인해 유저모드에서 커널모드로 넘어간 뒤, 다시 A로 돌아온 경우도 컨텍스트 스위칭인가요?
- 특정 프로세스가 특정 이벤트에 의해 커널 모드로 넘어간 뒤 다시 원래 프로세스로 복귀한다면 다른 프로세스로 복귀한 것이 아니기 때문에, Context Switching이라 할 수 없습니다.

멀티 프로세스 & 멀티 스레드

단일 프로세스, 멀티 프로세스와 멀티 스레드의 차이점을 설명해주세요.
  • 단일 프로세스
    • 말 그대로 하나의 프로세스로 사용하는 것을 말합니다. 때문에, CPU 사용률이 떨어집니다.
    • 예를 들어, 한 프로세스가 실행되고 있을 때 CPU를 사용하다가 I/O 작업을 만나면 I/O 작업으로 인해 CPU는 놀고 있기 때문입니다.
  • 멀티 프로세스
    • 하나의 프로그램을 여러 개의 프로세스로 나눠 사용하는 것을 말합니다.
    • 각 프로세스가 OS에게 독립적으로 자원을 할당받아 서로의 메모리에 침범하지 않습니다.
    • 독립적인 영역을 가져 안정적입니다. 즉, 각 프로세스에 문제가 발생해도 다른 프로세스에 영향을 주지 않습니다.
    • 서로 독립된 메모리를 가지기 때문에, 서로 메모리를 공유하기 위해 IPC(Inter Process Communication) 기법을 사용해야 합니다. 이 과정에서 추가적인 설비가 필요하고 다소 비효율적입니다.
    • 서로 독립된 메모리를 가져 Context Switching(문맥 교환) 발생 시, 시간이 오래 걸립니다.
  • 멀티 스레드
    • 하나의 프로세스가 여러 스레드를 갖고, 각 스레드가 서로 다른 작업들을 수행하는 것을 말합니다.
    • 프로세스를 추가적으로 생성하지 않기 때문에, 비용 측면에서 효율적입니다.
    • 스레드는 동일한 프로세스 내 자원을 공유하기 때문에 프로세스에 비해 효율적입니다. 단, 동기화 처리가 필요한 상황이 생길 수 있습니다.
    • 하나의 스레드에 문제가 생기면 프로세스 전체에 문제가 발생할 수 있습니다.

멀티 프로세스, 멀티 스레드 중 어떤 것을 선택하는 게 좋을까요?
- 대부분의 경우 멀티 스레드를 선택할 것 같습니다.
- 멀티 프로세스의 경우 멀티 프로세스를 시작하기 위해 여러 프로세스를 생성해야 하기 때문에 비용이 많이 발생합니다.
- 또한 각 프로세스가 독립적이기 때문에 스레드의 Context Switching 과정보다 프로세스의 Context SWitching 과정에서 비교적 많은 비용이 발생할 것입니다.
- 그리고 스레드의 자원 공유 방식이 프로세스의 IPC 기법보다 더 빠르고 효율적이기 때문에 멀티 스레드를 선택할 것 같습니다.
웹 브라우저는 멀티 스레드인가요? 멀티 프로세스인가요? (답변 미작성)
크롬의 경우 멀티 프로세스 구조를 택했는데, 그 이유는 무엇일까요?
- 멀티 스레드라면 각각의 크롬 탭에서 문제가 발생하거나 확장 중에 문제가 발생하면 전체 브라우저에 영향이 갈 수 있습니다.
- 크롬은 특정 탭이 전체 브라우저에 영향이 가지 않도록 하기 위해 서로 다른 프로세스로 분리시켜 관리한다고 생각합니다.

동시성과 병렬성의 차이에 대해 설명해 주세요.
많은 프로세스가 동시에 실행되는 것처럼 보이는 이유는 무엇일까요? (답변 부족)
- 싱글 코어 기준
  - 컴퓨터는 많은 프로그램을 동시에 실행되는 것처럼 보이지만, 사실 특정 시점에 실행되는 프로세스는 단 1개입니다.
  - 이는 프로세스들 간에 컨텍스트 스위칭이 매우 빠르게 발생하여 동시에 실행되는 것처럼 보이는 것입니다.
- 멀티 코어 기준
  - 현대 컴퓨터는 멀티 코어 CPU를 가지기 때문에, 특정 시점에 단 1개의 프로세스가 실행된다는 말은 틀린말입니다.

CPU 혹은 프로세스 스케쥴링이라 부르는 데, 이에 대해서 설명해주세요.
  • 스케줄링 알고리즘 종류로는 무엇이 있나요?
  • 단기, 중기, 장기 스케줄링에 대해서 설명해주세요.
  • 현대 OS에는 단기, 중기, 장기 스케쥴러를 모두 사용하고 있나요?
  • 프로세스 스케쥴링 상태에 대해 설명해 주세요.
  • 선점형(preemptive) 스케줄링과 비선점형(non-preemptive) 스케줄링의 차이점은 무엇일까요?
  • 선점형(preemptive)과 비선점형(non-preemptive)에서 존재할 수 없는 상태가 있을까요?
  • RR을 사용할 때, Time Slice에 따른 trade-off를 설명해 주세요.
  • Memory가 부족할 경우, Process는 어떠한 상태로 변화할까요?
  • 싱글 스레드 CPU 에서 상시로 돌아가야 하는 프로세스가 있다면, 어떤 프로세스 스케쥴링 알고리즘을 사용하는 것이 좋을까요? 근거는?
  • 타 스케쥴러와 비교하여, Multi-level Feedback Queue는 어떤 문제점들을 해결한다고 볼 수 있을까요?
  • 보통 스케줄링 알고리즘을 "프로세스" 스케줄링 알고리즘이라고 부릅니다. 스레드는 다른 방식으로 스케줄링을 하나요?
  • 유저 스레드와 커널 스레드의 스케쥴링 알고리즘은 똑같을까요?
  • FIFO 스케쥴러는 정말 쓸모가 없는 친구일까요? 어떤 시나리오에 사용하면 좋을까요?

IPC(Inter-Process Communication)가 무엇이고, 어떤 종류가 있는지 설명해 주세요.
  • 서로 다른 프로세스가 데이터를 주고 받고 관리하는 메커니즘입니다.
  • 대표적으로 공유 메모리, 메시지 큐 등이 있습니다.

Shared Memory가 무엇이며, 사용할 때 유의해야 할 점에 대해 설명해 주세요.
- 프로세스 주소 공간의 일부를 공유하여 여러 프로세스가 통신할 수 있도록하는 기법으로 알고 있습니다. 즉, 어떤 매개체를 통해 데이터를 주고 받는 것이 아닙니다. 
- 이는 메모리 자체를 공유하기 때문에, 불필요한 데이터 복사로 인한 오버헤드가 발생하지 않아 IPC 기법 중 가장 빠른 것으로 알고 있습니다.
- 단, 여러 프로세스가 동일한 메모리 영역을 공유하기 때문에, 동기화 처리가 필요합니다. 따라서 쓰기 및 읽기 빈도가 높으면 동기화 처리를 꼭 해줘야 해서 복잡해집니다.
IPC의 Shared-Memory 기법은 프로세스 주소공간의 어디에 들어갈까요? 그 이유는? (답변 부족)
- 공유 메모리 기법 자체가 세그먼트를 생성하고 이 세그먼트를 공유하는 기술입니다.
- 즉, 물리적인 공간에 공유 메모리 영역이 구축되고 이 세그먼트가 물리적인 메모리 주소 공간에 할당된다고 이해하고 있습니다.
- 결론적으로 프로세스 주소 공간에서는 해당 공유 메모리 영역과 매핑해주고 각 프로세스에 이를 통해 세그먼트에 접근하여 데이터를 읽고 쓰는 것 같은데, 
- 그렇다면 "이 프로세스 주소 공간 어디에 들어갈까?"가 궁금한데, 아마 "Data 영역에서 공유 메모리를 가리키는 게 있지 않을까?" 추측해봅니다.
메시지 큐에 대해 설명하고 흐름도 간단하게 말씀해주세요.
- 큐 형태로 관리하는 버퍼를 만들어 통신하는 기법으로 알고 있습니다.
- 이는 커널에서 전역적으로 관리되며 다른 IPC에 비해 사용 방법이 직관적이며 간단합니다.
- 대표적인 예시로 RabbitMQ, Kafka가 있습니다.

- 흐름
  1. 프로세스가 메시지를 보내거나 받기 전에 큐를 초기화합니다.
  2. 프로세스의 메시지는 큐에 복사되어 다른 프로세스에게 전달됩니다.
메시지 큐는 단방향이라고 할 수 있나요?
- 상황마다 다르지만 일반적으로는 단방향이라 생각합니다.
- 예를 들어, 메시지 큐 구현 시 파이프가 쓰이기도 하는데, 익명 파이프에는 단방향이고 명명 파이프를 사용할 경우에는 양방향인 것으로 알고 있습니다.

- 익명 파이프 (Anonymous/Unnamed Pipe)
  - 단방향 방식의 읽기/쓰기 전용 파이프를 만들어 작동하는 방식입니다.
  - 이는 부모-자식 프로세스 간에서만 사용할 수 있고 다른 네트워크 상에서는 사용이 불가능합니다.
  - 파이프의 데이터 용량은 제한되어 있기 때문에 쓰기 프로세스가 읽기 프로세스보다 더 빠르게 사용될 수 없습니다.
- 명명 파이프 (Named Pipe)
  - 양방향 방식의 읽기/쓰기 전용 파이프를 만들어 작동하는 방식입니다.
  - 이는 부모-자식 뿐만 아니라 다른 네트워크 상에서도 통신이 가능합니다.

동기화

뮤텍스와 세마포어의 차이점은 무엇인가요?
  • 이진 세마포어와 뮤텍스의 차이에 대해 설명해 주세요.
  • Lock을 얻기 위해 대기하는 프로세스들은 Spin Lock 기법을 사용할 수 있습니다. 이 방법의 장단점은 무엇인가요? 단점을 해결할 방법은 없을까요?
  • 뮤텍스와 세마포어 모두 커널이 관리하기 때문에, Lock을 얻고 방출하는 과정에서 시스템 콜을 호출해야 합니다. 이 방법의 장단점이 있을까요? 단점을 해결할 수 있는 방법은 없을까요?
Deadlock 에 대해 설명해 주세요.
  • Deadlock 이 동작하기 위한 4가지 조건에 대해 설명해 주세요.
  • 그렇다면 3가지만 충족하면 왜 Deadlock 이 발생하지 않을까요?
  • 어떤 방식으로 예방할 수 있을까요?
  • 왜 현대 OS는 Deadlock을 처리하지 않을까요?
  • Wait Free와 Lock Free를 비교해 주세요.
Thread Safe 하다는 것은 어떤 의미인가요?
  • Thread Safe 를 보장하기 위해 어떤 방법을 사용할 수 있나요?
  • Peterson's Algorithm 이 무엇이며, 한계점에 대해 설명해 주세요.
  • Race Condition 이 무엇인가요?
  • Thread Safe를 구현하기 위해 반드시 락을 사용해야 할까요? 그렇지 않다면, 어떤 다른 방법이 있을까요?
Thread Pool, Monitor, Fork-Join에 대해 설명해 주세요.
  • Thread Pool을 사용한다고 가정하면, 어떤 기준으로 스레드의 수를 결정할 것인가요?
  • 어떤 데이터를 정렬 하려고 합니다. 어떤 방식의 전략을 사용하는 것이 가장 안전하면서도 좋은 성능을 낼 수 있을까요?
동기와 비동기, 블로킹과 논블로킹의 차이에 대해 설명해 주세요.
  • 그렇다면, 동기이면서 논블로킹이고, 비동기이면서 블로킹인 경우는 의미가 있다고 할 수 있나요?
  • I/O 멀티플렉싱에 대해 설명해 주세요.
  • 논블로킹 I/O를 수행한다고 하면, 그 결과를 어떻게 수신할 수 있나요?
동기화를 구현하기 위한 하드웨어적인 해결 방법에 대해 설명해 주세요.
  • volatile 키워드는 어떤 의미가 있나요?
  • 싱글코어가 아니라 멀티코어라면, 어떻게 동기화가 이뤄질까요?

메모리

캐시 메모리 및 메모리 계층성에 대해 설명해 주세요.
  • 캐시 메모리는 어디에 위치해 있나요?
  • L1, L2 캐시에 대해 설명해 주세요.
  • 캐시에 올라오는 데이터는 어떻게 관리되나요?
  • 캐시간의 동기화는 어떻게 이루어지나요?
  • 캐시 메모리의 Mapping 방식에 대해 설명해 주세요.
  • 캐시의 지역성에 대해 설명해 주세요.
  • 캐시의 지역성을 기반으로, 이차원 배열을 가로/세로로 탐색했을 때의 성능 차이에 대해 설명해 주세요.
  • 캐시의 공간 지역성은 어떻게 구현될 수 있을까요? (힌트: 캐시는 어떤 단위로 저장되고 관리될까요?)
메모리의 연속할당 방식 세 가지를 설명해주세요. (first-fit, best-fit, worst-fit)
  • worst-fit 은 언제 사용할 수 있을까요?
  • 성능이 가장 좋은 알고리즘은 무엇일까요?
Thrashing 이란 무엇인가요?
  • Thrashing 발생 시, 어떻게 완화할 수 있을까요?
가상 메모리란 무엇인가요?
  • 가상 메모리가 가능한 이유가 무엇일까요?
  • Page Fault가 발생했을 때, 어떻게 처리하는지 설명해 주세요.
  • 페이지 크기에 대한 Trade-Off를 설명해 주세요.
  • 페이지 크기가 커지면, 페이지 폴트가 더 많이 발생한다고 할 수 있나요?
  • 세그멘테이션 방식을 사용하고 있다면, 가상 메모리를 사용할 수 없을까요?
세그멘테이션과 페이징의 차이점은 무엇인가요?
  • 페이지와 프레임의 차이에 대해 설명해 주세요.
  • 내부 단편화와, 외부 단편화에 대해 설명해 주세요.
  • 페이지에서 실제 주소를 어떻게 가져올 수 있는지 설명해 주세요.
  • 어떤 주소공간이 있을 때, 이 공간이 수정 가능한지 확인할 수 있는 방법이 있나요?
  • 32비트에서, 페이지의 크기가 1kb 이라면 페이지 테이블의 최대 크기는 몇 개일까요?
  • 32비트 운영체제는 램을 최대 4G 까지 사용할 수 있습니다. 이 이유를 페이징과 연관 지어서 설명해 주세요.
  • C/C++ 개발을 하게 되면 Segmentation Fault 라는 에러를 접할 수 있을텐데, 이 에러는 세그멘테이션/페이징과 어떤 관계가 있을까요?
TLB는 무엇인가요?
  • TLB를 쓰면 왜 빨라지나요?
  • MMU가 무엇인가요?
  • TLB와 MMU는 어디에 위치해 있나요?
  • 코어가 여러개라면, TLB는 어떻게 동기화 할 수 있을까요?
  • TLB 관점에서, Context Switching 발생 시 어떤 변화가 발생하는지 설명해 주세요.
페이지 교체 알고리즘에 대해 설명해 주세요.
  • LRU 알고리즘은 어떤 특성을 이용한 알고리즘이라고 할 수 있을까요?
  • LRU 알고리즘을 구현한다면, 어떻게 구현할 수 있을까요?
  • LRU 알고리즘의 단점을 설명해 주세요. 이를 해결할 수 있는 대안에 대해서도 설명해 주세요.

기타

프로그램이 컴파일 되어, 실행되는 과정을 간략하게 설명해 주세요.
  • 링커와, 로더의 차이에 대해 설명해 주세요.
  • 컴파일 언어와 인터프리터 언어의 차이에 대해 설명해 주세요.
  • JIT에 대해 설명해 주세요.
  • 본인이 사용하는 언어는, 어떤식으로 컴파일 및 실행되는지 설명해 주세요.

File Descriptor와, File System에 에 대해 설명해 주세요.
  • I-Node가 무엇인가요?
  • 프로그래밍 언어 상에서 제공하는 파일 관련 함수 (Java - BufferedReader/Writer 등)은, 파일을 어떤 방식으로 읽어들이나요?

Reference