Post

Operating System

01. 운영체제 (Operating System)

운영체제는 컴퓨터 하드웨어와 소프트웨어 간의 중재자 역할을 수행하며, 사용자와 시스템 간의 상호작용을 관리하고 시스템 자원(System Resources)을 효율적으로 할당하는 소프트웨어.

  • RTOS (Real-Time Operating System): 특정 응용 프로그램의 실시간 성능을 보장, 정확한 응답 시간예측 가능한 실행 시점을 제공합니다. 주로 임베디드 시스템, 산업 제어 등에서 사용.

  • GPOS (General-Purpose Operating System): 응용 프로그램의 실행 시간이 엄격하지 않은 운영체제로, 다양한 사용자 작업범용 응용 프로그램에 적합. 예: Windows, Linux.

역할

  • 자원 관리 (Resource Management): CPU, 메모리, 입출력 장치 등 하드웨어 자원의 효율적 사용 및 할당.
  • 프로세스 관리 (Process Management): 프로세스 생성, 스케줄링, 종료 및 동기화.
  • 파일 시스템 관리 (File System Management): 파일 저장, 접근, 보호.
  • 사용자 인터페이스 제공 (User Interface Provision): 사용자와 시스템 간의 상호작용 창구 제공 (CLI, GUI).
  • 보안 및 보호 (Security and Protection): 사용자 데이터 및 시스템 자원의 무결성과 보안을 유지.

구성 요소

  • 커널 (Kernel): 운영체제의 핵심으로, 하드웨어와 직접 상호작용하며 자원 관리 및 기본 서비스 제공.
    • 기능: 프로세스 관리, 메모리 관리, 파일 시스템 관리, 장치 드라이버 관리, 시스템 호출 관리 등.
  • 사용자 인터페이스 (User Interface): 사용자가 시스템과 상호작용하는 방식을 제공.
    • 종류:
      • CLI (Command-Line Interface): 텍스트 명령어를 통해 시스템과 상호작용.
      • GUI (Graphical User Interface): 그래픽 요소를 통해 사용자의 상호작용을 돕는 시각적 인터페이스.
  • 시스템 라이브러리 (System Libraries): 응용 프로그램이 커널 기능을 이용할 수 있도록 돕는 표준 함수 모음.
    • : C 표준 라이브러리 (libc), 네트워크 통신 라이브러리 등.
  • 시스템 유틸리티 (System Utilities): 시스템 유지 관리, 설정, 성능 모니터링 등 다양한 관리 기능을 제공하는 도구.
    • : 디스크 정리, 백업 도구, 성능 모니터링 유틸리티 등.

System Call

  • 정의: System Call은 운영체제 커널이 제공하는 기능을 애플리케이션에서 사용할 수 있게 하는 프로그래밍 인터페이스. 애플리케이션은 시스템 콜을 통해 하드웨어 자원(예: 파일 시스템, 네트워크, 메모리)에 접근하거나 관리할 수 있다.
  • 기능:
    • 프로세스 관리: 프로세스 생성, 실행, 종료 (fork(), exec(), exit()).
    • 파일 조작: 파일 열기, 읽기, 쓰기, 닫기 (open(), read(), write(), close()).
    • 메모리 관리: 메모리 할당, 해제 (mmap(), munmap(), brk()).
    • 디바이스 통신: 하드웨어 장치와의 상호작용 (ioctl()).
    • 통신: 프로세스 간 통신 (pipe(), socket()).

    • Windows 계열: CreateProcess(), ReadFile(), WriteFile(), CreateFile().

운영체제를 만든다면

  1. 운영체제 개발 (kernel): 운영체제의 핵심 부분을 개발. 이는 하드웨어 자원을 관리하고 프로세스 스케줄링, 메모리 관리 등의 기능을 수행.

  2. 시스템 콜 개발: 운영체제 커널이 제공하는 시스템 콜 인터페이스를 설계하고 개발. 이는 사용자 공간의 프로그램이 커널 공간의 기능에 접근할 수 있는 방법을 정의.

  3. 프로그래밍 언어별 라이브러리 개발 (API): 각 프로그래밍 언어별로 운영체제 기능에 접근할 수 있도록 표준화된 API를 제공하는 라이브러리를 개발.

  4. 지원되는 프로그래밍 언어로 Shell 프로그램 개발: 사용자가 운영체제와 상호작용할 수 있는 쉘 프로그램을 개발. 쉘은 CLI(Command Line Interface) 또는 GUI(Graphical User Interface) 형태일 수 있으며, 사용자의 명령을 해석하고 시스템 콜을 호출하여 결과를 반환.

  5. 지원되는 프로그래밍 언어로 응용 프로그램 개발: 다양한 응용 프로그램을 개발하여 사용자가 운영체제를 통해 작업을 수행할 수 있도록 함. 이 과정에서는 API를 통해 운영체제의 기능을 이용하게 된다.

