CS

Pintos Project1 -키워드 정리 (코드로 이해하기) / 프로세스, 스레드, 멀티 스레딩 문제

Jerry_K 2024. 11. 2. 20:29

프로세스 (Process) / 스레드 (Thread)

 

프로세스 (Process)

  • 실행 중인 프로그램의 인스턴스
  • 독립적 메모리 공간
    • 각 프로세스는 각각 독립된 메모리 공간을 가짐
    • 다른 프로세스가 접근 불가능
  • 고유한 자원 
    • CPU, 메모리, 파일 핸들 등의 자원을 OS로 부터 할당
  • 주소 공간 분리
    • 프로세스는 독립된 주소 공간을 가짐
    • 다른 프로세스의 메모리에 직접 접근 불가능
  • IPC (Inter-Process Communication) 
  • 독립된 메모리를 관리하여 컨텍스트 스위칭으로 오버헤드 
  • 프로세스 예시
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main() {
    pid_t pid = fork();  // 새로운 프로세스 생성

    if (pid < 0) {
        // fork 실패
        perror("fork failed");
        return 1;
    } else if (pid == 0) {
        // 자식 프로세스 실행
        printf("This is the child process. PID: %d\n", getpid());
    } else {
        // 부모 프로세스 실행
        printf("This is the parent process. PID: %d\n", getpid());
    }

    return 0;
}
This is the parent process. PID: 1234
This is the child process. PID: 1235
  • fork를 하면 자식 프로세스가 생성되는데 서로 다른 PID를 가짐
  • 자식 프로세스와 부모 프로세스는 독립적인 메모리 공간을 사용
  • 서로의 메모리에 접근 불가능

 

스레드 (Threads)

  • 프로세스 내 실행되는 작은 실행 단위
  • 하나의 프로세스 내에 여러개의 스레드 생성
  • 메모리 공간 공유
    • 같은 프로세스 내에 코드, 데이터, 힙 영역 공유
    • 하지만 각 스레드는 고유한 스택을 가짐
  • 프로세스보다 스레드 생성 및 종료가 빠름
  • 컨텍스트 비용 줄임
  • 동기화 매커니즘 필요 (스레드가 동일한 자원 접근 제어)
    • 뮤텍스, 세마포어 등의 메커니즘 
  • 스레드 예시
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void* print_message_function(void* arg) {
    char* message = (char*)arg;
    for (int i = 0; i < 5; i++) {
        printf("%s\n", message);
        sleep(1); // 1초 대기 (다른 스레드가 실행될 수 있도록)
    }
    return NULL;
}

int main() {
    pthread_t thread1, thread2;
    char* message1 = "Hello from Thread 1";
    char* message2 = "Hello from Thread 2";

    // 스레드 생성
    pthread_create(&thread1, NULL, print_message_function, (void*)message1);
    pthread_create(&thread2, NULL, print_message_function, (void*)message2);

    // 스레드 종료 대기
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    printf("All threads completed.\n");
    return 0;
}
  • pthread_create 함수를 통해서  thread1, thread2 생성
  • 각각의 쓰레드들은 번갈아가면서 print_message_function을 실행 (1초 대기)
  • 메인 스레드는 각 스레드가 완료될 때까지 기다림
  • 모든 스레드 종료 후 메인 스레드로 돌아가서 서브 스레드 종료
[New Thread 0x7ffff77c2700 (LWP 15792)]
Hello from Thread 1
[New Thread 0x7ffff6fc1700 (LWP 15793)]
Hello from Thread 2
Hello from Thread 2
Hello from Thread 1
Hello from Thread 2
Hello from Thread 1
Hello from Thread 2
Hello from Thread 1
Hello from Thread 2
Hello from Thread 1
All threads completed.
[Thread 0x7ffff6fc1700 (LWP 15793) exited]
[Thread 0x7ffff77c2700 (LWP 15792) exited]

 

 

 

