Upstage AI LAB 부트캠프 5기/실시간 공부내용 복습

[2024.10.17] 컴퓨터 공학 개론

김 도경 2024. 10. 17. 19:00

* 강의를 듣고 필기한 내용일 이후에 따로 정리한 내용입니다.

* https://glowdp.tistory.com/32 에서 이어지는 게시물 입니다.

Memory Hierarchy

1. Registers : CPU 내부에 위치하며, 가장 빠른 속도로 데이터에 접근할 수 있는 기억장치
              - CPU가 처리할 데이터나 명령어를 저장하고, 중간 결과를 보관
    
2. Cache Memory : Register와 메인 메모리 사이에 위치하는 기억장치

              - CPU가 처리할 데이터나 명령어를 미리 가져와 저장하므로, 더 빠른 속도로 접근이 가능
              - 일반적으로 캐시는 L1, L2, L3 등의 레벨로 나누어져 있으며, 각 레벨마다 용량과 접근 속도가 다름
    
3. Main Memory (DRAM) : 프로그램이 실행될 때 필요한 데이터나 명령어가 저장되는 주 기억장치
              - CPU가 메모리에 접근하는 속도는 캐시보다 느리지만, 더 많은 용량
    
4. Secondary Memory(=Storage) : 하드디스크(HDD)나 SSD와 같은 보조기억장치
              - 용량은 메인 메모리보다 더 크지만, 접근 속도는 매우 느림
              - 보조기억장치는 데이터를 비롯한 모든 파일을 저장하며, 시스템이 꺼져도 데이터를 유지

Types of memory (RAM, ROM, Flash Memory)
컴퓨터에서 사용되는 메모리는 크게 RAM, ROM, Flash Memory

1. RAM(Random Access Memory) 컴퓨터가 작업 중인 데이터와 프로그램을 저장하는 메모리
              -  읽기와 쓰기 모두 가능하며, 전원이 꺼지면 내용이 지워진다. 일반적으로 가격이 저렴하고, 빠른 속도로 데이터를 처리                  -  DDR4 SDRAM, DDR5 SDRAM 등 여러 종류의 RAM
    
2. ROM(Read-Only Memory) : 주로 컴퓨터의 BIOS(Basic Input/Output System)나 장치 드라이버 등 시스템 소프트웨어를 저장하는 메모리
              - 읽기만 가능하며, 내용을 수정할 수 없다. 전원이 꺼져도 내용이 지워지지 않는다.
    
3. 플래쉬 메모리 : 컴퓨터나 디지털 기기에서 많이 사용되는 메모리
              - 데이터를 저장하고, 읽기와 쓰기가 모두 가능하다. 전원이 꺼져도 내용이 지워지지 않으며, 비교적 저렴한 가격과 높은 용량을 제공
              - USB 메모리, SD 카드, SSD(Solid State Drive) 등에 사용

 

Types of I/O Device

 

  • SSD, HDD와 같은 저장소입니다. block에 저장되고 각각의 주소를 가짐

  • HDD : 기계적인 구조로 이루어진 저장 장치
                - 자성을 띄는 원형 디스크가 회전하면서 헤드로 데이터를 읽고 쓰는 작업이 이루어짐
        - 구조
            - Platter : 여러 개의 자성 디스크가 쌓여 있으며, 고속으로 회전합니다.
            - Head : 데이터를 사용하기 위한 작은 장치로, platter 위에서 자기 신호를 감지
            - Spindle : platter가 회전 하는걸 고정 해주는 축.
            - Arm : platter의 특정 위치로 Head를 옮겨줌
            - 장점 : 비교적 저렴한 가격으로 만들 수 있습니다.
            - 단점 : 기계의 움직임으로 인하여 데이터 입출력이 비교적 느림, 충격에 취약

  • SSD (Solid State Drive): 반도체 메모리 칩(NAND 플래시 메모리)으로 이루어진 저장 장치
        - 구조
            - NAND memory : 데이터가 저장되는 비휘발성 메모리입니다.
            - Controller : 데이터를 관리하는 역할을 하는 장치입니다.
            - DRAM : Cache를 지원하여 더 빠른 속도를 지원할 수 있습니다.
            - 장점 : 빠른 동작 속도, 기계가 아니라서 충격에 강함
            - 단점 : NAND 메모리 성능의 한계, 비교적 비싼 가격, 수명이 있음