02. 커널 모드(Kernel Mode)

모드

  1. 사용자 모드 (User Mode):
    • 일반적인 응용 프로그램이 실행되는 모드.
    • 사용자 모드에서는 제한된 시스템 리소스에만 접근할 수 있다.
    • 예를 들어, 일반적인 파일 읽기/쓰기, 네트워크 통신 등이 가능.
  2. 커널 모드 (Kernel Mode):
    • 운영체제 커널이 실행되는 모드로, 높은 권한을 가진다.
    • 커널 모드에서는 시스템의 모든 리소스에 접근할 수 있다.
    • 예를 들어, 하드웨어 제어, 메모리 관리, 인터럽트 처리 등이 가능.

가상 메모리와 커널 영역

  • 가상 메모리 (Virtual Memory):
    • 프로세스가 사용할 수 있는 메모리 공간을 가상으로 제공.
    • 각 프로세스는 자신만의 가상 주소 공간을 가지며, 이는 실제 물리적 메모리에 매핑.
    • 보통 32-bit 시스템에서는 4GB(2^32 바이트)의 가상 주소 공간을 제공.
  • 커널 공간 (Kernel Space):
    • 운영체제의 핵심 부분이 실행되는 메모리 영역.
    • 커널 공간은 모든 프로세스에게 동일하게 매핑되어, 운영체제가 제공하는 서비스와 자원에 접근할 수 있도록 한다.
    • 커널 코드, 데이터 및 프로세스 제어 블록(PCB)과 같은 구조체들이 위치.
    • 이 영역은 보안 및 안정성을 위해 사용자 공간과 분리되어 있다.
  • 사용자 공간 (User Space):
    • 일반 응용 프로그램이 실행되는 메모리 영역.
    • 프로세스의 실행 코드, 데이터, 스택 등이 위치하는 메모리 영역.
    • 사용자 프로세스는 이 공간에서 작업을 수행하며, 운영체제의 서비스가 필요할 때는 시스템 콜을 통해 커널 모드로 전환.

32-bit 시스템에서 프로세스가 4GB를 할당받는데, 사용자 공간(User Space)의 메모리 할당을 의미. 이 4GB는 프로세스가 직접 접근하여 사용할 수 있는 가상 메모리 공간. 하지만 이 가상 메모리 공간 내에서 일부 영역은 커널 공간(Kernel Space)과 매핑되어 있다.

03. 프로세스(Process)와 스케줄링(Scheduling)

프로세스(Process)

프로세스는 실행 중인 프로그램으로, CPU가 메모리에 적재하여 실행하는 프로그램. 32비트 시스템에서 각 프로세스는 최대 4GB의 가상 주소 공간을 가질 수 있다. 이 공간은 일반적으로 사용자 공간과 커널 공간으로 나뉜다.

  • User Space 구조:
    • 가상 주소 공간의 하위 부분 (예: 0 ~ 3GB)은 사용자 공간으로 할당
    • 텍스트 영역 (Text Segment): 실행할 프로그램 코드가 저장된 영역.
    • 데이터 영역 (Data Segment): 전역 변수 및 정적 변수와 초기화된 데이터가 저장된 영역.
    • 스택 영역 (Stack Segment): 함수 호출 시 생성되는 프레임, 지역 변수, 함수 인자, 반환 주소 등이 저장되는 영역.
    • 힙 영역 (Heap Segment): 동적 메모리 할당에 사용되는 영역으로, 프로세스가 실행 중에 필요에 따라 메모리를 할당하거나 해제하는 영역.
  • Kernel space:
    • 가상 주소 공간의 상위 부분 (예: 3GB ~ 4GB)은 커널 공간으로 예약된다.
    • 이 부분은 모든 프로세스가 동일한 커널 코드를 공유하도록 설정.
    • 커널 공간에는 운영 체제의 커널 코드, 커널 데이터 구조, 디바이스 드라이버 등이 포함.
  • 상태:
    • 생성 (New): 프로세스가 생성되는 중.
    • 준비 (Ready): CPU 할당을 기다림.
    • 실행 (Running): CPU에서 실행 중.
    • 대기 (Waiting/Blocked): 특정 이벤트나 자원을 기다림.
    • 종료 (Terminated): 프로세스 실행 종료.

스케줄링 (Scheduling)

정의: CPU 자원을 여러 프로세스에 효율적으로 분배하기 위해 프로세스의 실행 순서를 결정하는 작업.