Race Condition 

  • 경쟁 상태 
  • 발생 조건
    • 여러 스레드가 동시에 공유 자원 접근
    • 공유 자원의 상태를 읽고 쓰는 순서에 따라 결과가 달라지는 경우
#include <stdio.h>
#include <pthread.h>

int balance = 100; // 계좌 잔액

void* withdraw(void* amount) {
    int withdraw_amount = *((int*)amount);

    if (balance >= withdraw_amount) {
        balance -= withdraw_amount; // 잔액 업데이트
        printf("Withdrawn %d, New Balance: %d\n", withdraw_amount, balance);
    } else {
        printf("Insufficient funds\n");
    }
    return NULL;
}

int main() {
    pthread_t t1, t2;
    int amount1 = 50, amount2 = 50;

    // 두 스레드가 동시에 출금 시도
    pthread_create(&t1, NULL, withdraw, &amount1);
    pthread_create(&t2, NULL, withdraw, &amount2);

    pthread_join(t1, NULL);
    pthread_join(t2, NULL);

    printf("Final Balance: %d\n", balance);
    return 0;
}
  • 두 스레드가 동시에 blance를 읽어 잔액이 잘못 계산  될 수 있음
  • 때문에 데이터 불일치나 예상치 못한 동작 발생
  • 이를 방지하기 위한 Mutex, Semaphore 동기화 도구 사용

 

 

 

CPU Scheduling 알고리즘

  • OS가 CPU를 여러 프로세스에게 효율적으로 할당
  • 시스템 성능 극대화와 UX 향상
  • 동시에 여러 프로세스가 실행되거나 대기할 때 사용 우선 순위 정함
  • 스케줄링의 목표
    • 프로세스 효율적 배치 (처리량)
    • 프로세스가 대기 큐에서 대기 시간 최소화 (대기 시간)
    • 프로세스 실행 요청부터 완료까지의 반환  (반환 시간)
    • 프로세스가 처음으로 CPU에 접근한 시간까지의 지연 (응답 시간)

 

알고리즘

  • FCFS (First come First Served) 
    • 도착 순서대로 프로세스 처리
    • 긴 작업이 먼저 도착하면 후속 작업들이 오래 기다리는 문제
    • 비선점형
  • SJF (Shortest Job First)
    • 실행 시간이 가장 짧은 프로세스 먼저 처리
    • 평균 대기 시간 최적화
    • 긴 작업은 계속 대기하는 starvation 현상
    • 작업이 끝날 때까지 CPU 양보하지 않음
    • 비선점형
  • SRTF (Shortest Remaining Time First) 
    • 남은 실행 시간이 가장 짧은 프로세스에 우선권 제공
    • 짧은 작업을 빠르게 완료 
    • 긴 작업은 계속 대기하는 starvation 현상 
    • 더 짧은 남은 실행 시간을 가진 프로세스 도착 시 CPU를 넘김
    • 선점형
  • Round Robin 
    • 모든 프로세스가 동일한 시간단위 동안 CPU 번갈아 사용
    • 각 프로세스는 타임 슬라이스를 부여 받음
      • 타임 슬라이스는 프로세스가 CPU 점유 할 수 있는 최대 시간
    • 모든 프로세스 일정한 응답 시간 보장
    • 너무 짧은 context switching으로 오버헤드가 큼
    • 선점형
  • Multilevel Queue Scheduling 
    • 프로세스 우선순위에 따라 여러 큐로 분리 
    • 각 큐에 서로 다른 스케줄링 정책 적용
    • 특정 프로세스 집합에 최적화된 스케줄링 정책 적용
    • 낮은 우선순위 큐는 높은 우선순위 큐에 의해 오랫동안 대기 
    • 우선순위큐 
      • 우선순위 큐는 커널 메모리 영역에 존재
      • 사용자 프로세스가 직접 접근 불가능 
      • 커널 영역의 스케줄러가 우선순위 큐 관리
      • 각 큐는 고유의 우선순위를 가짐
    • 선점형
  • Multilvel Feedback Queue 
    • Multilevel Queue Scheduling와 유사
    • 프로세스가 큐 사이를 이동할 수 있도록 피드백 제공
    • 동적인 큐 이동으로 starvation 현상 방지 
    • 선점형

 