Components of I/O System

 

  • device controller : 각 I/O 장치마다 존재하며, 데이터 전송을 관리하는 하드웨어
        - 구성요소
            - I/O port : 장치와 직접적으로 명령어 및 데이터를 주고 받는 부분
            - register : 데이터, 장치의 상태, 동작의 명령어등을 저장하고 보내는 영역.
        - 역할
            - 해당하는 device의 하드웨어적인 동작 제어.
            - 데이터를 주고 받음
            - 작업 상태에 따른 interrupt를 CPU에 전달
  • device driver : 하드웨어와 소프트웨어 간의 인터페이스를 제공하는 소프트웨어
        - 구성요소
            - I/O control : 운영체제와 하드웨어 장치를 관리.
            - buffering : 데이터를 임시저장하여 반응속도를 높여줌
            - Interrupt handler : 발생한 interrupt를 처리할 수 있음
        - 역할
            - 장치 제어, 데이터 관련 정보를 포멧에 맞게 맞춰 보내줌
            - 장치 상태를 추적하여 오류 발생시 운영체제에게 알려줌.
        - 종류
            - kernel mode driver : 자원을 활용하는 상태입
            - user mode driver : 유저가 사용하는 제한된 상태
  • port : 컴퓨터와 연결이 되는 지점
  • Bus : I/O Device간의 연결 및 Device와 CPU등과 연결을 도와줌
Methods of I/O Data transmission
  • 폴링(Polling) : CPU가 주기적으로 장치 상태를 확인하여 데이터를 처리하는 방식
    - 동작 순서
        - CPU가 controller의 Busy Bit(명령어 수행 상태 확인)가 0이 될 때까지 추적
        - CPU가 명령어를 레지스터에 작성하고 command-ready bit(명령어 상태 확인)를 1로 변경
        - Controller가 Busy Bit를 1로 변경.
        - Controller가 명령어 레지스터에 있는 명령어를 수행
        - Command-ready bit와 Busy Bit를 0으로 변경
    - 장단점
        - 장점: 구현이 쉽고 세밀한 동작이 가능
        - 단점: 지속적인 감시 체계가 리소스를 낭비

  • Interrupt Method : 장치가 준비되었을 때 CPU에 신호를 보내 작업을 처리하는 방식
    - 동작 순서
        - CPU가 명령어 레지스터에 명령어를 작성하고 자신이 할일을 수행
        - controller가 명령어 레지스터에서 명령어를 받아서 수행
        - controller가 수행완료 및 특이사항 발생시 interrupt를 유발
        - CPU가 interrupt를 처리 및 controller의 결과물을 받음
    - 장단점
        - 장점 : 감시체계가 사라져서 리소스의 낭비가 사라짐
        - 단점 : interrupt의 발생이 많아질경우 CPU가 계속 응답해줘야 하기때문에 과부하가 발생.

  • DMA(Direct Memory Access) Method : CPU 개입 없이 I/O 장치가 직접 메모리와 데이터를 주고받는 방식
    - 동작 순서
        - CPU가 DMA controller에 데이터를 요청
        - DMA controller가 I/O에서 memory로 데이터를 전송
        - memory로 전송 완료 되면 interrupt를 발생
        - CPU가 interrupt와 데이터를 사용
    - 장단점
        - 장점 : CPU의 간섭없이 많은 데이터를 송수신 할 수 있음
        - 단점 : DMA controller가 지원이 되어야 합니다. 적은 데이터를 사용할때는 번거로울 수 있음

 

Operating System Concepts