스케줄링 기법의 분류
  • 배치 처리 (Batch Processing): 여러 작업을 순차적으로 처리하는 방식.
  • 시분할 (Time-Sharing): 다중 사용자를 지원하여 응답 시간을 최소화하는 시스템.
  • 멀티태스킹 (Multitasking): 여러 프로세스가 동시에 실행되는 것처럼 보이게 하는 방식으로, CPU가 여러 작업을 빠르게 교대 실행.
  • 멀티프로세싱 (Multiprocessing): 여러 CPU를 사용하여 하나 또는 여러 프로그램을 병렬로 실행하는 방식.
  • 멀티프로그래밍 (Multiprogramming): CPU 활용을 극대화하기 위해 여러 프로그램이 메모리에 상주하며 실행을 기다리는 시스템.
스케줄링 종류
  • 비선점형 스케줄링 (Non-Preemptive Scheduling): 프로세스가 자발적으로 CPU를 반납할 때까지 실행.
    • FIFO (First In, First Out): 도착한 순서대로 작업을 처리하는 방식으로, 단순하고 비선점형이며 주로 배치 처리에 사용.
    • FCFS (First-Come, First-Served): 도착한 순서대로 CPU를 할당하는 방식으로, FIFO와 유사하지만 더 넓은 상호작용 시스템에 적용.
    • SJF (Shortest Job First): 가장 짧은 작업을 먼저 처리하는 방식으로, 효율적이지만 긴 작업이 기아 상태에 빠질 수 있다.
  • 선점형 스케줄링 (Preemptive Scheduling): 운영체제가 프로세스를 중단하고 다른 프로세스에게 CPU를 할당.
    • 우선순위 스케줄링 (Priority Scheduling): 각 프로세스에게 우선순위를 부여하여 높은 우선순위를 가진 프로세스에게 CPU를 먼저 할당하는 방식.
    • ROUND ROBIN (라운드 로빈): 각 프로세스에게 동일한 시간 할당량을 주고 순환하며 CPU를 할당하는 방식으로, 공정성을 강조하며 주로 시분할 시스템에 사용.

컨텍스트 스위칭 (Context Switching)

정의: 컨텍스트 스위칭은 CPU가 실행할 프로세스를 교체하는 기술입니다. 현재 실행 중인 프로세스의 상태를 저장하고, 새롭게 실행할 프로세스의 상태를 복원하여 CPU에 할당하는 과정입니다.

간단한 과정:

  1. 현재 프로세스의 상태 저장: 현재 실행 중인 프로세스의 PCB(Process Control Block)에 레지스터, 프로그램 카운터, 그리고 기타 CPU 상태 정보를 저장합니다.
  2. 새 프로세스 상태 로드: 실행할 새 프로세스의 PCB에서 저장된 상태 정보를 복원하여 CPU 레지스터와 프로그램 카운터에 로드합니다.
  3. CPU 제어권 전달: 새 프로세스가 실행을 시작합니다.

PCB (프로세스 제어 블록):

  • 역할: 각 프로세스의 상태 정보를 저장하는 데이터 구조체입니다. 컨텍스트 스위칭 시, PCB를 이용해 프로세스의 현재 상태를 저장하고 복원합니다.
  • 내용: PCB에는 프로세스의 식별자(PID), 레지스터 상태, 프로그램 카운터, 메모리 관리 정보, 스케줄링 정보 등이 포함됩니다.

프로세스 간 커뮤니케이션 (Inter-Process Communication, IPC)

프로세스 간 커뮤니케이션은 서로 독립적으로 실행되며 분리된 공간에 있는 프로세스들이 정보를 교환하는 방법.

IPC (Inter-Process Communication) 기법은 여러 프로세스가 데이터를 주고받기 위해 사용하는 다양한 방법. 대부분의 기법은 커널 공간을 활용하여 통신을 중개. 주요 IPC 기법은 다음과 같다:

  • 메시지 전달 (Message Passing): 프로세스 간에 메시지를 보내고 받는 방식. 큐(queue)나 포트(port)를 통해 메시지를 전달하며, 메시지 큐와 신호를 사용해 프로세스 간 동기화도 가능.

  • 공유 메모리 (Shared Memory): 프로세스들이 공통된 메모리 영역을 공유하여 데이터를 읽고 쓰는 방식. 속도가 빠르지만, 동기화 문제가 발생할 수 있어 세마포어(semaphore)나 뮤텍스(mutex) 같은 동기화 도구가 필요.

  • 파이프 (Pipes): 한 프로세스의 출력이 다른 프로세스의 입력이 되는 통로를 형성하는 방식. 주로 부모-자식 프로세스 간의 데이터 전송에 사용되며, 익명 파이프(Anonymous Pipe)와 명명된 파이프(Named Pipe)가 있다.

  • 소켓 (Sockets): 네트워크를 통해 프로세스 간 통신을 가능하게 하는 방식. 주로 네트워크 기반 애플리케이션에서 사용되며, 로컬 시스템 내 통신을 위한 유닉스 도메인 소켓(Unix Domain Sockets)도 포함.

  • 메모리 매핑 (Memory-Mapped Files): 파일을 메모리에 매핑하여, 파일을 공유 메모리처럼 사용하는 방식. 프로세스들은 동일한 메모리 맵핑을 사용하여 파일의 내용을 공유하고, 이를 통해 효율적으로 데이터를 교환할 수 있다.