Single / Multilevel Queue 

  • Single Queue : FCFS, SJF, SRTF, Round Robin
    • Single Queue는 전체 시스템에 하나만 존재
    • 모든 프로세스가 단일 큐에 대기
    • 하나씩 꺼내어 CPU에 할당
  • Multilevel Queue : Multilevel Queue Scheduling 
    • 각 큐에 서로 다른 스케줄링 정책 이용
    • 다양한 작업을 효율적으로 관리 

 

위에 타임 슬라이스가 나왔다. 

그렇다면 타임 슬라이스와 타임 인터럽트의 차이는 무엇일까 ?

  • 타임 슬라이스
    • 프로세스가 CPU를 차지할 수 있는 최대 시간 단위
    • 타임 슬라이스가 끝나면 현재 프로세스는 CPU를 반환
  • 타이머 인터럽트
    • CPU에 내장된 하드웨어 타이머는 일정 주기마다 인터럽트
      • 다른 인터럽트는 주로 외부 장치나 특정 이벤트에 발생
    • OS는 타이머 인터럽트를 받아 context switching 수행
    • CPU 스케줄러와 연계되어 프로세스 스케줄링 자동 관리 

 

 

Semaphore / Mutex

  • 공유 자원에 대한 접근을 안전하게 제어하는 동기화 매커니즘
  • Race Condition이나 데이터 불일치 문제 방지

 

Semaphore

  • 멀티스레딩 환경의 동기화 매커니즘
  • OS에서 자원 접근 제어을 위한 도구
  • 자원과 스레드 수 제한
  • 특정 조건을 만족할 때까지 스레드 대기 
  • 카운터를 사용 (정수형 카운터) 
    • 카운터 값이 양수이면, 자원에 접근할 수 있는 스레드 남아있음
    • 카운터 값이 0이면, 자원 모두 사용 중 (추가 접근 제한)
    • P 연산 (Wait)
      • 자원에 접근할 때 세마포어 값 1  감소
    • V 연산 (Signal)
      • 자원 사용 후 세마포어 값 1 증가 
  • 프로세스 간 공유 가능한 세마포어
    • 프로세스 간 공통 자원에 접근
    • 커널 영역에서 관리
  • 프로세스 간 공유가 안되는 세마포어
    • 해당 프로세스의 메모리 공간에 위치
    • 데이터 영역이나 힙 영역에 저장
    • 해당 세마포어는 프로세스 내의 스레드만 접근 가능

 

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

#define NUM_THREADS 6   // 전체 스레드 수
#define MAX_RESOURCES 3 // 동시에 접근 가능한 최대 자원 수

sem_t semaphore;

void* access_resource(void* arg) {
    int thread_num = *((int*)arg);
    
    printf("Thread %d: Waiting to access resource...\n", thread_num);
    sem_wait(&semaphore); // P 연산: 자원 접근 제한

    // 자원 사용 중
    printf("Thread %d: Accessing resource\n", thread_num);
    sleep(2); // 자원 사용을 시뮬레이션하기 위해 2초 대기
    
    printf("Thread %d: Releasing resource\n", thread_num);
    sem_post(&semaphore); // V 연산: 자원 해제

    return NULL;
}

