어떤 작업을 위해 실행할 수 있는 파일
-> 파일이 저장 장치에만 저장되어 있고, 메모리에는 올라가 있지 않은 정적인 상태
-> 즉, 아직 실행되지 않은 파일
모든 프로그램은 운영체제가 해당 프로그램을 위한 메모리 공간을 할당한 뒤, 자원을 할당해주어야 실행할 수 있다.
code
, data
, stack
, heap
의 형식으로 할당한다.컨텍스트 스위칭(Context Switching)
이라 한다.멀티 스레드
이다.PROS
: 하나의 프로세스에 문제가 생겨도 전체적인 프로그램은 동작한다.CONS
: 프로세스 끼리 공유하는 메모리가 없기 때문에 Context Switching
에 많은 비용이 발생한다.stack
을 따로 할당받으며, code
, data
, heap
영역을 공유한다.code
, data
, heap
영역을 공유하고, stack
영역은 별도로 관리한다.메인 스레드
라 부른다.멀티 스레드
라고 한다.code
, data
, heap
영역을 공유하기 때문에 어떤 스레드 하나라도 오류가 발생한다면 같은 프로세스 내의 다른 스레드까지 모두 강제로 종료된다.PROS
Context Switching
처리 비용이 감소한다code
, data
, heap
영역을 공유하므로, Context Switching
이 일어날 때 stack
영역만 처리하면 된다.code
, data
, heap
영역을 공유하므로 프로세스 간 통신(IPC)보다 스레드 간 통신 응답 속도가 빠르다.CONS
여러 스레드가 공유 변수를 함께 사용할 경우
발생할 수 있는 문제
-> 스레드1이 어떤 공유 변수를 사용하다가 스레드2로 제어권이 넘어간다.
-> 스레드2가 해당 공유 변수를 수정한 뒤 다시 스레드1로 제어권이 넘어간다.
-> 스레드1은 바뀐 공유 변수로 인해 오류가 발생할 수 있다.
스레드의 스케쥴링은 운영체제가 관리하지 않기 때문에, 설계할 때 주의하여 동기화 문제를 해결해야 한다.
Thread Safe
를 지키기 위한 방법은 네가지로 이루어진다Mutual Exclusion(상호 배제)
세마포어
/뮤텍스
로 락을 통제하는 방법Atomic operation(원자 연산)
lock
을 걸고, 데이터를 변경하는 시간 동안 다른 스레드의 접근이 불가능하도록 하는 방법Thread-local storage(스레드 지역 저장소)
Re-entrancy(재진입성)
MUTual EXclusion(상호 배제)
의 줄임말로, 동시 프로그래밍에서 공유 불가능한 자원의 동시 사용을 피하기 위해 사용한다.critical section(임계 영역)
을 만들고, 임계 영역 내에 단 하나의 스레드만이 진입 가능하도록 하는 방식이다.key
에 해당하는 어떤 객체(object)
가 있으며, 이 객체를 소유한 스레드/프로세스만이 공유 자원에 접근할 수 있다.동기화(Synchronization)
또는 락(lock)
을 사용한다. #include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
스레드
를 생성하는 함수0
을 리턴하고 실패 시 에러 코드
를 리터한다.EAGAIN
: 스레드 생성을 위한 자원이 부족하거나, PTHREAD_THREADS_MAX
를 초과하여 스레드 생성을 요청하는 경우thread
: 이곳에 스레드의 식별자
가 저장됨attr
: 스레드와 관련된 특성을 지정하기 위한 용도로 사용됨start_routine
: 새로운 스레드는 arg
를 매개변수로 하는 start_routine
함수를 실행시키면서 생성된다. 생성된 스레드는 pthread_exit(3)
을 호출하거나 함수 내에서 return
하는 경우 제거된다.arg
: start_routine
함수의 매개변수로 들어간다. 분기될 함수 내에서 원하는 자료형을 캐스팅해야 한다. #include <pthread.h>
int pthread_join(pthread_t thread, void **thread_return);
pthread_exit(3)
으로 종료되거나 return
되는 경우 발생한다.pthread_join()
으로 자원을 해제해야 메모리 누수가 발생하지 않는다.pthread_join()
은 pthread_create()
의 두 번째 매개변수인 attr
이 joinable(default)
상태의 스레드로 작동하고 detached
상태가 아니어야 사용 가능하다.0
, 실패 시 에러 코드
를 반환한다.ESRCH
: 식별번호 thread
가 잘못된 식별번호인 경우EINVAL
: 식별번호 thread
가 detached
상태인 경우thread
: 스레드의 TID
thread_return
: 스레드 함수에 리턴 값이 있다면 이 변수로 전달된다. 없다면 NULL
을 입력한다. #include <pthread.h>
int pthread_detach(pthread_t thread);
thread
를 가지는 스레드를 메인 스레드에서 분리시킨다. 이는 thread
를 가지는 스레드가 종료되는 즉시 스레드의 모든 메모리를 해제해 줄 것을 보증한다.detached
상태가 아닌 경우 pthread_join(3)
을 호출하지 않는 한 메모리를 해제하지 않는다. 반드시 pthread_join()으로 메모리를 해제할 것.pthread_detach()
를 호출하는 것 외에도 pthread_create()
시 pthread_attr_t
에 detachstate
를 지정해줌으로써 detached
상태로 스레드를 생성할 수도 있다.pthread_attr_t
는 pthread_attr_int(3)
함수를 통해 변경할 수 있다.0
, 실패 시 에러 코드
반환ESRCH
: thread
식별자를 가진 스레드가 존재하지 않는다.EINVAL
: thread
식별자를 가진 스레드가 이미 detached
상태에 있다. #include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutex_attr *attr);
뮤텍스 객체
를 초기화
시키기 위해서 사용한다.fast
, recursive
, error checking
3가지 중 하나를 선택할 수 있으며, 기본적으로는 fast
가 사용된다.0
, 실패 시 에러 코드
반환EINVAL
: 뮤텍스가 제대로 초기화되지 않은 경우EDEADLK
: 뮤텍스가 이미 잠긴 경우(error checking
뮤텍스에서만 발생한다)mutex
: 초기화시킬 뮤텍스 객체
attr
: 초기화 시킬 때 뮤텍스의 특징을 정의할 수 있는데, attr
을 통해서 이루어진다. 기본 특징을 이용하고 싶다면 NULL
을 입력한다. #include <pthread.h>
int pthread_mutex_destroy(pthread_mutex_t *mutex);
mutex
가 가리키는 뮤텍스 객체를 제거
한다.free()
하기 전 pthread_mutex_destroy()
를 먼저 호출 해야한다.pthread_mutex_destroy()
를 사용하기 위해서는 뮤텍스가 반드시 잠금이 해제
된 상태여야 한다.0
, 실패 시 에러 코드
반환EINVAL
: 지정한 뮤텍스 객체가 유효하지 않은 경우EBUSY
: 지정한 뮤텍스 객체가 다른 스레드에 의해 잠겨있는 경우mutex
: 제거할 뮤텍스 객체 #include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);
잠금을 요청
한다.0
, 실패 시 에러 코드
반환EINVAL
: 뮤텍스가 잘못 초기화된 경우EDEADLK
: 이미 잠금을 얻은 스레드가 다시 잠금을 요청할 때(error checking 뮤텍스인 경우 사용 가능) #include <pthread.h>
int pthread_mutex_unlock(pthread_mutex_t *mutex);
잠금을 해제
한다.fast
의 경우 언제나 잠금을 해제한다.recursive
의 경우 잠겨있는 뮤텍스의 수를 감소시키고, 이 수가 0
이 된다면 잠금을 해제한다.0
, 실패 시 에러 코드
반환EINVAL
: 지정한 뮤텍스 객체 mutex
가 NULL
이거나 유효한 객체가 아닌 경우EPERM
: 지정한 뮤텍스 객체가 호출한 스레드에 의해 잠기지 않았을 경우 #include <sys/time.h>
int gettimeofday(struct timeval *tv, struct timezone *tz);
1970-01-01 00:00:00 +0000(UTC)
이후의 현재가지 경과된 초와 micro초(백만분의 1초) 값을 얻는 함수.tz
는 사용되지 않는다.0
, 실패 시 에러코드
반환EFAULT
: tv
또는 tz
의 메모리 영역이 유효하지 않은 경우tv
struct timeval
{
time_t tv_sec; // seconds(long)
suseconds_t tv_usec; // microseconds(int)
}
ref
program, process, thread https://wooono.tistory.com/522
create https://www.joinc.co.kr/w/man/3/pthread_create
join https://www.joinc.co.kr/w/man/3/pthread_join
detach https://www.joinc.co.kr/w/man/3/pthread_detach
mutex_init https://www.joinc.co.kr/w/man/3/pthread_mutex_init
lock, unlock https://www.joinc.co.kr/w/man/3/pthread_mutex_lock
gettimeofday https://www.it-note.kr/130