04. 스레드 (Thread)

스레드(Thread)는 프로세스 내에서 실행되는 일련의 실행 흐름. 여러 스레드가 하나의 프로세스 내에서 공유된 자원을 동시에 접근하면서 병렬로 실행될 수 있다.

특징:

  • 경량 프로세스 (Lightweight Process)라고도 불린다.
  • 하나의 프로세스 내에서 여러 개의 스레드를 생성할 수 있다.
  • 스레드들은 동시에 실행될 수 있으며, 프로세스는 각기 자신만의 주소영역을 가지는 것과 달리 스레드는 프로세스의 주소 공간과 자원을 공유.
  • 스레드는 프로세스의 코드, 데이터, 파일 등에 대해 직접 접근할 수 있다.
  • 프로세스 간에는 IPC 기법으로 통신해야하는데 반해 스레드는 빌요 없음.

멀티스레드:

  • 프로세스 내에서 여러 스레드가 동시에 실행되는 것을 말함.
  • 멀티스레드는 병렬성을 활용하여 프로세스의 성능을 향상시킬 수 있다.
  • 각 스레드는 독립적인 실행 흐름을 가지며, 스레드 간의 데이터 공유와 동기화에 유의.
  • 한 프로세스 내부에 스레드 중 한 스레드만 문제가 있어도 프로세스 전반에 영향 줌.(해당 프로세스의 모든 스레드와 같이)

동기화(Synchronization) 이슈

멀티스레드 환경에서 동기화는 여러 스레드가 공유 자원에 접근하거나 데이터를 조작할 때, 그 접근이 일관되고 안전하게 이루어지도록 하는 것을 의미. 동기화 이슈는 다음과 같은 형태로 나타날 수 있다:

  1. 경쟁 조건(Race Condition)

    여러 스레드가 동시에 공유 자원에 접근할 때, 그 결과가 스레드의 실행 순서에 따라 달라지는 상황을 말한다. 이로 인해 예상치 못한 결과가 발생하거나, 데이터 무결성이 손상될 수 있다. 예를 들어, 두 개의 스레드가 동시에 같은 변수의 값을 갱신하려고 할 때, 한 스레드의 작업이 완료되기 전에 다른 스레드가 작업을 시작하면 잘못된 데이터가 저장 됨.

    1
    2
    3
    4
    5
    6
    7
    8
    
    int counter = 0;
    
    void *increment_counter(void *arg) {
        for (int i = 0; i < 1000000; i++) {
            counter++; // Race condition 발생 가능
        }
        return NULL;
    }
    
  2. 교착상태(Deadlock)

    교착상태는 두 개 이상의 스레드가 서로가 가지고 있는 자원을 기다리면서 무한정 대기하는 상태를 말한다. 각 스레드가 다른 스레드의 자원에 접근하려고 시도할 때 발생하며, 이러한 교착 상태에 빠지면 프로그램은 진행되지 못함.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    pthread_mutex_t lock1, lock2;
    
    void *thread1(void *arg) {
        pthread_mutex_lock(&lock1);
        pthread_mutex_lock(&lock2);
        // 자원 사용
        pthread_mutex_unlock(&lock2);
        pthread_mutex_unlock(&lock1);
        return NULL;
    }
    
    void *thread2(void *arg) {
        pthread_mutex_lock(&lock2);
        pthread_mutex_lock(&lock1);
        // 자원 사용
        pthread_mutex_unlock(&lock1);
        pthread_mutex_unlock(&lock2);
        return NULL;
    }
    
  3. 기아 상태(Starvation) 기아 상태는 특정 스레드가 자원에 접근할 기회를 계속 박탈당해, 자신의 작업을 진행할 수 없는 상태. 자원 접근이 우선순위가 높은 스레드에게 지속적으로 할당되는 경우, 우선순위가 낮은 스레드가 무한정 대기.

  4. 라이브락(Livelock) 라이브락은 스레드들이 서로의 진행을 방해하며, 계속해서 자원 사용을 시도하지만 실제로 아무 작업도 하지 못하는 상태. 데드락과 유사하지만, 자원이 계속해서 변화하면서도 해결되지 않는 상황.