int main() {
    pthread_t threads[NUM_THREADS];
    int thread_nums[NUM_THREADS];

    // 세마포어 초기화, 카운터를 MAX_RESOURCES로 설정하여 최대 접근 수 제한
    sem_init(&semaphore, 0, MAX_RESOURCES);

    // 스레드 생성
    for (int i = 0; i < NUM_THREADS; i++) {
        thread_nums[i] = i + 1; // 스레드 번호 할당
        pthread_create(&threads[i], NULL, access_resource, &thread_nums[i]);
    }

    // 모든 스레드가 종료될 때까지 대기
    for (int i = 0; i < NUM_THREADS; i++) {
        pthread_join(threads[i], NULL);
    }

    // 세마포어 파괴
    sem_destroy(&semaphore);

    printf("All threads completed.\n");
    return 0;
}

 

  • sem_init 함수를 통해 세마포어를 초기화
  • sem_wait 함수(P연산)으로 카운터 값 1 감소
    • 자원 접근 제한 시 스레드는 대기 상태
  • sem_post 함수(V연산)으로 카운터 값 1 증가
    • 다른 스레드가 자원에 접근
  • sem_destory로 세마포어 해제
[New Thread 0x7ffff77c2700 (LWP 3314)]
Thread 1: Waiting to access resource...
Thread 1: Accessing resource
[New Thread 0x7ffff6fc1700 (LWP 3315)]
Thread 2: Waiting to access resource...
Thread 2: Accessing resource
[New Thread 0x7ffff67c0700 (LWP 3316)]
Thread 3: Waiting to access resource...
Thread 3: Accessing resource
[New Thread 0x7ffff5fbf700 (LWP 3317)]
Thread 4: Waiting to access resource...
[New Thread 0x7ffff57be700 (LWP 3318)]
Thread 5: Waiting to access resource...
[New Thread 0x7ffff4fbd700 (LWP 3319)]
Thread 6: Waiting to access resource...
Thread 1: Releasing resource
Thread 4: Accessing resource
Thread 2: Releasing resource
Thread 3: Releasing resource
[Thread 0x7ffff67c0700 (LWP 3316) exited]
Thread 6: Accessing resource
[Thread 0x7ffff77c2700 (LWP 3314) exited]
Thread 5: Accessing resource
[Thread 0x7ffff6fc1700 (LWP 3315) exited]
Thread 4: Releasing resource
Thread 5: Releasing resource
Thread 6: Releasing resource
All threads completed.
[Thread 0x7ffff4fbd700 (LWP 3319) exited]
[Thread 0x7ffff57be700 (LWP 3318) exited]
[Thread 0x7ffff5fbf700 (LWP 3317) exited]

 

 

Mutex

  • Mutual Exclusion (상호 배제)
  • 멀티스레드 및 멀티 프로세스 환경에서 안전하게 자원 보호
  • 한 번에 하나의 스레드 또는 프로세스만 자원에 접근
  • Lock과 Unlock 기법 사용
  • 하나의 스레드가 Mutex를 획득하면(Lock), 자원에 접근할 수 있는 유일한 스레드
  • 잠근 스레드만 이를 Lock 해제 (다른 스레드는 해제 불가능)
  • 대기상태
    • 자원이 이미 다른 스레드에 의해 잠긴 상태면, 접근하려는 스레드는 대기 상태
  • 커널 모드와 사용자 모드 간의 전환 없이 사용자 모드에서 운영 가능
    • 커널 모드 전환이 필요 없는 경우 CPU 오버헤드가 줄어듬
      • 일반적인 자원 관리 방식은 커널 모드로 전환하여 자원 접근 속도 향상
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

pthread_mutex_t mutex; // 뮤텍스 객체 선언
int shared_resource = 0; // 공유 자원

void* thread_function(void* arg) {
    pthread_mutex_lock(&mutex); // 뮤텍스 잠금 (락)
    int thread_num = *((int*)arg);
    
    // 공유 자원 접근
    printf("Thread %d: Accessing shared resource\n", thread_num);
    shared_resource += 1;
    printf("Thread %d: Shared resource value = %d\n", thread_num, shared_resource);
    sleep(1); // 작업 시뮬레이션

    pthread_mutex_unlock(&mutex); // 뮤텍스 잠금 해제 (언락)
    return NULL;
}

