1 / 58

POSIX thread

POSIX thread. SSLab. 신장열. CONTENTS. Thread 의 생성 및 종료 Join and detach Cleanup handler Mutex Condition variable Thread signal Thread cancel. pthread_create (). Arguments pthread_t *th 생성된 thread 에 대한 식별자 (identifier) 에 대한 구조체 pointer pthread_attr_t *attr

cgoodrich
Download Presentation

POSIX thread

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. POSIX thread SSLab. 신장열

  2. CONTENTS • Thread의 생성 및 종료 • Join and detach • Cleanup handler • Mutex • Condition variable • Thread signal • Thread cancel

  3. pthread_create () • Arguments • pthread_t *th • 생성된 thread에 대한 식별자(identifier)에 대한 구조체 pointer • pthread_attr_t *attr • thread 의 특성을 지정하기 위해 사용, default thread를 사용하면 NULL • void *(start_routine)(void *) • 분기 시켜서 실행할 thread 함수 • void *arg • start_routine 함수에 넘겨줄 argument • Return value • 성공하면 0을 return, 에러가 발생하면 non-zero를 return하고 errno를 설정 • errno • EAGAIN – 새 thread에 할당할 자원(thread 개수제한 포함)이 없거나 이미 생성된 thread #include <pthread.h> int pthread_create ( pthread_t *th, const pthread_attr *attr, void *(*start_routine)(void *), void *arg )

  4. pthread_exit () • 현재 실행중인 thread를 종료 • cleanup handler • pthread_cleanup_push로 cleanup handler가 정의되어 있다면 pthread_exit가 내부적으로 호출 • Arguments • void *retval • Thread가 종료할 때의 return value #include <pthread.h> void pthread_exit(void *retval);

  5. Example 1 #include <stdio.h> #include <string.h> #include <pthread.h> pthread_t threads[5]; int done[5]; void *thread_main(void *); int main(void) { int i; int rc; int status; printf("pid=%d\n", getpid()); for (i = 0; i < 5; i++) { done[i] = 0; pthread_create(&threads[i], NULL, &thread_main, (void *)i); printf("%d, %d\n", i, threads[i]); }

  6. Example 1 for (i = 4; i >= 0; i--) { done[i] = 1; rc = pthread_join(threads[i], (void **)&status); if (rc == 0) { printf("Completed join with thread %d status= %d\n",i, status); } else { printf("ERROR; return code from pthread_join() is %d, thread %d\n", rc, i); return -1; } } return 0; }

  7. Example 1 void *thread_main(void *arg) { int i; double result=0.0; printf("thread: %d, %d\n", (int)arg, getpid()); while (!done[(int)arg]) { for (i=0; i < 1000000; i++) { result = result + (double)random(); } printf("thread: %d, result = %e\n", (int)arg, result); } pthread_exit((void *) 0); }

  8. Example 1

  9. Join and Detach • Join • pthread_join을 호출한 thread는 thread에 대한 종료를 기다림 • Thread는 자신의 종료상태를 main thread에 통보 • Detach • Thread가 프로세스와 분리 • 자신이 사용했던 자원을 바로 반납 • Thread가 어떻게 종료되던지 상관이 없게 되었을 때 detach시킨다.

  10. pthread_join () • waitpid ()와 유사, thread가 종료하기를 기다린다. • Arguments • pthread_t thread • join할 thread identifier • void **thread_return • thread의 return value • Return value • 성공하면 0, 에러가 발생하면 non-zero를 return하고 errno를 설정 • errno • ESRCH – th에 해당하는 thread를 찾을 수 없다 • EINVAL – thread가 detatch되었거나 다른 thread가 이미 waiting 중 • EDEADLK – th가 자기 자신일 때 #include <pthread.h> int pthread_join(pthread_t th, void **thread_return);

  11. pthread_detach () • thread를 분리시킨다. 분리된 thread는 pthread_join ()으로 기다릴 수 없다. • Arguments • pthread_t th • detach된 thread는 pthread_join을 호출하지 않아도 자동으로 모든 resource가 free된다. • Return value • 성공하면 0, 에러가 발생하면 non-zero를 return하고 errno를 설정 • errno • ESRCH – th에 해당하는 thread를 찾을 수 없다 • EINVAL – thread 가 이미 detach되어 있다. #include <pthread.h> int pthread_detach(pthread_t th);

  12. pthread_self () • Return value • 자기 자신의 thread identifier를 return #include <pthread.h> pthread_t pthread_self ( void );

  13. Example 2 #include <stdio.h> #include <string.h> #include <pthread.h> pthread_t threads[5]; int done[5]; void *thread_main(void *); int main(void) { int i; int rc; int status; printf("pid=%d\n", getpid()); for (i = 0; i < 5; i++) { done[i] = 0; pthread_create(&threads[i], NULL, &thread_main, (void *)i); printf("%d, %d\n", i, threads[i]); }

  14. Example 2 for (i = 4; i >= 0; i--) { done[i] = 1; rc = pthread_join(threads[i], (void **)&status); /* detach thread에서는 사용할 필요 없다. */ if (rc == 0) { printf("Completed join with thread %d status= %d\n",i, status); } else { printf("ERROR; return code from pthread_join() is %d, thread %d\n", rc, i); return -1; } } // sleep(5); return 0; }

  15. Example 2 void *thread_main(void *arg) { int i; double result=0.0; pthread_detach(pthread_self()); /* 쓰레드 분리 */ printf("thread: %d, %d\n", (int)arg, getpid()); while (!done[(int)arg]) { for (i=0; i < 1000000; i++) { result = result + (double)random(); } printf("thread: %d, result = %e\n", (int)arg, result); } pthread_exit((void *) 0); }

  16. Example 2

  17. Example 2

  18. Cleanup handler • thread를 일종의 객체로 생각하면 객체의 destructor(소멸자)와 동일 • 객체가 할당 받은 자원을 시스템에 돌려준다 • Lock중인 mutex를 unlock • malloc()등으로 할당받은 memory를 free • File descriptor나 socket등도 close

  19. pthread_cleanup_push () • Cleanup handler를 등록 • Arguments • void (*routine) (void *) • cleanup handler • void *arg • Cleanup handler function의 arguments • cleanup handler • 할당받은 resource를 되돌려주거나 mutex lock등을 해제 #include <pthread.h> void pthread_cleanup_push ( void (*routine) (void *), void *arg );

  20. pthread_cleanup_pop () • 등록된 cleanup handler를 제거 • Arguments • int excute • 0이 아니면 cleanup handler를 실행 • 0이면 실행시키지 않고 제거 #include <pthread.h> void pthread_cleanup_pop ( int execute );

  21. Mutex • Pthread 자체에서 제공하는 동기화 기법 • MUTual EXclusion 의 약자 • Lock or unlock (Binary Semaphore) • Mutex를 사용할 때 주의할 점 • Deadlock • mutex의 파괴 • 다른 thread가 lock한 mutex를 unlock • 간단한 뮤텍스 생성 방법 • pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

  22. pthread_mutex_init () • Mutex를 초기화 • Arguments • pthread_mutex_t *mutex • 초기화할 mutex 객체 • pthread_mutex_attr *attr • Mutex에 지정할 attribute. Default는 NULL • Return Value • 항상 0을 return #include <pthread.h> int pthread_mutex_init (pthread_mutex_t *mutex, pthread_mutex_attr *attr );

  23. pthread_mutex_destroy () • Arguments • pthread_mutex_t *mutex • identifier에 해당하는 mutex를 제거한다. • Lock되어있는 mutex는 제거할 수 없다. • Return Value • 성공하면 0, 실패하면 non-zero을 return하고 errno를 설정 • errno • EBUSY – mutex가 현재 lock되어있다. #include <pthread.h> int pthread_mutex_destroy ( pthread_mutex_t *mutex );

  24. pthread_mutex_lock () • mutex를 lock중이면 mutex가 unlock될 때까지 block된다. • Arguments • pthread_mutex_t *mutex • mutex identifier에 해당하는 mutex를 lock한다. • Return Value • 성공하면 0, 실패하면 non-zero을 return하고 errno를 설정 • errno • EINVAL – mutex가 제대로 초기화 되어 있지 않다. • EDEADLK - 이미 잠금을 얻은 쓰레드가 다시 잠금을 요청할 때 #include <pthread.h> int pthread_mutex_lock ( pthread_mutex_t *mutex );

  25. pthread_mutex_trylock () • pthread_mutex_lock의 nonblocking 버젼 • Arguments • pthread_mutex_t *mutex • mutex identifier에 해당하는 mutex에 lock을 시도한다. • Return Value • 성공하면 0, 실패하면 non-zero을 return하고 errno를 설정 • errno • EBUSY - mutex가 잠겨 있어서 잠금을 얻을 수 없다. • EINVAL - mutex가 잘못 초기화 되었다. #include <pthread.h> int pthread_mutex_trylock ( pthread_mutex_t *mutex );

  26. pthread_mutex_unlock () • Arguments • pthread_mutex_t *mutex • mutex identifier에 해당하는 mutex를 unlock한다. • Return Value • 성공하면 0 을 return, 실패하면 non-zero을 return하고 errno를 설정 • errno • EINVAL – mutex가 제대로 초기화 되어있지 않다. • EPERM – mutex가 이 함수를 호출한 thread에게 lock되지 않았다. #include <pthread.h> int pthread_mutex_unlock ( pthread_mutex_t *mutex );

  27. Condition Variable • Thread 간의 signaling 기법 • 특정 event나 조건이 충족되었음을 하나 혹은 모든 thread에게 알림 • Mutex 잠금과 함께 사용되어 mutex를 자동으로 얻을 수 있다.

  28. pthread_cond_init () • Arguments • pthread_cond_t *cond • 초기화할 condition variable • const pthread_cond_attr *attr • condition variable의 attribute • Return value • 성공하면 0을 return • errno • EAGAIN – 새로운 condition variable을 할당할만한 resource가 부족 • ENOMEM – condition variable 을 초기화할 만한 memory가 부족 • EBUSY – 이미 초기화된 condition variable을 재초기화 • EINVAL – attr 변수의 attribute 지정이 잘못 #include <pthread.h> int pthread_cond_init( pthread_cond_t *cond, const pthread_cond_attr *attr );

  29. pthread_cond_destroy () • Arguments • pthread_cond_t *cond • 제거할 condition variable • Return value • 성공하면 0을 return • errno • EBUSY – pthread_cond_wait()나 pthread_cond_timedwait())을 이용해 다른 thread가 condition variable을 기다리고 있음 • EINVAL – cond의 값이 잘못되었다. #include <pthread.h> int pthread_cond_destroy ( pthread_cond_t *cond );

  30. pthread_cond_signal () • Condition variable에 signal을 보내 pthread_cond_timewait()이나 pthread_cond_wait()으로 기다리고 있던 thread를 하나 깨운다. (어느 것이 깨어날지는 알 수 없다.) • Arguments • pthread_cond_t *cond • Signal을 보낼 condition variable • Return value • 성공하면 0 을 return • errno • EINVAL – cond 값이 초기화 되지 않았다. #include <pthread.h> int pthread_cond_signal ( pthread_cond_t *cond );

  31. pthread_cond_broadcast () • Condition variable에 signal을 보내 pthread_cond_timewait()이나 pthread_cond_wait()으로 기다리고 있던 thread를 모두 깨운다. • Arguments • pthread_cond_t *cond • Signal을 보낼 condition variable • Return value • 성공하면 0을 return • errno • EINVAL – cond 값이 초기화 되지 않았다. #include <pthread.h> int pthread_cond_broadcast ( pthread_cond_t *cond );

  32. pthread_cond_wait () • 조건변수 cond로 시그널이 전달되기를 기다린다. • 시그널을 전달받아 쓰레드가 깨어나면 자동적으로 mutex lock을 획득 • Arguments • pthread_cond_t *cond • 기다릴 condition variables • pthread_mutex_t *mutex • Condition variable에 의해 lock을 얻을 mutex • Return value • 성공하면 0을 return • errno • EINVAL – 인자의 값이 잘못 초기화 되어있거나 같은 condition variable에 다른 mutex가 연결되었다. (pthread_cond_wait ()와 pthread_cond_timewait ()의 동시 사용의 경우) • EPERM – 현재 thread에 mutex가 주어지지 않았다. #include <pthread.h> int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex);

  33. pthread_cond_timewait • 지정된 시간까지 condition variable에 signal이 오기를 기다린다. • 그외에는 pthread_cond_wait와 거의 동일 • Return value • 성공하면 0을 return • errno • ETIMEDOUT – 지정된 시간이 지났다. • 참고 • abstime에 대해서는 time()와, gettimeofday()를 참고 #include <pthread.h> int pthread_cond_timewait ( pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime );

  34. Example 3 #include <pthread.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <vector> #include <iostream> using namespace std; void *ping(void *); void *pong(void *); pthread_mutex_t sync_mutex; pthread_cond_t sync_cond; pthread_mutex_t gmutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t gcond = PTHREAD_COND_INITIALIZER;

  35. Example 3 int main() { vector<void *(*)(void *)> thread_list; vector<pthread_t> tident(10); int thresult; int status; int i; pthread_mutex_init(&sync_mutex, NULL); pthread_cond_init(&sync_cond, NULL); thread_list.push_back(pong); thread_list.push_back(ping); for(i = 0; i < thread_list.size(); i++ ) { pthread_mutex_lock(&sync_mutex); if (pthread_create(&tident[i], NULL, thread_list[i], (void *)NULL) <0) { perror("error:"); exit(0); } pthread_cond_wait(&sync_cond, &sync_mutex); pthread_mutex_unlock(&sync_mutex); } for (i = 0; i < tident.size(); i++) { pthread_join(tident[i], (void **)&status); } }

  36. Example 3 void *ping(void *data) { int i=0; pthread_mutex_lock(&sync_mutex); pthread_cond_signal(&sync_cond); pthread_mutex_unlock(&sync_mutex); while(1) { pthread_mutex_lock(&gmutex); printf("%d : ping\n", i); pthread_cond_signal(&gcond); pthread_cond_wait(&gcond, &gmutex); pthread_mutex_unlock(&gmutex); usleep(random()%100); i++; } }

  37. Example 3 void *pong(void *data) { int i = 0; pthread_mutex_lock(&sync_mutex); sleep(1); pthread_cond_signal(&sync_cond); pthread_mutex_unlock(&sync_mutex); while(1) { pthread_mutex_lock(&gmutex); pthread_cond_wait(&gcond, &gmutex); printf("%d : pong\n", i); pthread_cond_signal(&gcond); pthread_mutex_unlock(&gmutex); i++; } }

  38. Example 3

  39. pthread_attr_init ()pthread_attr_destroy () • Thread에 대한 속성을 초기화하거나 제거한다. • Arguments • pthread_attr_t *attr • Thread에 대한 속성 변수 • Return value • 성공하면 0을 return • errno • ENOMEM – thread attribute에 할당할 memory가 부족 #include <pthread.h> int pthread_attr_init ( pthread_attr_t *attr ); int pthread_attr_destroy ( pthread_attr_t *attr );

  40. pthread_attr_getscope () pthread_attr_setscope () • Thread에 대한 scope 속성을 알아내거나 혹은 세팅한다. • Arguments • int *scope • attr에서 Scope를 받아올 변수 • int *contentionscope • attr에 세팅할 scope • Return value • 성공하면 0을 return • errno • EINVAL – contentionscope의 값이 잘못되었다. • ENOTSUP – 지원되지 않은 value로 set하려고 했다. #include <pthread.h> int pthread_attr_getscope (const pthread_attr_t *attr, int *scope); int pthread_attr_setscope (pthread_attr_t *attr, int contentionscope);

  41. pthread_attr_getdetachstate ()pthread_attr_setdetachstate () • Arguments • const pthread_attr_t *attr, pthread_attr_t *attr • thread의 attr를 가지고 있는 변수 • int *detachstate , int detachstate • 값을 얻어 오거나 설정 • Return value • 성공하면 0을 return • errno • EINVAL – detachstate의 값이 잘못되었다. #include <pthread.h> int pthread_attr_getdetachstate ( const pthread_attr_t *attr, int *detachstate ); int pthread_attr_setdetachstate ( pthread_attr_t *attr, int detachstate );

  42. pthread_sigmask () • 특정 thread만 특정 signal을 받도록 할 수 있다. • Arguments • int how • SIG_BLOCK – 지금 현재의 값에 newmask된 값 부분만 block • SIG_UNBLOCK – 지금 현재의 값에 newmask된 값 부분만 unblock • SIG_SETMASK – 현재 thread의 mask를 newmask로 교체 • sigset_t *newmask • sigset_t *oldmask • Return value • 성공하면 0 • errno • EINVAL – how의 값이 잘못되었다. • 참조 • sigsetmask (), sigemptyset (), sigfillset (), sigaddset (), sigaction () #include <pthread.h> #include <signal.h> int pthread_sigmask(int how, const sigset_t *newmask, sigset_t *oldmask);

  43. pthread_kill () • 프로세스 내의 thread에 signal을 보낸다 • Arguments • pthread_t thread • Signal을 보낼 thread • int signo • Thread에 보낼 signal 번호 • Return value • 성공하면 0을 return • errno • ESRCH – 주어진 thread identifier에 맞는 thread를 찾을 수 없다 • EINVAL – signo의 값이 지원되지 않는 signal number이다. • 참조 • kill (), sigwait (), sigtimewait(), #include <pthread.h> #include <signal.h> int pthread_kill(pthread_t thread, int signo);

  44. Example 4 #include <pthread.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <stdio.h> pthread_t thread_t[3]; void sig_handler(int signo) { printf("Thread Stop %d:\n", (int)pthread_self()); sleep(100); } void null(int signo) { printf("Thread Start\n"); }

  45. Example 4 void *test(void *data) { sigset_t newmask; struct sigaction act, act2; int i = 0; sigemptyset(&newmask); sigaddset(&newmask, SIGUSR1); sigaddset(&newmask, SIGCONT); act.sa_handler = sig_handler; act2.sa_handler = null; sigaction(SIGUSR1, &act, NULL); sigaction(SIGCONT, &act2, NULL); pthread_sigmask(SIG_UNBLOCK, &newmask, NULL); while(1) { printf("Im child Thread %d %d\n", (int)pthread_self(),i); i++; sleep(1); } }

  46. Example 4 void *worker(void *data) { sigset_t newmask; sigemptyset(&newmask); sigaddset(&newmask, SIGUSR1); sigaddset(&newmask, SIGCONT); pthread_sigmask(SIG_BLOCK, &newmask, NULL); while(1) { sleep(2); pthread_kill(thread_t[0], SIGUSR1); sleep(3); pthread_kill(thread_t[0], SIGCONT); } } int main() { pthread_create(&thread_t[0], NULL, test, NULL); pthread_create(&thread_t[1], NULL, test, NULL); pthread_create(&thread_t[2], NULL, worker, NULL); pthread_join(thread_t[0], NULL); pthread_join(thread_t[1], NULL); return 1; }

  47. Example 4

  48. pthread_cancel () • Arguments • pthread_t thread • 강제로 종료시킬 thread의 identifier • 종료 요청을 받은 thread는 thread_exit(PTHREAD_CANCELD)를 수행 (cleanup handler도 당연히 수행됨) • 해당 thread의 return value는 PTHREAD_CANCELD • Return value • 성공하면 0 • errno • ESRCH • 쓰레드 식별자 thread를 가지는 쓰레드가 존재하지 않는다. #include <pthread.h> int pthread_cancel (pthread_t thread );

  49. pthread_setcancelstate () • Arguments • int state • PTHREAD_CANCEL_ENABLE – 이 thread를 cancel할 수 있음 • PTHREAD_CANCLE_DISABLE – 이 thread를 cancel할 수 없음 • int *oldstate • 바로 이전의 cancel state • Return value • 성공하면 0을 return • errno • state의 값이 PTHREAD_CANCEL_ENABLE 이나 PTHREAD_CANCEL_DISABLE가 아닐 때 #include <pthread.h> int pthread_setcancelstate(int state, int *oldstate);

  50. pthread_setcanceltype () • Arguments • int type • PTHREAD_CANCEL_DEFERRED – 바로 cancel됨 • PTHREAD_CANCLE_ASYNCHRONOUS – 취소지점까지 기다린다. • int *oldtype • 바로 이전의 cancel type • Return value • 성공하면 0을 return • errno • type의 값이 PTHREAD_CANCEL_DEFERRED 이나 PTHREAD_CANCEL_ASYNCHRONOUS가 아닐 때 #include <pthread.h> int pthread_setcanceltype(int type, int *oldtype);

More Related