Introduction to Operating Systems
  • operating system
    유저가 컴퓨터를 편하게 사용할 수 있게 하드웨어 지원을 관리해주는 프로그램.
    - 사용자 입장에서는 하드웨어의 이용과 성능을 편리하게 해주는 프로그램
    - 시스템 입장에서는 CPU, memory, I/O device 등의 resource를 총괄하는 프로그램
    - 컴퓨터는 매우 다양한 곳에 적용되고, 이 때문에 OS의 보편적인 정의라는 것은 불가능
            / 가장 기초적인 목적은 프로그램을 실행하고 user의 문제를 쉽게 풀 수 있도록 만드는 것에 있음

  • Architecture of Operating System
     - 커널(Kernel): 프로세스 관리, 메모리 관리, 저장공간 관리, 장치 관리 등 컴퓨터에 속한 자원들에 대한 접근을 중재
     -  Interface: 사용자의 명령을 컴퓨터에 전달하고 결과를 사용자에게 알려주는 소통의 역할. 
                 - 사용자가 직접 접하는 화면이 여기에 속함.
                 -  운영체제가 제공하는 대표적인 인터페이스는 GUI(Graphical User Interface), CLI(Command Line Interface)
     -  System call : 사용자나 프로그램이 직접적으로 컴퓨터 자원에 접근하는 것을 막고 커널을 보호하기 위해서 만든 코드 집합.
                  -  system call 함수를 통해 커널에 접근.
     -  Driver: 프린터, 키보드 및 디스크 드라이브와 같은 하드웨어 장치와 운영체제 간의 통신을 가능하게 하는 소프트웨어.

    - 운영체제를 통해 안정적이고, 효율적인 동작을 하기 위해 : 사용자 또는 응용프로그램이 직접 하드웨어에 접근하는 것을 막음
           - User Mode(CPU 명령어 사용을 제한)와 Kernel Mode(CPU 명령어를 사용해 하드웨어를 직접 제어)로 분리해 운영체제를 사용
    - User Mode와 Kernel Mode 사이는 시스템 호출(System Call) 을 통해서 전환된다.

  • System calls and APIs
    System call
        - 입출력, 메모리할당, 프로세스의 생성 등을 수행하는 코드의 집합이다. 사용되는 컴퓨터와 OS에 따라서 다양하게 구현
        - System call의 유형 : Process control, File management, Device management, Information maintenance, Communications
  • Overview of popular operating systems (Windows, Linux, macOS)
        - 운영체제는 데스크탑 뿐만 아니라 임베디드, 서버, 모바일 등의 기기에서도 사용
        -  대표적인 OS의 예시로는 Windows, Unix, macOS, Android 등

        - Windows
              - Microsoft사에서 개발한 컴퓨터용 운영체제
              - 데스크톱 OS 중 가장 많은 점유율을 차지하며 이 덕분에 다양한 서드파티 프로그램이 제작 및 배포되고 있음.
              - 사용자에게 최적화가 가장 잘 되어있는 운영체제

     - Unix
              - 다양한 하드웨어 플랫폼에서 사용되고 있는 운영체제
              - 소규모 내장 컨트롤러부터 데스크탑까지 다양한 영역에서 수많은 응용프로그램을 구동시키는 개방형 표준 운영체제
               - 유닉스는 95% 이상이 C언어로 작성되어 있어 System에 종속적인 부분만 수정한다면 새로운 시스템에서도 실행가능
              - 이러한 확장성 덕분에 Linux나 macOS와 같은 다른 운영체제의 기반
        - macOS
              -  애플에서 Unix/Darwin을 기반으로 개발한 Mac 전용 운영체제
              -  시스템의 전체 설정을 담는 레지스트리가 존재하지 않는다는 특징이 있음
              -  또한 윈도우에 비해 권한체계가 엄격해 보안에 장점을 지님

        - Android
              -  Linux 커널을 기반으로 구글에서 제작하는 모바일 운영체제
              -  오픈소스 지향으로 많은 정보가 공개되어 있고, Java 언어를 통해 응용프로그램의 개발이 가능

 

Processes and Threads

면접 필수 질문 : process VS thread의 차이가 뭔가요?

- 중요해서도 물어보고 대표적인 예시 : 암기하기

 

Program : passive(수동적임)
- 저장공간에 저장되어있는 목록 파일

Process : active(활발한)
- 메뫼에 실행되고 있는 프로그램

 

  • Process states and transitions
    - new : 새롭게 생성된 process
    - ready : CPU에서의 실행을 기다리는 상태
                  - ready가 안 되는 경우도 있다 :  new 요청을 무시 : 승인이 필요함
    - running : 실행중인 process
    - waiting: I/O(사용자의 입출력)이나 scheduling에 의한 대기 상태
    - terminated: 실행을 마친 상태
                  - 프로세스를 없앤다
    - 프로세스는 요청에 따라 상태가 계속 전환된다.