int main() {
    pthread_t threads[3];
    int thread_nums[3] = {1, 2, 3};

    pthread_mutex_init(&mutex, NULL); // 뮤텍스 초기화

    // 스레드 생성
    for (int i = 0; i < 3; i++) {
        pthread_create(&threads[i], NULL, thread_function, &thread_nums[i]);
    }

    // 스레드 종료 대기
    for (int i = 0; i < 3; i++) {
        pthread_join(threads[i], NULL);
    }

    pthread_mutex_destroy(&mutex); // 뮤텍스 파괴
    printf("Final shared resource value: %d\n", shared_resource);
    return 0;
}
  • 뮤텍스 객체 선언 및 초기화
  • 스레드 생성 및 실행
  • 하나의 스레드가 Lock 상태여서 다른 스레드 자원 접근 불가능
  • 스레드 잠금 해제 된 이후 대기 뮤텍스 중 하나 자원 접근
[New Thread 0x7ffff77c2700 (LWP 21120)]
Thread 1: Accessing shared resource
Thread 1: Shared resource value = 1
[New Thread 0x7ffff6fc1700 (LWP 21121)]
[New Thread 0x7ffff67c0700 (LWP 21122)]
Thread 2: Accessing shared resource
Thread 2: Shared resource value = 2
[Thread 0x7ffff77c2700 (LWP 21120) exited]
Thread 3: Accessing shared resource
Thread 3: Shared resource value = 3
[Thread 0x7ffff6fc1700 (LWP 21121) exited]
Final shared resource value: 3
[Thread 0x7ffff67c0700 (LWP 21122) exited]

 

 

 

Deadlock 

  • 교착 상태
  • 둘 이상의 프로세스 또는 스레드가 서로 자원 점유
  • 다른 자원이 해제되기만 기다리며 무한정 대기
  • 발생 조건
    • 상호 배제
      • 자원은 한 번에 하나의 프로세스만 사용 가능
      • 한 프로세스가 자원을 점유하면 다른 프로세스는 해당 자원 사용 불가
    • 점유 대기
      • 하나 이상의 자원을 점유한 상태에서 다른 자원이 해제되기를 기다리는 상태
    • 비선점
      • 프로세스가 점유한 자원은 해당 프로세스가 자발적 자원 해저 전까지 강제로 뺐을 수 없음
    • 순환 대기
      • 교착 상태에 있는 프로세스들이 서로 순환 형태로 자원 기다림
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

pthread_mutex_t resourceA; // 자원 A
pthread_mutex_t resourceB; // 자원 B

void* thread1(void* arg) {
    pthread_mutex_lock(&resourceA); // 자원 A 점유
    printf("Thread 1 acquired resource A\n");
    sleep(1); // 다른 스레드가 자원을 점유할 기회를 주기 위해 대기

    pthread_mutex_lock(&resourceB); // 자원 B 점유 시도
    printf("Thread 1 acquired resource B\n");

    pthread_mutex_unlock(&resourceB);
    pthread_mutex_unlock(&resourceA);
    return NULL;
}

void* thread2(void* arg) {
    pthread_mutex_lock(&resourceB); // 자원 B 점유
    printf("Thread 2 acquired resource B\n");
    sleep(1); // 다른 스레드가 자원을 점유할 기회를 주기 위해 대기

    pthread_mutex_lock(&resourceA); // 자원 A 점유 시도
    printf("Thread 2 acquired resource A\n");

    pthread_mutex_unlock(&resourceA);
    pthread_mutex_unlock(&resourceB);
    return NULL;
}

int main() {
    pthread_t t1, t2;
    pthread_mutex_init(&resourceA, NULL);
    pthread_mutex_init(&resourceB, NULL);

    pthread_create(&t1, NULL, thread1, NULL);
    pthread_create(&t2, NULL, thread2, NULL);

    pthread_join(t1, NULL);
    pthread_join(t2, NULL);

    pthread_mutex_destroy(&resourceA);
    pthread_mutex_destroy(&resourceB);
    return 0;
}

 

  • Thread 1은 자원 A 점유, Thread 2는 자원 B를 점유
  • Thread 1은 자원 B를 요청하지만, Thread 2는 자원 B를 이미 점유
  • Thread 2은 자원 A를 요청하지만, Thread 1는 자원 A를 이미 점유
  • 무한 대기 (Deadlock)

 


