스레드

이지우·2023년 5월 8일
0

운영체제

목록 보기
1/3
  • 프로세스의 문제점
  • 스레드 개념
  • 스레드 주소 공간과 컨텍스트
  • 커널 레벨 스레드와 사용자 레벨 스레드
  • 멀티스레드 구현
  • 멀티스레딩에 관한 이슈

프로세스의 문제점

  1. 프로세스 생성의 큰 오버헤드
  2. 프로세스 컨텍스트 스위칭의 큰 오버헤드
  3. 프로세스 사이 통신의 어려움

오버헤드

  • 프로세스 생성
    메모리 할당, PCB 생성, 매핑 테이블 생성

  • 컨텍스트 스위칭
    매핑 테이블 전환에 시간적 공간적 오버헤드
    컨텍스트 옮기는 시간
    CPU 캐시에 새로운 프로세스의 코드와 데이터가 채워지는데 걸리는 시간

프로세스 사이 통신

프로세스들은 완전한 독립적인 주소 공간을 가짐
-> 프로세스가 다른 프로세스의 메모리에 접근 불가

프로세스 사이의 통신을 위한 제 3의 방법 필요함
-> 커널 메모리나 커널에 의해 마련된 메모리 공간을 이용하여 데이터 송수신
-> 코딩 어렵고 속도 느리고 운영체제 호환성 부족

부록 A 공유 메모리, 신호, 파이프 참고


스레드

프로세스보다 더 작은 실행 단위

  • 프로세스 문제점 해결을 위해 고안됨
  • 프로세스 생성 및 소멸에 따른 오버헤드 감소
  • 빠른 컨텍스트 스위칭

개념

  1. 스레드는 실행 단위이며 스케줄링 단위이다.
  2. 프로세스는 스레드들의 컨테이너이다.
  3. 프로세스는 스레드들의 공유 공간을 제공한다.
  4. 스레드가 실행할 작업은 함수로 작성한다.
  5. 스레드와 프로세스의 생명

스레드는 실행 단위이며 스케줄링 단위

  • 스레드는 응용프로그램 개발자에게는 작업을 만드는 단위
  • 운영체제에게는 실행 단위, CPU를 할당하는 스케줄링 단위
  • 코드, 데이터, 힙, 스택이 담긴 주소공간을 가진 실체
  • 실행이 운영체제에 의해 제어됨
    스레드마다 TCB 구조제를 두고 스레드 ID, 스케줄링 우선순위 등 스레드 정보를 관리
    생성, 소멸, 스케줄링 등 스레드들을 독립된 단위로 다룸

운영체제가 TCB를 통해 스레드 존재를 인식하고 TCB 중 하나를 선택해서 CPU에게 실행시킴


프로세스는 스레드들의 컨테이너

  • 프로세스는 스레드들을 담는 컨테이너로 개념이 수정됨
  • 스레드는 독립적으로 존재할 수 없고 프로세스 안에 존재
  • 스레드가 실행단위이므로 프로세스 내에 최소 1개 스레드가 있어야함
  • 프로세스 생성할때 커널이 자동으로 1개 스레드 생성 (Main thread)
  • 메인 스레드가 다른 스레드를 생성하고 이 스레드가 다른 스레드를 생성하면서 여러 스레드가 만들어지게 됨
  • 프로세스가 실행 중 == 스레드 중 하나가 실행 중


프로세스는 스레드들의 공유 공간 제공

  • 모든 스레드는 프로세스의 코드, 데이터, 힙을 공유하며, 프로세스의 스택 공간을 나누어 사용
  • 공유되는 공간을 이용하면 스레드 사이의 통신 용이

프로세스와 스레드

프로세스와 스레드 차이

구분ThreadProcess
상호통신Library Call / 요청한 Thread만 BlockingSystem Call / Call 종료까지 전체 Blocking
구분처리CPU를 사용할 기본단위자원을 할당할 기본단위
실행방식다중 처리한 개의 Process
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
int a[4] = {1,2,3,4}; int b[4];
void *func1() {
	b[0] = a[0] + 1; b[1] = a[1] + 1;
	printf("In func1: %d\n", b[0]);
}
void *func2() {
	b[2] = a[2] + 1; b[3] = a[3] + 1;
	printf("In func2: %d\n", b[2]);
}
int main(void) {
	int pid;
	// child 프로세스를 생성하여 func1()을 수행
	if ((pid = fork()) < 0)
		exit(1);
	else if (pid == 0) {
		func1();
		exit(0);
	}
	wait();
	func2();
	printf("sum=%d\n", b[0]+b[1]+b[2]+b[3]);
	exit(0);
}

실행 결과

In func 1: 2
In func 2: 4
Sum=9 

child 프로세스에서 func1을 수행하고 exit(0)를 하지 않으면

In func 1: 2
In func 2: 4
Sum = 14
In func 2: 4
Sum=9

pthread 라이브러리

POSIX thread
thread를 지원하기 위한 C 표준 라이브러리셋 제공

컴파일 시 gcc -o ~ ~.c -lpthread

#include <pthread.h> // pthread 라이브러리를 사용하기 위해 필요한 헤더 파일
#include <stdio.h>
#include <stdlib.h>

void* calcThread(void *param); // 스레드로 작동할 코드(함수)
int sum = 0; // main 스레드와 calcThread가 공유하는 전역 변수

int main() {
	pthread_t tid; // 스레드의 id를 저장할 정수형 변수
	pthread_attr_t attr; // 스레드 정보를 담을 구조체
	pthread_attr_init(&attr); // 디폴트 값으로 attr 초기화
	pthread_create(&tid, &attr, calcThread, "100"); // calcThread 스레드 생성
	// 스레드가 생성된 수 커널에 의해 언젠가 스케줄되어 실행
	pthread_join(tid, NULL); // tid 번호의 스레드 종료를 기다림
	printf("calcThread 스레드가 종료하였습니다.\n");
	printf("sum = %d\n", sum);
}

void* calcThread(void *param) { // param에 "100" 전달
	printf("calcThread 스레드가 실행을 시작합니다.\n");
	int to = atoi(param); // to = 100
	int i;
	for(i=1; i<=to; i++) // 1에서 to까지 합계산
	sum += i; // 전역 변수 sum에 저장
}

atoi() : ASCII 를 integer로 변환


멀티스레드

concurrency(동시성)

  • 1개의 cpu에서 2개 이상의 스레드가 동시에 실행

parallelism(병렬성)

  • 2개 이상의 스레드가 다른 cpu에서 같은 시간에 동시에 실행

스레드 주소 공간과 컨텍스트

스레드 주소 공간

스레드가 생성되고 실행되는 동간 접근 가능한 메모리 영역
프로세스의 주소 공간 내에 형성됨

  • 스레드 사적 공간
    - Thread code

    • TLS, Thread local storage
  • 스레드 사이의 공유 공간(프로세스 내에 존재)
    - 프로세스의 코드

    • 데이터 공간(로컬 제외)
    • 힙 영역


스레드 상태(states)

TCB에 저장됨

  • 준비 상태 (Ready)
  • 실행 상태 (Running)
  • 대기 상태 (Blocked)
  • 종료 상태 (Terminated)


join

스레드가 다른 스레드의 종료를 기다림
부모 스레드가 자식 스레드 종료할 때까지 대기


스레드 컨텍스트

스레드의 실행중인 상태 정보(CPU 레지스터 값)로 TCP에 저장됨


TCP

스레드 제어 블록
: 스레드에 관한 정보를 담은 구조체
: 커널 영역에 만들어짐


스레드 컨텍스트 스위칭


profile
노력형 인간

0개의 댓글