운영체제 - 스레드 개요

TopOfTheHead·2025년 7월 25일

운영체제

목록 보기
11/24

스레드 ( Thread ) 하드웨어 스레드

소프트웨어 스레드 : 프로세스가 할당받은 자원을 이용하는 실행단위
CPU에서 실행하는 명령어 단위로 해석가능

단일 프로세스 내에서 실행되는 명령어의 흐름
스레드 \in 프로세스
스레드LWP( lightweight process )
스레드프로세스의 특징을 공유하므로 프로세스와 동일한 상태( new , running ,... ) 등을 가진다

멀티스레드를 통해 프로세스는 여러 스레드를 가질 수 있으며 각 스레드는 독립적으로 실행

프로세스스레드 구조



프로세스스레드들은 동일한 Text Section / Data Section / Heap Section프로세스 주기억장치 영역을 공유하며 각 스레드들은 고유한 스레드ID / Stack / 프로그램 카운터 / 레지스터 집합를 가진다.
멀티스레딩을 통해 동일한 프로세스 자원을 공유하면서 스레드 별로 독립적으로 Concurrently하게 함수를 실행 및 스레드실행위치상태를 독립적으로 관리 가능

  • 스레드ID ( Thread ID ) :
    。개별 스레드의 식별을 위해 존재

  • 프로그램 카운터 ( Program Counter ) :
    스레드가 다음에 실행할 명령어의 주소를 지시하는 포인터
    ▶ 각 스레드의 실행위치를 저장하기 위해 각 스레드 마다 별도로 PC를 가진다.

  • 레지스터 집합 ( Register Set ) :
    스레드가 현재 실행되는 상태를 저장하는데 사용하는 임시저장장치의 집합
    ▶ 각 스레드의 명령어 처리중 값을 임시로 저장하기 위해 각 스레드는 별도의 레지스터 집합 공간을 가진다.

  • 스택 ( Stack ) 프로세스 메모리 레이아웃 - 스택
    스레드에서의 함수 호출 시 매개변수, 되돌아갈 주소값, 함수 내 지역 변수을 저장하는 주기억장치 영역
    ▶ 각 스레드마다 독립적인 함수 호출을 위해 각 스레드는 별도의 스택 영역을 가진다.

스레드의 실행방식 종류
하드코어 스레드 , 소프트웨어 스레드로 구분
하드코어 스레드 : CPU의 단일 코어가 동시에 처리하는 명령어 단위로서 논리 프로세서
소프트웨어 스레드 : OS의 단일 프로그램( = 프로세서 )에서 독립적으로 실행되는 단위

소프트웨어 스레드 실행방식 종류

  • 싱글 스레드 ( Single Thread ):
    。단일 프로세스가 하나의 스레드만 가지면서 한번에 오직 한 Task를 처리하는 것을 의미

  • 멀티 스레드 ( Multi Thread )
    。단일 프로세스가 여러 스레드들을 가지면서 동시에 여러 Task를 처리하는 것을 의미

    OS이 제공하는 멀티태스킹 or 멀티 프로세싱 기능을 통해 수행됨

    。예전에는 병렬처리에 대해 여러 코어들을 통한 parallelism으로서 멀티코어 프로세서가 유행했다면 현재는 OS를 이용한 Concurrency멀티 스레드가 유행
    ▶ ex. JAVA

스레드의 2가지 TYPE
생성 주체( 사용자 or OS )에 따라 구분

  • User Thread
    User Level Library에 의해 구현되어 user mode에서 스레딩하는 스레드
    JAVA 등의 프로그래밍 언어의 스레드 관련 라이브러리로 생성된 스레드

    OS가 아닌 라이브러리에 의해 스레드 생성스케줄링을 관리
    Kernel이 직접 개입하지 못한다.

    。동일 메모리 영역에서 스레드의 생성 및 관리가 되므로 속도가 빠름

    프로세스User Thread특정 User ThreadSystem Call에 의해 중단 시 프로세스가 중단
    Kernel 입장에서는 User Thread를 인식하지 못하므로 System Call 발생 시 프로세스waiting 상태로 전환

  • Kernel Thread
    Kernel에 의해 구현되어 kernel mode에서 스레딩하는 스레드
    OS에 의해 스레드 생성 및 개별적으로 스케줄링을 통해 관리됨

    User Thread에 비해 스레드의 생성 및 관리속도가 느리다.

    프로세스Kernel Thread특정 Kernel ThreadSystem Call에 의해 중단이 되더라도 다른 Kernel Thread는 영향 없이 계속 실행
    멀티 코어 환경에서도 병렬 처리에 유리.

    Multi-Threading Model 종류
    User ThreadKernel Thread 간 관계를 의미
    User ThreadKernel Thread 는 생성한 프로세스에 대해 반드시 결합.

    • Many to One Model

      。여러 User Thread가 단일 Kernel ThreadMapping

      스레드User Level Library에 의해 관리되므로 속도가 빠르지만, 스레드 하나가 System Call 등에 의해 정지할 경우 나머지 스레드들도 모두 정지

    • One to One Model

      。단일 User Thread를 단일 Kernel Thread로 각각 Mapping

      。한 스레드가 중지되어도 다른 스레드에 영향이 없지만 속도가 느려 효율이 좋지않음
      Concurrency 측면에서는 Many-to-one에 비해 유리

    • Many to Many Model

      M개의 User ThreadN개의 Kernel ThreadMapping

      。위 장점들을 모두 가지지만 구현이 어려움.