Context Switching

  • OS가 CPU를 한 프로세스 또는 스레드에서 다른 프로세스 또는 스레드로 전환하는 과정
  • CPU가 현재 실행 중인 상태 저정 
  • 다음 실행할 프로세스 상태 복원
  • Context Switching으로 여러 프로세스 동시 실행되는 듯 보임
  • CPU 자원 효율적 활용

 

주요 단계 

  • OS는 현재 실행 중인 프로세스의 레지스터 값, PC, 스택 포인터 등을 PCB에 저장  
    •  PCB
      •  프로세스 상태 및 정보 관리하는 데이터 구조 
      • 커널 영역에 저장
      • 프로세스의 중요한 정보 보호 (커널 영역)
      • 운영체제의 관리 영역 (커널은 운영체제의 메모리 공간)
      • 따라서 Context Switching  시 빠르게 PCB에 접근 가능
        • 시스템 콜이 필요 없기 때문
      • 각 프로세스의 PCB는 모든 스레드의 TCB 참조
  • 실행할 다음 프로세스 선택
    • PCB에 저장된 상태 정보를 CPU 레지스터로 로드
    • 이전에 실행했던 위치부터 이어서 실행
  • CPU 제어권 전환
    • 새로운 프로세스 활성화
    • CPU가 해당 프로세스의 명령어 실행

 

Context Switching  발생 

  • 프로세스 스케줄링
    • time slice가 끝난 시점 다른 프로세스에 CPU 할당
  • Interrupt (인터럽트)
    • I/O 요청 및 외부 이벤트 발생
    • 현재 프로세스 대기 상태로 전환되고 다른 프로세스 실행
  •  System call 
    • User Mode에서 실행 중인 프로세스가 OS에게 요청하여 Kernel Mode 사용
    • ex ) read, write, malloc, fork 함수 등
    • 커널 모드로 전환하여 Context Switching 발생 
    • System call 완료 후 User Mode 복귀

 

특정 함수 실행되는 중에 타임 슬라이스가 종료되는 경우

  • 타이머 인터럽트 발생하여 종료
  • OS는 해당 함수 실행 중단하고 Context Switching 
  • OS는 레지스터 상태, PC, 스택 포인터 등을 PCB에 저장
  • 이후 복귀는 PCB에 저장된 상태를 복사
  • 하지만 특정 명령어가 중간에 끊기지는 않음
    • 원자적 명령어 (더 이상 나눌 수 없는 연산)
    • CPU 중단 없이 한 번에 완료
    • 도중에 멈추거나 끊기지 않음  (예외 없는 실행)

 

프로세스 / 스레드 간 Context Switching  

  • 프로세스 간 Context Switching
    • OS가 프로세스 A에서 프로세스 B에게 제어권 넘김
    • 메모리 주소 공간, 레지스터 상태, PC 등 완전히 전환
  • 스레드 간 Context Switching
    • 현재 프로세스의 주소 공간과 다음 프로세스 주소 공간이 같으면 스레드 간 전환
    • 같은 프로세스간 전환
      • 메모리 공간 공유
      • 주소 공간 전환 필요 없음
      • 전환시 필요 정보 (레지스터 상태, PC, 스택 포인터)
      • 캐시 활용 가능 증가
    • 다른 프로세스 간의 스레드 전환 
      • 주소 공간 전환
      • 캐시 무효화
      • PCB와 TCB 전환

 

Context Switching  오버헤드

  • 시간 지연
    • 새 프로세스 로드 과정에 CPU는 Context Switching에 시간 소비
  • 메모리 캐시 손실
    • 프로세스 전환으로 CPU 캐시에 저장된 데이터 무효화
    • 캐시 미스로 성능 저하

 