Process management

 

  • 프로세스 제어(프로세스 관리)
        - 각각의 process는 Process Control Block(PCB)에 관련된 정보를 저장한다.
        - PCB에서 다루는 Process 정보
            - Process state
            - Process number(ID)
            - Program counter
            - CPU registers
            - CPU scheduling information
            - Memory-management information
            - I/O status information
  •  Process 생성
        - parent process에서 child process를 생성
        - process들은 고유한 process identifier(pid)를 통해 구분, 관리 됨
                         - PID로 관리, 모든process는 pid로 관리, 권한을 받음, 뭘 사용할 수 있는지, 등등 다양한 옵션들을 받음
        - 생성 시 child process는 부모의 PCB를 공유 받으며 어떤 정보를 공유할지는 공유 옵션에 따라 달라짐
            - Resource sharing option(Full/Partial/No sharing)
            - Execution option(Overlay/Swapping)
            - Address space option(Fixed/Variable)

  • Process 제거(termination)
        - exit system call을 통해 process를 삭제 가능함
        - present process는 wait system call을 통해 child가 정상적으로 제거되었는지 확인
        - 이 때 제대로 process가 제거되지 않으면 Zombie/Orphan 상태의 process가 만들어짐
            - Zombie process: parent에서 child가 죽은걸 모르고 process table에 child에 대한 정보가 남아있는 경우
            - Orphan: child가 terminate되기 전에 parent가 죽어버려서 부모가 없어진 경우
       - CUDAOOMError : ( OOM : Out-Of-Memory ) 재시작해야함 

  • Process Scheduling
        - CPU 내부에서 어떤 process를 다음에 실행할지 선택하는 기능
        - 예시
            - 사용자는 동시에 여러 일을 수행하길 원함(웹서핑을 하면서 노래를 듣고, 카톡알림이 울리는 등)
            - 한번에 실행될 수 있는 Process의 수는 정해져 있음 (보통 하나, Multi-core 환경에서는 늘어날 수 있음).
            - Process Scheduling을 통해서 실행하는 Process를 바꿔주면서 여러 프로세스를 동시에 실행하는 것 같은 효과를 냄.
  • Context Switching     : 무조건 싱글코어에서 적용!
      - Process가 종료되거나 Scheduling에 의해서 종료될 때 발생
    - 이전의 프로세스 상태를 저장하고 새로운 프로세스의 PCB를 가져오는 역할을 함
    - overhead가 심함
    - Process context switching의 과정
  • Tread
    - flow of control within a process(process와 subprocess로 이해할 수 있음)
    - 각각의 thread는 각자의 register state와 stack을 가지고 있다.
    - CPU scheduling의 기본 단위.
    - 하나의 process는 하나 이상의 thread를 가지고 있음. : 프로세스 내에서 실행 흐름을 담당하는 가장 작은 단위
    - process는 프로세스 간의 전환에 대하여 PCB에 접근해서 Process address space를 복사해오는 등의 과정 때문에 overhead가 클 수 밖에 없는데, Thread는 Process에 비해 creation과 switching에 드는 시간이 적다는 장점이 있다.(Memory와 CPU 효율성 면에서 모두 장점을 가짐)
    - 자신의 스택과 레지스터 상태를 별도로 가지고 있지만, 메모리 공간(코드, 데이터, 힙 등)은 프로세스 내 다른 스레드들과 공유
    - CPU 스케줄링의 기본 단위로서, 각 스레드가 CPU에서 실행될 때 CPU 레지스터스택 같은 정보가 스레드별로 유지되지만, 프로세스 간에 있는 데이터나 코드 영역을 공유하는 특징

          - Heap : 힙 영역은 동적 메모리 할당에 사용되는 공간
                    - global variable들이 저장되는 공간
                    - minheap, maxheap : minheapmaxheap은 힙 자료 구조의 일종으로, 최소값 또는 최대값을 빠르게 찾기 위한 방식 ( 메모리에서의 힙 영역과 자료 구조에서의 힙은 다른 개념 )
                    - 프로그램 실행 중에 동적으로 생성되는 전역 변수 또는 객체들이 저장되는 공간
          -  Stack : local variable들이 저장되는 공간 : 스택 영역은 함수 호출 시 생성되는 지역 변수들이 저장되는 공간
                   - 스레드가 각각의 스택을 독립적으로 가지는 이유는, 함수 호출과 관련된 지역 변수를 각각 관리하고 함수 호출의 흐름을 기록
          -  Static : 여러 process들이 함께 share하는 데이터가 저장되는 공간
               - 정적 영역은 전역 변수, 정적 변수처럼 프로그램 시작과 동시에 할당되고, 프로그램이 종료될 때까지 존재하는 데이터들이 저장
               - 공유할 수 있는 데이터가 저장되기도 하지만, 일반적으로 전역 변수를 다른 프로세스와 공유하지 않는 것이 원칙
          -  Code : 코드를 통해 실행될 instruction들이 저장되는 공간 (실제 machine instruction이 저장되는건 아니고 실제 코드와 machine instruction의 중간 형태로 저장됨)

  • multi-threading : 현대의 중요한 것 (인텔이 hyper-threading라는 걸 특허냄)
    - 하나의 process에 대해서 여러 thread가 만들어질 수 있고, 이 때 code와 address space, operating resources를 공유한다.
    - 멀티쓰레딩을 통해서 동시성을 추구한다.
        - 병렬성(parallelism): 여러 코어에서 동시에 process가 처리될 때
            - parallelism = num of CPUs(cores)
        - 동시성(concurrency): illusion of parallelism

    * hyper-threading에 대한 설명
     - 인텔(Intel)에서 개발한 기술로, 하나의 물리적 CPU 코어가 동시에 두 개의 스레드를 처리할 수 있게 해주는 기술입니다. 이를 통해 CPU 코어의 효율성을 극대화하고, 성능을 개선하는 것이 목적
     - Intel processor들중에 hyper-threading을 지원하는 프로세서들은 물리 코어의 2배를 논리코어로 정의해서, 실제 OS에서는 물리코어의 2배 코어를 "실제로" 가지고 있는걸로 인식하게 만드는 방법.
     - 실제로 물리코어는 4개이지만, hyper-threading이 적용된 프로세서는 8개의 코어를 가지는것처럼 일을 할 수 있으며 실제로 multi-threading을 적용하여 OS가 8개의 프로세서에다가 일 처리를 한것과 거의 비슷한 속도를 낼 수 있는 기술

    - Multi-processing: 두개 이상, 다수의 프로세서(처리장치, 프로세스 아님)가 협력적으로 작업을 동시에 처리하는 것
              - import os , os.cpu_counts()