Thread Library
스레드를 생성 및 관리하기위한 API의 집합
ex ) JAVAThread Class

가장 많이 사용되는 Thread Library 종류
POSIX PthreadsLinux 계열에서 주로 사용
Windows threads
Java threads

  • Pthreads( Posix Thread ) #include <pthread.h>
    UNIX OS에서 멀티스레딩을 통한 병렬처리 프로그래밍을 위한 API 집합
    커널 스레드 정의
    POSIX 표준의 Thread Library ( IEEE 1003.1c )
    병렬 프로그램은 여러 스레드 들을 통해 구동

    메인스레드에서 2개의 커널스레드 생성 시 서로 Round Robin 스케쥴링으로 Context Switching을 수행하면서 Concurrent하게 Task를 처리
int main(){
  pthread_t tid1, tid2;
  // 스레드 생성
  pthread_create(&tid1, NULL, 사용자정의 함수, NULL);
  pthread_create(&tid2, NULL, 사용자정의 함수, NULL);
  // 각 스레드끼리 Context Switching 발생 시 비동기 작동 차단
  pthread_join(tid1,NULL);
  pthread_join(tid2,NULL);
  printf("%d\n", sum);
}

메인스레드 내 2개의 커널스레드 ( tid1 , tid2 ) 생성 후 Context Switching을 하면서 특정 함수를 실행
▶ 각 스레드parallel하게 실행되는게 아닌, Concurrent하게 실행

POSIX ( Portable Operating System Interface For Unix )
。서로 다른 UNIX OS 간 호환성을 위해 공통 API를 책정한 Application Interface 규격
POSIX를 준수하는 UNIX OS는 다른 UNIX OS와 호환

  • Java에서의 User Thread
    Java스레드 기반으로 개발한 언어
    자바로 구축한 Application은 기본적으로 스레드기반으로 실행하며 메인 스레드에서 main()를 실행하여 시작

    Java멀티스레딩을 지원하며 여러 작업을 Concurrently하게 실행

    。여러종류의 스레드 API를 지원
    ▶ 각 스레드의 생성 및 관리가 쉽다

    。단. JAVAUser Thread를 생성 및 관리
    OS에 의해 관리되지 않으며 JAVA에 의해 스레드가 관리됨
    JVM에 의해 특정 OSkernel thread( pthreads 등 )와 Many to One Model 등의 관계를 맺어서 운용

    자바에서 스레드 활용

  • UNIX OS에서의 Kernel Thread
    pthreads Library 사용
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
// 컴파일러 인식하기위해 전역변수 및 프로토타입 선언
int sum; // 전역변수
void *runner(void *param);
//
int main(int argc , char *argv[]){
  pthread_t tid; // 스레드 식별 
  pthread_attr_t attr; // 스레드 속성
  pthread_attr_init(&attr);
  pthread_create(&tid,&attr, runner, argv[1]);
  pthread_join(tid, NULL);
  printf("sum = %d\n", sum);
}
void *runner(void *param){
  int i, upper = atoi(param);
  sum = 0;
  for(int i = 0 ; i <= upper ; i++){
    sum += i;
  }
  pthread_exit(0);
}

。이때, 함수 void *runner(void *param)의 경우 JavaThread Classpublic void run()과 같은 역할을 수행
pthread_create()에 의해 호출됨

gcc -pthread 파일명.c를 통해 컴파일

스레드 예제

  • 다음 코드에서 생성되는 Unique스레드프로세스 수는?
  pid_t pid;
  pid = fork();
  if ( pid == 0 ){
    // 자식프로세스
    fork();
    thread_create( .... );
  }
  fork()

스레드 수 : 2개 / 프로세스 수 : 6개


  • 예제2
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wait.h>
#include <pthread.h>
// 컴파일러 인식하기위한 전역변수 및 프로토타입 선언
int value = 0;
void *runner(void *param);
//
int main(int argc , char *argv[]){
  pid_t pid; // 프로세스 ID
  pthread_t tid; // 스레드 ID 
  pthread_attr_t attr; // 스레드 속성
  pid = fork(); // 자식 프로세스 생성
  if (pid == 0){
    // 자식프로세스
    pthread_attr_init(&attr);
    pthread_create(&tid,&attr, runner, argv[1]);
    pthread_join(tid, NULL);
    printf("CHILD : value = %d\n" , value);
  } else if ( pid > 0 ){
    // 부모프로세스
    wait(NULL);
    printf("PARENT : value = %d\n" , value);
  }
}
void *runner(void *param){
  value = 5;
  pthread_exit(0);
}

퀴즈문제 해설

출처
운영체제 공룡책 강의

profile
공부기록 블로그

0개의 댓글