동기화(Synchronization)

Mutual exclusion (상호 배제)
여러 스레드가 접촉하는 임계 자원(Critical resource)에 Exclusive Access 설정.
  1. 뮤텍스(Mutex)
    뮤텍스는 상호 배제를 통해 동기화 문제를 해결. 단일 스레드만이 임계 구역(Critical Section)에 들어갈 수 있도록 보장하며, 다른 스레드는 해당 뮤텍스가 해제될 때까지 대기한다. 이는 경쟁 조건을 방지하는 데 유용.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    pthread_mutex_t lock;
    
    void *increment_counter(void *arg) {
        for (int i = 0; i < 1000000; i++) {
            pthread_mutex_lock(&lock);
            counter++; // 뮤텍스로 보호된 코드
            pthread_mutex_unlock(&lock);
        }
        return NULL;
    }
    
  2. 세마포어(Semaphore)

    세마포어는 주어진 수의 스레드가 자원에 접근할 수 있도록 허용. 이를 통해 제한된 자원에 대한 접근을 동기화할 수 있다. 세마포어는 일반적으로 초기화된 값에서 접근할 수 있는 최대 스레드 수를 설정. 즉, Mutex는 임계구역에 하나의 스레드만 들어가게 하고, Semaphore는 임계구역에 설정한 수의 스레드만 들어가게 함.

    1
    2
    3
    4
    5
    6
    7
    8
    
    sem_t semaphore;
    
    void *thread_function(void *arg) {
        sem_wait(&semaphore); // 세마포어 획득
        // 공유 자원 접근
        sem_post(&semaphore); // 세마포어 해제
        return NULL;
    }
    
  3. 데드락 회피 및 해결

    데드락을 피하기 위해 자원 할당 순서를 정하거나, 타임아웃을 설정할 수 있습니다. 또한, 데드락이 발생한 경우 이를 감지하고 적절히 해결하는 방법도 있습니다. 자원을 정해진 순서로 요청하여 데드락을 예방할 수 있으며, 타임아웃을 통해 일정 시간이 지나면 자원 요청을 포기하도록 할 수 있습니다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    pthread_mutex_t lock1, lock2;
    
    void *thread1(void *arg) {
        pthread_mutex_lock(&lock1);
        if (pthread_mutex_trylock(&lock2) == 0) {
            // 자원 사용
            pthread_mutex_unlock(&lock2);
        }
        pthread_mutex_unlock(&lock1);
        return NULL;
    }
    
    void *thread2(void *arg) {
        pthread_mutex_lock(&lock2);
        if (pthread_mutex_trylock(&lock1) == 0) {
            // 자원 사용
            pthread_mutex_unlock(&lock1);
        }
        pthread_mutex_unlock(&lock2);
        return NULL;
    }
    

05. 가상 메모리(Virtual Memory)와 페이징

가상 메모리는 실제 물리적 메모리보다 더 많은 메모리를 사용할 수 있게 하는 기술. 이를 통해 프로그램들은 물리 메모리의 제약 없이 동작.

  • 가상 주소와 물리 주소
    프로세스는 가상 주소를 사용하여 메모리에 접근하며, MMU(Memory Management Unit)가 이를 물리 주소로 변환한다. 실제 데이터 접근은 이 변환을 통해 이루어짐.

페이징 시스템(Paging System)

  • 페이지(Page): 가상 메모리의 고정 크기 블록. 일반적으로 페이지의 크기는 4KB로 설정.

  • 프레임(Frame): 물리 메모리의 고정 크기 블록으로, 각 페이지는 하나의 프레임에 매핑됨.

  • 페이지 테이블(Page Table): 각 가상 페이지가 실제 물리 메모리의 어느 프레임에 매핑되는지를 기록. 각 페이지의 첫 번째 물리 주소 정보를 저장. 각 프로세스는 PCB에서 자신만의 페이지 테이블을 가지며, CPU가 가상 주소 접근 시, MMU는 페이지 테이블을 참조하여 가상 주소를 물리 주소로 변환.

  • 페이지 번호(Page Number): 가상 메모리에서 각 페이지를 식별하는 번호다. 페이지 번호는 페이지 테이블의 인덱스 역할을 한다.

  • 변위(Offset): 페이지 내에서 실제 데이터에 접근하기 위한 위치를 나타내는 값. 페이지 크기로 나눈 나머지로 계산된다. 페이지 처음부분부터 떨어진 크기.

