여러가지 일들을 동시에 처리 -> multi threading
Thread의 개념
- 프로세스란 프로그램이 실행되고 있는 것 -> 한 부분만 실행
- 쓰레드를 사용하면 프로그램의 여러부분을 동시에 실행 가능 -> 각각의 부분의 쓰레드라고 함
- function을 호출해가는 순서, local variable을 저장할 공간이 필요
- 어느 부분을 하고 있는지를 가리키는 counter와 호출해가는 순서를 기록하는 stack을 각자 개별적으로 보유
- light-weight process : 쓰레드의 다른 이름 -> 쓰레드들은 프로세스에 있는 메모리 space를 공유해서 사용하기 때문
- 일반적인 프로세스들은 쓰레드가 1개 밖에 없음
A single-threaded vs. a multi-thread processes
- single-threaded
- data : address space에 data를 저장하는 부분
- file descripter : 파일을 open한 descripter
- register : cpu상태를 나타내는 register값들
- stack : function을 어떤식으로 호출해 갔는지
- code : code의 어떤 부분을 실행하는 thread
- multi-thread
- 쓰레드가 동시에 실행 중
- code의 여러부분을 동시에 실행 가능
- 각각이 cpu의 프로그램 counter를 가지고 있어야하고 stack또한 따로 가지고 있어야 함
- global한 data와 files는 공유
- 구체적인 memory map
- 왼쪽은 일반적인 프로세스의 메모리영역
- kernel 영역과 user 영역(text, data, Heap, stack이 딱 하나!!!)
- 오른쪽은 멀티 쓰레드의 메모리영역 -> kernel은 동일
- data그대로 Heap그대로 / stack이 따로따로 존재 -> 쓰레드마다 각기 다른 부분을 호출하며 수행하기 때문에 각 쓰레드별로 어떤 식으로 호출했는지 stack을 따로 잡아주어야 함
왜 여러개의 프로세스를 사용하지 않고 병렬적인 쓰레드를 사용하는가
- process
- fork() : 오버헤드가 큼 - time & memory -> 새로운 프로세스를 생성할 때 매우 많은 시간과 메모리가 필요
- 각각 독립적인 space를 가지고 있기 때문에 데이터를 주고받기 어려움 -> IPC라는 interprocess comunication mechanism을 사용해야 가능
- Threads
- stack영역을 하나 더 추가하는 것이기 때문에 매우 빠름, 하나의 memory space를 공유하기 때문에 메모리 사용량도 적음
- data를 공유하기 쉬움(global, static) -> 한 쓰레드가 사용한 것을 다른 쓰레드가 가져다 사용 가능
Multi-threading
- 쓰레드들이 각각 일정 부분의 일들을 나누어서 처리
- cpu core들을 여러개 가지고 있는 경우 각각의 cpu에 쓰레드들이 수행하도록 함으로써 병렬로 처리되도록 할 수 있음
- cpu가 하나만 있는 경우 하나의 cpu에서 여러 쓰레드가 time sharing을 하기 때문에 수행 속도가 빨라지거나 하지 않음
- 여러 cpu가 있는 경우(core), 각각의 cpu에서 쓰레드를 나누어 수행하는 경우 time sharing을 할 필요가 없어지기 때문에 진정한 병렬처리를 수행 할 수 있게됨 -> 속도가 빨라짐
POSIX threads
- Pthreads라고 표현
- Unix계열의 운영체제들에서 multi threading을 하기위한 프로그래밍 API들을 define해놓은 것
- pthread API
- 쓰레드 관리 : 생성, 종료 등/ 쓰레드의 속성 결정
- 데이터 공유할때 어떻게 충돌하지 않도록 공유하는지 -> mutexes, condition variables
- pthread_self : 쓰레드의 ID를 가져옴
- pthread_equal : 두 쓰레드가 같은 쓰레드인지 비교
- pthread_create : 가장 많이 사용, 쓰레드를 생성
- pthread_join : 쓰레드가 종료 될 때까지 기다림
- pthread_detach : 쓰레드를 Detach
- pthread_exit : 쓰레드를 종료시킴
Using Pthreads
- 어떤 부분을 thread로 만들 것인가
- 함수의 형태로 만듦
- pthread_create의 함수의 인자로 넘겨줌
- libpthread library를 써줘야 컴파일 가능
- gcc -lpthread -o outputfile threaded_program.c
- 프로그램 실행 시 생성한 쓰레드들이 동시에 실행 됨 -> 데이터 공간 공유(address space)
pthread_create(3)
- void * (*start_routine) (void *) : 쓰레드를 만들고 싶은 함수의 function pointer를 받아서 argument로 void 포인터를 받고 리턴 값도 동일
- void *arg : 쓰레드를 수행할 함수에 넘겨줄 argument를 정해줌
- const pthread_attr_t *attr : 자세히 사용하지 않을 경우 NULL로 세팅
- pthread_t *thread : 생성하면 handle을 return -> 이것을 가지고 특정한 쓰레드를 지정할 수 있음
- 성공한 경우 0을, 실패한 경우 -1을 return -> 반드시 확인해야 함!!
- EAGAIN : 충분한 리소스가 없음 -> ex) 스택을 새로 할당해야 하는데 무한대로 쓰레드를 만들수는 없음(스택이 모자람)
-
pthread_t objects
-
쓰레드를 지정하기 위해 쓰레드의 ID가 pthread_t 타입으로 return됨
-
어떤 타입인지 알 필요 없음 -> 내부적으로 구현이 되어있는지 몰라도 됨
-
보조함수 : Thread IDs
-
pthread_self : pthread_t 타입, 자기자신의 thread ID를 리턴
-
pthread_equal : 두 쓰레드가 같은 쓰레드인지 비교
-
Function started by pthread_create(3)
-
argument로 void pointer를 받고 리턴값으로 void pointer로 넘겨줌 -> 어떠한 데이터에 대한 포인터도 넘겨줄 수 있다는 의미 -> type casting을 하여 사용
-
리턴값 또한 사용할 때 type casting을 하여 사용
-
예제
- pthread.h를 include
- pthread_t의 핸들을 선언
- attribute는 NULL, 쓰레드는 snow라는 함수 수행, data(string)
- (char *)data : type casting을 함
- snow가 수행되는 동안 main 쓰레드도 수행 됨
- fork()와 비교
- 완전히 동일한 프로세스가 생성됨 -> 오래 걸림
- 메인 쓰레드가 수행되고 있는 상태에서 새로운 쓰레드를 만들면 Stack만 새로 만들어지고 나머지 부분은 공통으로 사용
- 각각의 thread를 위한 스택이 존재
쓰레드의 종료
- return으로 종료 됨, thread를 pthread_exit라는 함수를 불러서 명시적으로 종료시킴
- pthread_exit() : 종료되기를 기다리고 있는 어떤 쓰레드에게 retval값을 넘겨줄 수 있음 -> pthread_exit()를 하게 되면 프로그램 자체가 종료 되는 것이 아니라 다른 쓰레드들은 수행중임
- exit()는 프로세스 자체가 종료되므로 모든 쓰레드가 종료됨
- pthread_cancle()
- 종료하면서 넘겨주는 return값을 기다리는 함수 : pthread_join(3)
- thread가 종료되기를 기다림
- **retval : retrun값을 가져옴 -> 가져올 필요가 없다면 NULL로 설정
- 여러개가 종료되기를 기다리기 위해서는 각 쓰레드마다 join을 해야함
- 예제
- main thread가 수행되고 있다가 func이라는 함수를 수행하는 쓰레드가 생성됨
- pthread_join이라는 함수를 부름 -> mythread가 종료될 때 까지 기다림
- func가 만약 (void *)42를 return했다면 그 값을 i에 받아서 사용할 수 있음
- pthread_detach(3)
- 한 쓰레드가 종료했을 때 exit값을 받아가야 종료된 쓰레드에 관련된 자원들이 릴리즈 됨
- 그러나 쓰레드를 종료하는 것을 기다리지 않겠다고 선언하는 함수가 pthread_detach라는 함수
- thread에 종료될 thread를 넣으면 이 thread가 종료 될 때 기다리지 않고 바로 종료한다는 뜻
- 여러 쓰레드 생성 -> create
- 각 쓰레드가 종료 될 때마다 기다려서 return값을 가져옴
- 각 쓰레드를 기다리지 않음 -> pthread_detach()
'임베디드SW공학' 카테고리의 다른 글
[13주차]POSIX Threads(2) (0) | 2018.12.02 |
---|---|
[11주차]시그널과 타이머 (0) | 2018.11.27 |
[10주차]리눅스 시스템 프로그래밍:Processes (0) | 2018.11.19 |
[9주차]시스템 콜 파일(2) - 디렉토리 (0) | 2018.11.17 |
[8주차]리눅스시스템 프로그래밍: File I/O (0) | 2018.11.11 |