## TO-DO : Matrix multiplication을 numpy로 구현한 다음, 
## 해당 연산을 4개의 core를 이용해서 multi-processing하는 코드를 작성

import numpy as np
import multiprocessing as mp

# 행렬 곱셈을 수행할 함수
def matrix_multiply_chunk(A_chunk, B, output, idx):
    output[idx] = np.dot(A_chunk, B)

# 행렬을 4개의 코어로 나누어 처리하는 함수
def parallel_matrix_multiply(A, B, num_cores=4):
    # 프로세스에 나눌 크기
    chunk_size = A.shape[0] // num_cores
    chunks = [A[i*chunk_size:(i+1)*chunk_size] for i in range(num_cores)]
    
    # 공유 메모리 배열 생성
    manager = mp.Manager()
    output = manager.dict()

    processes = []
    
    for idx, chunk in enumerate(chunks):
        p = mp.Process(target=matrix_multiply_chunk, args=(chunk, B, output, idx))
        processes.append(p)
        p.start()

    for p in processes:
        p.join()

    # 결과를 병합
    result = np.vstack([output[i] for i in range(num_cores)])
    return result

# 두 개의 랜덤 행렬 생성
A = np.random.rand(1000, 1000)
B = np.random.rand(1000, 1000)

# 멀티프로세싱을 사용한 행렬 곱셈
C = parallel_matrix_multiply(A, B, num_cores=4)
print("Parallel matrix multiplication result:\n", C)

 