페이지 테이블을 통한 가상 주소 접근

  1. 프로세스 컨텍스트 스위칭과 페이지 테이블 업데이트 :
    프로세스 컨텍스트 스위칭 시, CPU는 다음 실행할 프로세스의 PCB 정보로 레지스터들(PC, SP 등)을 업데이트한다. 이 과정에서 페이지 테이블의 base 주소를 저장하는 레지스터 CR3도 갱신되어 다음 프로세스의 메모리 매핑 정보를 로드.

  2. 가상 주소 접근과 MMU 동작 :
    CPU가 가상 주소 V = (P:페이지 번호, d:변위)에 접근하면, MMU는 CR3 레지스터에 있는 페이지 테이블의 base 주소를 참조하여 해당 프로세스의 페이지 테이블을 가져온다.

  3. 페이지 테이블 조회 및 물리 주소 변환 :
    MMU는 가상 주소의 페이지 번호 P를 사용하여 페이지 테이블에서 해당 페이지 엔트리를 찾는다. 페이지 테이블 엔트리에는 페이지가 매핑된 물리 메모리의 프레임 번호 P’와 오프셋 d 정보가 저장되어 있다. MMU는 이 정보를 결합하여 최종적인 물리 주소 P’ + d를 생성.

  4. 메모리 접근 :
    생성된 물리 주소 P’ + d를 사용하여 프로세스는 물리 메모리에 있는 데이터에 접근하거나 수정할 수 있다.

  5. 페이지 부재 (Page Fault) :
    프로세스가 필요로 하는 페이지가 물리 메모리에 없는 경우, 페이지 부재가 발생. 운영 체제는 해당 페이지를 디스크에서 메모리로 가져오는 페이지 교체 알고리즘을 실행.

페이지 교체

페이징 시스템에서 물리 메모리가 부족할 때 페이지 교체 알고리즘을 통해 페이지를 디스크로 내보내고 새로운 페이지를 불러온다. 주요 페이지 교체 알고리즘으로는 LRU(Least Recently Used), FIFO(First In First Out), LFU(Least Frequently Used) 등이 있다. 이러한 알고리즘은 페이지 테이블을 통해 관리되며, 메모리 관리의 효율성을 높이는 데 중요한 역할을 한다.

TLB (Translation Lookaside Buffer)

TLB는 페이지 테이블의 페이지 번호와 해당 물리 메모리 프레임 번호 간의 매핑 정보를 캐시하는 고속 메모리. TLB는 가상 주소를 물리 주소로 변환하는 속도를 높이기 위해 사용.

동작 원리

  1. TLB 조회: CPU가 가상 주소에 접근할 때, 먼저 TLB에서 해당 가상 주소의 페이지 번호를 검색.
  2. TLB 히트: 페이지 번호가 TLB에 존재하면, 물리 주소 변환이 즉시 이루어진다.
  3. TLB 미스: 페이지 번호가 TLB에 없으면, 페이지 테이블을 조회하여 변환 정보를 얻고 TLB에 캐시.
  4. 페이지 테이블 조회: TLB 미스 시, MMU는 페이지 테이블에서 매핑 정보를 가져와 물리 주소를 생성.

페이징 시스템과 공유 메모리(IPC)

페이징 시스템에서 프로세스 간의 통신(IPC)을 위해 공유 메모리를 사용하면, 두 프로세스가 동일한 물리 주소를 가리키도록 설정할 수 있다. 이는 주로 fork() 시스템 호출을 통해 자식 프로세스를 생성할 때 이루어진다.

동작 원리

  1. fork() 시스템 호출:
    • fork() 호출 시, 자식 프로세스가 생성되며 부모 프로세스의 주소 공간을 복사합니다. 이때, 페이지 테이블의 엔트리들도 복사되어 초기에는 동일한 물리 메모리를 가리킨다.
    • 부모와 자식 프로세스는 페이지 테이블에서 동일한 물리 페이지를 가리키므로, 메모리 낭비를 줄이고 데이터 일관성을 유지할 수 있다.
  2. 공유 메모리 설정:
    • IPC를 위해 특정 페이지를 공유 메모리로 설정할 수 있습니다. 부모와 자식 프로세스의 페이지 테이블 엔트리에서 동일한 물리 주소를 가리키도록 조정.
    • 예를 들어, 부모와 자식 프로세스의 가상 주소 V = (P, d)와 P’ + d는 동일한 물리 메모리 P’를 가리키도록 함.
  3. 메모리 접근:
    • 두 프로세스는 자신들의 가상 주소 공간을 통해 동일한 물리 메모리에 접근하여 데이터를 읽거나 쓸 수 있다.

06. 인터럽트와 페이지 폴트

