익명 사용자
로그인하지 않음
계정 만들기
로그인
youngwiki
검색
Posix Threads 문서 원본 보기
youngwiki
이름공간
문서
토론
더 보기
더 보기
문서 행위
읽기
원본 보기
역사
←
Posix Threads
문서 편집 권한이 없습니다. 다음 이유를 확인해주세요:
요청한 명령은 다음 권한을 가진 사용자에게 제한됩니다:
사용자
.
문서의 원본을 보거나 복사할 수 있습니다.
상위 문서: [[Concurrent Programming]] ==개요== Pthreads(Posix threads)는 C 프로그램에서 쓰레드(thread)를 조작하기 위한 표준적인 인터페이스이다. Pthreads는 프로그램이 쓰레드를 생성하고, 종료시키며, 수거할 수 있도록 하며, 또한 피어(peer) 쓰래드들과 데이터를 안전하게 공유하며, 시스템 상태 변화에 대해 피어들에게 알리도록 하는 약 60개 정도의 함수를 정의한다. 아래는 간단한 Pthreads 프로그램을 보여준다: <syntaxhighlight lang="c"> #include "csapp.h" void *thread(void *vargp); int main() { pthread_t tid; Pthread_create(&tid, NULL, thread, NULL); Pthread_join(tid, NULL); exit(0); } void *thread(void *vargp) { /* Thread routine */ printf("Hello, world!\n"); return NULL; } </syntaxhighlight> 위에서 메인 쓰레드는 하나의 피어 쓰레드를 생성하고, 그 쓰레드가 종료할 때까지 기다린다. 피어 쓰레드는 "Hello, world!\n"을 출력하고 종료된다. 메인 쓰레드가 동료 쓰레드의 종료를 감지하면, exit을 호출하여 프로세스를 종료한다. 좀 더 자세히 살펴보면, 피어 쓰레드에서 사용되는 코드와 로컬 데이터는 쓰레드 루틴 내<ref>void *thread(void *vargp);에 해당한다.</ref>에 캡슐화되어 있다. 2번째 줄에 있는 프로토타입이 보여주듯이, 각 쓰레드 루틴은 하나의 일반 포인터(generic pointer)를 입력으로 받고, 일반 포인터를 반환한다. 만약 여러 개의 인자를 쓰레드 루틴에 전달하고자 한다면, 인자들을 구조체에 넣고 그 구조체에 대한 포인터를 전달하면 된다. 마찬가지로, 쓰레드 루틴이 여러 값을 반환하게 만들고자 할 때에도 구조체에 대한 포인터를 반환하면 된다. main 함수는 메인 쓰레드의 코드가 시작되는 부분을 포함한다. 메인 쓰레드는 지역 변수 tid를 선언하며, 이는 피어 쓰레드의 TID(Thread ID)를 저장하는데 사용된다. 그리고 메인 쓰레드는 <code>pthread_create()</code> 함수를 호출하여 새로운 피어 쓰레드를 호출한다. 해당 함수의 호출이 리턴되면, 메인 쓰레드와 새롭게 생성된 피어 쓰레드는 동시에 실행되며, tid에는 피어 프로세스의 TID가 저장된다. 그리고 메인 쓰레드는 <code>pthread_join()</code> 함수를 호출하여 피어 쓰레드가 종료될 때까지 기다린다. 마지막으로, 메인 쓰레드는 <code>exit()</code>을 호출하여 프로세스를 종료한다. ==Creating Threads== 쓰레드는 <code>pthread_create()</code> 함수를 호출하여 다른 쓰레드를 생성한다: <syntaxhighlight lang="c"> #include <pthread.h> typedef void *(func)(void *); //반환값: 성공 시 0, 오류시 0이 아닌 값 int pthread_create(pthread_t *tid, pthread_attr_t *attr, func *f, void *arg); </syntaxhighlight> <code>pthread_create()</code> 함수는 새로운 쓰레드를 생성하고, 새 쓰레드의 컨텍스트(context)에서 쓰레드 루틴을 함수 포인터 f와 해당 함수의 인자를 저장하는 일반 포인터 arg를 통해 생성한다. 또한 attr 인자는 새로 생성된 쓰레드의 기본 속성을 변경하는데 사용되며, 기본적으로는 NULL을 사용한다. <code>pthread_create()</code>가 반환되면, 인자인 tid에는 새로 생성된 쓰레드의 TID가 저장된다. 이때 각 쓰레드는 아래와 같이 <code>pthread_self</code> 함수를 호출하여 자신의 TID를 알아낼 수 있다. <syntaxhighlight lang="c"> #include <pthread.h> //반환값: 호출자의 TID pthread_t pthread_self(void); </syntaxhighlight> ==Terminating Threads== 쓰레드는 다음 중 하나의 방식으로 종료된다: * 최상위 쓰레드 루틴이 반환될 때, 암묵적으로 해당 쓰레드는 종료된다.<ref>해당 쓰레드들로부터 생성된 쓰레드들은 영향받지 않는다. 쓰레드 사이에는 부모-자식 관계가 없기 때문이다.</ref> ** 최상위 쓰레드 루틴이 반환된다는 것은 쓰레드가 처음 실행을 시작할 때 지정된 함수가 리턴을 통해 실행을 마친다는 뜻이다. * <code>pthread_exit()</code> 함수를 호출하여 명시적으로 종료된다. ** thread_return 인자는 쓰레드가 종료될 때 <code>pthread_join()</code> 함수를 통해 기다리고 있는 쓰렏드에게 반환하고자 하는 값을 전달하는 포인터이다. ** 메인 쓰레드가 <code>pthread_exit()</code> 함수를 호출하면, 다른 피어 쓰레드들이 종료될 때까지 기다린 후, 메인 쓰레드와 전체 프로세스를 thread_return 값과 함께 종료시킨다. <syntaxhighlight lang="c"> #include <pthread.h> void pthread_exit(void *thread_return); </syntaxhighlight> * 어떤 피어 쓰레드가 <code>exit()</code> 함수를 호출하면, 해당 프로세스와 그에 속한 모든 쓰레드가 종료된다. * 다른 피어 쓰레드가 <code>pthread_cancel()</code> 함수를 호출하면서 어떤 쓰레드의 TID를 인자로 전달하면, 해당 쓰레드가 종료된다. <syntaxhighlight lang="c"> #include <pthread.h> //반환값: 성공 시 0, 실패 시 0이 아닌 값 int pthread_cancel(pthread_t tid); </syntaxhighlight> ==Reaping Terminated Threads== 쓰레드는 <code>pthread_join()</code> 함수를 호출하여 다른 쓰레드가 종료될 때까지 기다린다: <syntaxhighlight lang="c"> #include <pthread.h> //반환값: 성공 시 0, 오류 시 0이 아닌 값 int pthread_join(pthread_t tid, void **thread_return); </syntaxhighlight> <code>pthread_join()</code> 함수는 tid에 해당하는 쓰레드가 종료될 때까지 해당 함수를 호출한 쓰레드를 블록(block)시키며, tid 쓰레드 루틴이 반환한 일반 포인터(void *) 값을 thread_return이 가리키는 위치에 할당하고, 종료된 쓰레드가 점유하고 있던 메모리 자원들을 수거한다. 이때 리눅스의 <code>wait()</code> 함수와는 달리, <code>pthread_join()</code> 함수는 특정한 쓰레드의 종료를 기다리는 작업만 할 수 있다. ==Detaching Threads== 쓰레드는 항상 조인 가능(joinable)하거나 분리(detatched) 상태이다. 조인 가능한 쓰레드는 다른 쓰레드에 의해서 수거되고 종료될 수 있으며, 해당 쓰레드의 스택과 같은 자원은 다른 쓰레드에 의해서 수거되기 전까지는 해제되지 않는다. 반면, 분리된 쓰레드는 다른 쓰레드에 의해 수거되거나 종료될 수 없으며, 해당 쓰레드가 종료되면 메모리 자원은 시스템에 의해서 자동으로 해제된다. 기본적으로 쓰레드는 조인 가능한 상태로 생성되며, 메모리 누수를 방지하기 위해서는 조인 가능한 쓰레드를 명시적으로 다른 쓰레드에 의해서 수거되도록 하거나, <code>pthread_detach()</code> 함수를 호출하여 분리된 쓰레드로 변경해야 한다: <syntaxhighlight lang="c"> #include <pthread.h> //반환값: 성공 시 0, 오류 시 0이 아닌 값 int pthread_detach(pthread_t tid); </syntaxhighlight> <code>pthread_detach()</code> 함수는 조인 가능한 쓰레드 tid를 분리된 쓰레드로 만든다. 이때 쓰레드는 <code>pthread_self()</code> 함수의 반환값을 인자로 하여 <code>pthread_detach()</code> 함수를 통해 자신의 상태를 변경할 수도 있다. ==Initializing Threads== <code>pthread_once()</code> 함수는 쓰레드 루틴과 관련된 상태를 초기화할 수 있도록 한다: <syntaxhighlight lang="c"> #include <pthread.h> pthread_once_t once_control = PTHREAD_ONCE_INIT; //항상 0을 반환 int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)); </syntaxhighlight> once_control 변수는 전역(global)이나 정적(static)으로 선언되며, 항상 PTHREAD_ONCE_INIT으로 초기화된다. <code>once_control</code>을 인자로 하여 <code>pthread_once()</code> 함수를 처음 호출하면, 어떤 초기화 함수인 <code>init_routine()</code> 함수가 호출된다. 이후 동일한 once_control 변수로 <code>pthread_once()</code> 함수를 다시 호출하면 아무 일도 일어나지 않는다. <code>pthread_once()</code> 함수는 여러 쓰레드가 초기화 작업을 동시에 실행하더라도, 특정 초기화 함수가 단 한번만 실행되도록 보장한다. 따라서, 여러 쓰레드가 공유하는 전역 변수를 동적으로 초기화해야 할 때 유용하다. ==각주== [[분류:컴퓨터 시스템]]
Posix Threads
문서로 돌아갑니다.
둘러보기
둘러보기
대문
최근 바뀜
임의의 문서로
미디어위키 도움말
위키 도구
위키 도구
특수 문서 목록
문서 도구
문서 도구
사용자 문서 도구
더 보기
여기를 가리키는 문서
가리키는 글의 최근 바뀜
문서 정보
문서 기록