Process Scheduling
  • Overview of process scheduling
    - 단일프로세서는 하나의 running process를 가질 수 있기 때문에 더 많은 process가 존재한다면 각각은 CPU에서 실행중인 process가 종료되거나 rescheduled 될 때가지 기다려야할 것이다. 이 때 필요한것이 process scheduling
    - Process Scheduling을 통해서 CPU 효율성을 최대화
    - Scheduling은 process의 상태가 바뀔 때 일어나고 처리할 process는 ready queue와 device queue에 저장되어 관리된다.
        - ready queue vs device queue(I/O wait queue)
            - Ready queue: set of all processes residing in main memory, ready and waiting do execute.
            - Device queue: set of processes waiting for an I/O device

  • Scheduling Criteria
    - 효율성을 판단할 때의 기준들
        - CPU utilization: CPU를 가능한 바쁜상태(일하고 있는 상태)로 유지하는가
        - Throughput: 일정한 단위 시간 동안 얼마나 많은 수의 프로세스가 완료되었는가
        - Turnaround time: 특정 프로세스를 실행하는데 걸리는 시간
        - Waiting time: ready queue에서 기다린 시간
        - Response time: process가 ready queue에서 기다리고 끝날때까지 걸린 시간.
        → CPU utilization과 Throughput을 최대화하고, turnaround time과 waiting time, response time을 최소화하는 것이 중요하다. : 반드시 암기하기

  • Scheduling algorithms
    - non-preemptive(비선점형): Process가 자원을 반납하기 전까지 다른 프로세스가 자원을 사용할 수 없음.
                - 수행시간이 긴 프로세스가 자원을 점유하게 되면 이후 실행되어야 하는 프로세스들이 자원을 할당받지 못하는 기아 현상이 발생.
                -  정해진 시간 없이process 종료 전까지 점유
                -  중간에 interupt가 일어나지 않음
                -  종료 후 context switch 외에 추가적인 오버헤드 없음
                -  프로세스 우선순위 고려 없음
                -  FCFS, SJF, Priority Scheduling

    - preemptive(선점형): Process가 한번 실행될 때 제한된 시간만을 할당해서 사용.
                - 프로세스의 우선순위에 따라 스케쥴링을 하게 되므로 우선순위가 낮은 프로세스는 기아 상태에 빠짐.
                -  일정 시간을 process에 할당해 해당 시간만 자원을 사용하고 반납
                -  interupt를 통해 실행 중인 process를 교체
                -  context switch 가 일정 시간마다 일어나기 때문에 오버헤드 있음
                -  프로세스에 대한 우선순위를 고려
                -  Round-Robin, Multilevel Queue Scheduling 

    1. FCFS(First Come, First Served) Scheduling
        - 가장 간단하고 직관적인 스케쥴링 알고리즘으로 그 구조가 Queue와 비슷하다.
        - 먼저 도착한 프로세스를 먼저 실행하고, 프로세스가 도착한 순서대로 CPU를 할당한다.
        - 보편적으로 프로세스들의 평균 대기 시간이 길어진다는 문제가 있다.

    2. SJF (Shortest Job First) Scheduling (Non-preemtive)
        - 다음에 실행할 프로세스를 선택할 때 실행 시간이 가장 짧을 것으로 예상되는 프로세스를 선택하는 방식.
        - ready queue에 프로세스를 새로 삽입할 때 CPU burst time이 가장 짧은 것을 다음 프로세스로 지정할 수 있도록 제일 앞에 삽입한다. : ready queue가 실행시간이 제일 짧은 걸 가장 앞으로. : (enqueue에 priority가 존재)
            -> CPU burst time을 기준으로 priority queue(minheap으로 구성) 를 ready queue로 구성하면 됨
        - 이 경우 FCFS보다 평균 대기 시간이 줄어들지만 CPU burst time이 긴 프로세스의 경우 오히려 대기시간이 증가하고 심할 경우 starvation 상태가 되는 문제점이 있다.
        - 비선점형 방식뿐만 아니라 선점형 방식으로 이용되기도 한다.

    3. Round Robin Scheduling Scheduling : (시험에 많이 나옴)
        - 각 프로세스에 차례로 일정한 시간 할당량(time quantum) 동안 CPU 자원을 차지할 수 있도록 함.
        - time quantum 시간이 길다면 FCFS와 같은 형태로 작동하므로 RR 스케줄링을 사용하는 의미가 줄어들고, 시간이 너무 짧다면 너무 많은 Overhead가 생기기 때문에 좋지 않다.
        - 따라서 적절한 time quantum 길이를 찾는 것이 중요함.

    예시 . Ready Queue: [P1, P2, P3, P4] , Burst Time: [3, 2, 8, 5], Time Quantum: 3 
    Q1.  위의 process들을 RR방식으로 실행시 execution order은?
     실행 순서 : P1 -> P2  -> P3  -> P4  -> P3  -> P4  -> P3
            - Round Robin (RR) 스케줄링 방식을 사용하여 프로세스들이 실행되는 순서를 구하는 문제
                 - RR 방식은 타임 퀀텀(일정 시간 간격) 동안 각 프로세스가 CPU를 할당받아 실행되며, 그 시간이 지나면 다음 프로세스로 넘어가는 방식
                 - 만약 프로세스가 할당된 타임 퀀텀 내에 끝나지 않으면, 남은 시간을 처리하기 위해 다시 대기열의 끝으로 이동
           -  각 프로세스가 타임 퀀텀(3) 동안 실행됩니다.
                         - P1은 3초 동안 실행되고, 남은 시간이 없으므로 완료됩니다.
                          -  P2는 2초 동안 실행되는데, 타임 퀀텀이 3초이므로 P2도 완료됩니다.
                          -  P3는 8초가 필요하지만 타임 퀀텀은 3초이므로, 3초 동안 실행되고 5초가 남습니다.
                          -  P4는 5초가 필요하지만 3초만 실행되고, 2초가 남습니다.
                          - P1과 P2는 이미 완료되었기 때문에 다시 실행하지 않습니다. 남은 P3와 P4가 다시 실행됩니다.
                          -  P3는 남은 5초 중 3초 동안 실행되고, 남은 시간은 2초입니다.
                          -  P4는 남은 2초 동안 실행되어 완료됩니다.
                          -   이제 남은 프로세스는 P3뿐입니다. P3의 남은 2초를 실행하여 완료됩니다

    Q2. 각 프로세스별 waiting time을 계산하라
        P1 : 0 
           - P1은 처음으로 실행되었기 때문에 0입니다.
        P2 : 3
           - P2는 첫 번째 라운드에서 P1이 끝난 후에 바로 실행되었으므로 3초 기다렸습니다.
        P3 : 3+2+3+2
            - 첫 번째 라운드에서 P1(3초) + P2(3초)만큼 기다림 → 6초
            - 두 번째 라운드에서 P4가 끝날 때까지 2초 더 대기 (P4의 남은 2초)
            - 마지막 라운드에서 다시 실행되기 전에 3초 추가 대기 (P3 두 번째 실행 후 P4가 남은 작업을 완료)
        P4 : 3+3+3+2
            - 첫 번째 라운드에서 P1, P2, P3가 끝날 때까지 9초 대기 (P1 3초 + P2 3초 + P3 3초)
            - 두 번째 라운드에서 다시 실행되기 전 2초 대기 (P3가 두 번째 실행 후)

    -> average waiting time = (0+3+10+11) / 4 = 6

    Q3. SJF scheduling로 했을 때, average waiting time을 계산해보세요.
        - SJF(Shortest Job First) 스케줄링 : 가장 짧은 실행 시간을 가진 프로세스부터 실행
       - SJF 스케줄링에 따른 실행 순서 : P2 (2) -> P1 (3) -> P4(5) -> P3 (8)
      각 프로세스별 Waiting Time 계산
        P1 : 2
           - P2가 끝난 후 실행되므로 대기 시간은 P2의 Burst Time만큼 기다림
        P2 : 0 
           - P2는 처음 실행되므로 대기 시간이 0초
        P3 : 2+3
           -  P2와 P1이 끝난 후 실행되므로 대기 시간은 P2와 P1의 Burst Time을 더한 값
        P4 : 2+3+5
           - P2, P1, P4가 끝난 후 실행되므로 대기 시간은 P2, P1, P4의 Burst Time을 모두 더한 값
    -> Average Waiting Time = 0+2+5+10 / 4 =  4.25