인터럽트는 CPU의 현재 작업을 중단하고, 사전에 정의된 인터럽트 처리 루틴(Handler)을 실행하도록 하는 신호.

  • 사용자 모드와 커널 모드 전환: 인터럽트가 발생하면 CPU는 사용자 모드에서 커널 모드로 전환하여 인터럽트 처리 루틴을 실행.
  • 타이머 인터럽트: 주기적으로 발생하여 시스템의 시간을 관리하거나 프로세스 스케줄링을 수행.
  • 인터럽트 벡터 테이블(IDT): 각각의 인터럽트는 미리 정의된 번호와 실행 코드를 가리키는 주소가 기록된 테이블에 의해 관리. 컴퓨터가 부팅될 때 운영 체제는 IDT를 설정.

인터럽트 처리 과정

  1. 인터럽트 발생: 하드웨어나 소프트웨어 이벤트가 인터럽트를 발생.
  2. 현재 작업 중단: CPU는 현재 실행 중인 작업을 중단.
  3. IDT: CPU는 IDT를 확인하여 해당 인터럽트의 처리 루틴 주소를 찾는다.
  4. 인터럽트 처리 루틴 실행: CPU는 인터럽트 처리 루틴을 실행하여 커널 모드에서 필요한 작업을 수행.
  5. 작업 재개: 인터럽트 처리 루틴이 완료되면 CPU는 중단된 작업을 재개.

인터럽트 처리 예시: 시스템 콜 인터럽트

  1. 인터럽트 발생 시 IDT 확인: 인터럽트가 발생하면 CPU는 IDT를 참조하여 해당 인터럽트의 처리 루틴을 찾는다.
  2. 시스템 콜 인터럽트 (0x80): 예를 들어, 시스템 콜 인터럽트는 0x80 번호로 정의.
  3. 인터럽트 처리 루틴: IDT에서 0x80에 해당하는 system_call() 함수를 실행한다.

페이지 폴트

페이지 폴트는 프로세스가 접근하려는 메모리 페이지가 실제 물리적 메모리에 없는 경우 발생하는 인터럽트.

  • 작동 원리:
    • CPU가 메모리 관리 장치(MMU)를 통해 프로세스의 가상 주소를 물리적 주소로 변환할 때, 해당 페이지가 물리적 메모리에 없는 경우 페이지 폴트가 발생.
    • 운영 체제는 페이지 폴트를 처리하기 위해 다음 작업을 수행:
      1. 페이지 테이블을 확인하여 요청된 페이지의 현재 상태를 확인합니다.
      2. 해당 페이지가 디스크의 스왑 영역 또는 파일 시스템에 존재하는지 확인합니다.
      3. 존재하는 경우, 해당 페이지를 디스크에서 물리적 메모리로 로드합니다.
      4. 페이지 테이블을 업데이트하여 새로 로드된 페이지의 물리적 메모리 위치를 반영합니다.
      5. MMU가 올바른 물리적 주소를 참조할 수 있도록 프로세스의 실행을 재개합니다.

요구 페이징 (Demand Paging)

요구 페이징은 프로세스의 모든 데이터를 미리 메모리에 적재하지 않고, 실행 중에 필요한 데이터만 메모리에 적재하는 기법. 이는 선행 페이징과는 반대 개념으로, 프로세스의 관련 데이터를 미리 메모리에 올려놓고 실행하는 방식과 대조된다.

  • 실행 중 필요한 데이터만 적재: 프로세스의 실행 중에 실제로 필요한 데이터나 코드 페이지들만 메모리에 올린다. 이는 초기에 모든 데이터를 메모리에 로딩하는 것보다 자원 사용을 효율적으로 관리할 수 있게 함.

  • 미리 적재하지 않음: 모든 데이터를 미리 메모리에 올리지 않기 때문에 초기 부팅 시간이나 프로세스 시작 시간을 단축.

  • 페이지 부재 처리: 요구 페이징에서는 실행 중 필요한 페이지가 메모리에 없는 경우 페이지 부재가 발생하고, 이에 따라 해당 페이지를 보조 저장매체에서 가져와 메모리에 적재.

  • 유연한 메모리 관리: 필요 없어진 페이지 프레임은 필요한 경우 다시 저장매체에 저장하여 메모리를 효율적으로 관리.

07. 파일 시스템

운영 체제가 저장매체 파일을 쓰기 위한 자료구조 또는 알고리즘으로 사용하는 기법들:

블록 체인 기법

  • 파일을 연속적인 블록으로 나누어 저장하는 방식.
  • 각 파일은 첫 번째 블록의 주소를 가지고 있고, 이 블록은 다음 블록의 주소를 가리키는 포인터를 포함한다.
  • 파일이 저장매체에 저장될 때, 각 블록은 연결된 구조를 형성하여 파일을 구성한다.
  • 연결 리스트 형태.