코드 예시

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void* thread_func1(void* arg) {
    for (int i = 0; i < 5; i++) {
        printf("Thread 1 is running\n");
        sleep(1); // 1초 대기하여 다른 스레드가 실행될 수 있도록 함
    }
    return NULL;
}

void* thread_func2(void* arg) {
    for (int i = 0; i < 5; i++) {
        printf("Thread 2 is running\n");
        sleep(1); // 1초 대기하여 다른 스레드가 실행될 수 있도록 함
    }
    return NULL;
}

int main() {
    pthread_t t1, t2;

    // 두 개의 스레드를 생성
    pthread_create(&t1, NULL, thread_func1, NULL);
    pthread_create(&t2, NULL, thread_func2, NULL);

    // 각 스레드가 종료될 때까지 기다림
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);

    printf("Both threads have finished.\n");
    return 0;
}

 

  • 두 스레드가 번갈아가며 실행
[New Thread 0x7ffff77c2700 (LWP 7900)]
Thread 1 is running
[New Thread 0x7ffff6fc1700 (LWP 7901)]
Thread 2 is running
Thread 1 is running
Thread 2 is running
Thread 1 is running
Thread 2 is running
Thread 1 is running
Thread 2 is running
Thread 1 is running
Thread 2 is running
Both threads have finished.
[Thread 0x7ffff6fc1700 (LWP 7901) exited]
[Thread 0x7ffff77c2700 (LWP 7900) exited]

 

 

 

 

아래는 Context Switching 에 어떤게 들어가는지 궁금해서 찾아보았다. 

 

➕ Context Switching 시 저장되는 주요 정보

  • 레지스터 상태
    • 일반 목적 레지스터 : 변수 또는 프로세스가 현재 계산 중인 값
    • 프로그램 카운터 (PC) : 현재 실행 중인 명령어 위치 (중단된 명령어의 위치)
    • 스택 포인터 (SP) : 현재 스택의 최상단을 가르키는 포인터 
    • 베이스 포인터 (BP) : 함수 호출될 때의 스택 프레임의 시작주소 지정 
      • 함수 기준으로 스택 프레임 시작 고정
      • 스택 프레임에서 일정한 오프셋을 기준으로 접근
    • 플래그 레지스터 : 조건부 명령어 수행에 영향을 미치는 플래그 상태 저장
      • 제로 / 부호 / 오버플로우 / 캐리 / 패리티 / 보조 캐리 플래그
  • 스택 관련 정보 
    • 커널 스택 
      • 각 프로세스마다 커널 모드에서 사용하는 스택 존재
      • 시스템 호출이나 인터럽트 처리 중에 사용
      • 프로세스 중단 직전 커널 스택 상태 PCB에 저장
    • 사용자 스택
      • 프로세스가 사용자 모드에서 작업할 때 사용
  • 프로세스 상태
    • Running, Ready, Blocked 등의 상태
  • 메모리 관련 정보
    • 페이지 테이블 포인터 
      • 페이지 테이블의 위치를 가르키는 포인터 (PBTR의 값)
    • 세그먼트 레지스터
      • 코드,데이터 스택 등의 메모리 세그먼트를 가르키는 레지스터 
      • 세그먼트를 기반으로 메모리 접근 
  • 입출력 상태 정보
    • 파일 디스크립터 테이블 
      • 프로세스가 열어 놓은 파일들의 정보
    • I/O 장치 정보 
  • 우선 순위
    • 스케줄링 시 사용할 프로세스 우선순위
  • 계정 정보
    • 이 프로세스가 얼마나 많은 자원을 사용했는지 추적
  • 부모 프로세스 ID
    • 부모 프로세스 종료 시 자신 프로세스 종료 
      • 고아 프로세스 처리
      • 작업 수행을 부모에게 정보 전달 
    • 디버깅 목적 
    • 추후 자식 프로세스가 종료 될 때 wait () 부모 프로세느는  시스템 콜 호출
      • 자식 프로세스의 종료 상태 수집 및 자원 해제