Memory Management
  • Overview of memory management
    - Memory : 메인 메모리 RAM(Random Access Memory)
                      - 프로그램 실행 시 필요한 주소, 정보들을 저장하고 가져다 사용할 수 있게 만드는 공간.
    - 모든 프로그램은 메모리에 올라가서 실행되고 메모리 관리가 제대로 이루어지지 않으면 시스템 성능이 저하될 수 있기 때문에 효율적인 메모리 관리가 필수적.
    - Address binding과 MMU
        - Physical address vs. Logical address
            - Physical address(물리적 주소)는 프로세스가 실행되면서 메모리 내부에 실제로 프로세스가 위치해 있는 주소를 의미
            - 프로그램을 컴파일(실행하기 위한 사전 작업 수행)할 때 이러한 주소를 할당하게 되는데 이 때 물리적 주소를 이용
            - 단점 :  물리적 주소의 경우 항상 그 주소가 비어있을것이라는 보장이 없음
                         이미 메모리에 프로그램이 올라가 있으면 문제가 발생
            - 이를 해결하기 위해서 나온 것이 Logical address(논리적 주소)
            - 논리적 주소는 가상 주소라고도 불리며 물리적 주소와 논리적 주소를 잘 매핑하는 것이 중요함
        - 논리적 주소에 데이터를 저장해둔 뒤 데이터를 메모리에 로딩할 때나 프로세스를 실행할 때 물리적 주소에 직접 매핑하는데 이를 Address binding
        - 이러한 매핑은 MMU(Memory Management Unit) 에서 수행하며, 보통 물리적 주소가 시작하는 base 주소를 논리적 주소에 더해서 데이터를 메모리에 올린다.
        - 데이터를 메모리에 로딩할 때 논리 주소를 물리 주소에 매핑하는 방식을 Load time binding이라고 하는데 이 방식은 overhead가 너무 심해 요즘에는 잘 쓰이지 않고, 프로세스를 실행할 때 데이터를 메모리에 올리는 Execution time binding 방식이 주로 쓰인다.

    요약
        -  Physical Address: 실제 메모리에서 프로세스가 위치한 주소.
        -  Logical Address: 가상 주소로, 물리적 주소로 변환되어 사용됨.
        -  Address Binding: 논리적 주소를 물리적 주소로 매핑하는 과정.
        -  MMU(Memory Management Unit): 이 주소 변환을 담당하는 하드웨어.
        -  Load Time Binding: 프로그램 로드 시점에 주소를 바인딩하는 방식 (현재는 잘 사용되지 않음).
        -  Execution Time Binding: 실행 시점에 주소를 바인딩하는 방식 (현재 널리 사용됨).

  • Contiguous memory allocation : logical address가 연속적이라면 physical address도 연속적으로 배치하는 것을 의미.
        - 이 경우 MMU가 실행 시간 바인딩에서 해야하는 연산이 적다는 장점.
        - 또한 Memory Protection의 구현이 쉬움
            - Memory Protection : 시스템에서 참고하는 메모리 주소가 참고 가능한 범위를 넘어서는지를 체크하는 것.

      - 연속 메모리 할당 방식에서 메모리 공간을 분배하는 방법에는 여러 방법이 있음
            - Two Partition Allocation: Kernel과 User 모드 두 부분으로 메모리를 분할하여 활동하는 방식
                                        메모리 공간이 두 개의 파티션으로 분할되기 때문에, 메모리 공간의 낭비가 발생할 수 있음.
            - Multiple Partition Allocation
                - Fixed Size Partition: 메모리 공간을 고정 크기로 나누어 사용하는 메모리 관리 방식. 
                                  파티션마다 고정된 크기의 메모리 공간을 할당하므로 간단하고 빠르게 동작.
                                    그러나 프로세스가 필요로 하는 메모리 공간의 크기에 따라 파티션을 선택할 수 없어서
                                                       내부 단편화가 발생할 가능성이 높음.
                - Variable-size Partition: 메모리 공간을 프로세스의 요구에 따라 가변적으로 할당하는 메모리 관리 방식. 
                    - 프로세스의 크기에 따라 최적의 메모리 공간을 할당할 수 있으므로 내부 단편화 문제를 완화시킬 수 있으나
                    - 파티션의 크기가 자주 변하기 때문에 메모리 할당 및 해제 과정이 복잡해지고,
                    - 외부 단편화 문제가 발생할 가능성이 높음.
        - 이처럼 연속 메모리 할당 방식에서는 단편화(fragmentation) 의 문제가 발생하게 된다는 큰 문제가 있어 잘 쓰이지 않음
            - 외부 단편화: 메모리 내에 충분한 크기의 공간이 있더라도 연속적인 공간이 부족하여 메모리 할당이 불가능한 경우
            - 내부 단편화: 메모리 공간을 할당할 때, 필요한 공간보다 큰 크기의 공간을 할당하여 할당된 메모리에 사용하지 못하는 부분이 발생하는 경우