인덱스 블록 기법

  • 파일의 데이터 블록들을 직접적으로 참조하는 대신, 각 파일에 대한 인덱스 블록을 사용하여 간접적으로 접근하는 방식.
  • 인덱스 블록은 파일의 데이터 블록들의 주소를 저장하는 데 사용된다.
  • 한번에 끝 블록을 찾아갈 수 있음.

아이노드 기법

각 파일은 고유한 아이노드(Inode) 번호를 가지고 있습니다. 각 아이노드에는 파일의 메타데이터 정보(파일 권한, 소유자 정보, 파일 크기 등)와 데이터 블록의 위치 정보를 저장

  • 파일 시스템 기본 구조
    • 수퍼 블록: 파일 시스템의 전반적인 정보와 파티션의 기본적인 구조를 포함.
    • 아이노드 블록: 각 파일에 대한 상세 정보를 저장하는 곳으로, 파일의 메타데이터와 데이터 블록의 위치를 포함.
    • 데이터 블록: 실제 파일 데이터가 저장되는 공간.

파일의 데이터에 접근할 때, 운영 체제는 파일의 이름을 통해 해당 파일의 아이노드를 찾고, 아이노드에 저장된 데이터 블록의 위치 정보를 사용하여 실제 데이터에 접근한다.

  • 파티션
    • 파일 시스템이 저장되는 논리적인 구역을 의미하며, 디스크 공간을 논리적 단위로 나누어 관리.

가상 파일 시스템

가상 파일 시스템은 컴퓨터 시스템에서 파일 및 디렉터리와 같은 저장 매체를 추상화하여 제공하는 소프트웨어 구성 요소이다. 이는 다양한 운영 체제와 응용 프로그램 사이에서 일관된 파일 시스템 인터페이스를 제공하며, 다양한 종류의 저장 매체를 지원하는 데 유용하다.

  • 추상화: 가상 파일 시스템은 실제 물리적 저장 장치(하드 디스크, SSD 등)의 세부 사항을 숨기고, 일관된 인터페이스를 제공하여 여러 응용 프로그램이 동일한 방식으로 파일 및 디렉터리에 접근할 수 있도록 한다.

  • 다양한 지원: 다양한 파일 시스템 형식(NTFS, FAT32, ext4 등)을 지원하며, 네트워크 파일 시스템(NFS, SMB 등)과 같은 원격 저장소에 접근할 수 있는 인터페이스도 제공할 수 있다.

  • 가상화 계층: 가상 파일 시스템은 일반적으로 운영 체제의 파일 시스템 계층 구조의 맨 위에 위치하여, 파일 시스템의 접근 및 관리를 중앙에서 제어하고 관리한다. 이를 통해 여러 응용 프로그램이 동시에 다양한 파일 시스템을 사용할 수 있다.

가상 파일 시스템은 마우스, 키보드 등의 모든 디바이스 관련 기술도 파일로 다루어질 수 있도록 추상화된 인터페이스를 제공한다. 이러한 접근 방식은 다양한 응용 프로그램들이 하나의 표준화된 방법으로 다양한 디바이스와 상호 작용할 수 있도록 한다.

기타

  • CPU 바운드 프로그램은 주로 연산 작업에 많은 시간을 소비하며, CPU에서 대부분의 작업을 처리하는 프로그램
  • I/O 바운드 프로그램은 주로 I/O 작업(예: 디스크 읽기/쓰기, 네트워크 통신 등)에 많은 시간을 소비하는 프로그램
  • 재귀 함수의 호출 깊이가 지나치게 깊어지면 스택 메모리가 초과되어 스택 오버플로우가 발생할 수 있다.
  • 자바에서 가비지 컬렉터(Garbage Collector, GC)가 필요한 이유는 힙(heap) 메모리의 효율적 관리를 위해서.
  • 멀티 프로세스는 프로그램을 처음 구조를 잡을 때부터 만들어지지만, 스레드는 프로그램의 일부 기능에서만 사용할 수 있도록하여 코드의 일부를 수정할 수 있게 함.
  • 커널 메모리나 PCB와 같은 운영 체제의 구조체는 운영 체제의 커널 공간에 저장된다.
  • 프로세스의 가상 메모리 공간에 페이지 테이블이 직접 포함되지 않지만, 페이지 테이블의 위치를 가리키는 포인터는 CPU 내부의 CR3 레지스터에 저장.
  • 스레싱(Thrashing) 반복적으로 페이지 폴트가 발생해서, 과도하게 페이지 교체 작업이 일어나는 경우.
This post is licensed under CC BY 4.0 by the author.