치춘짱베리굿나이스

[Rank 3] Philosophers - 사용가능 함수 정리 [Mandatory] 본문

42/42s Cursus

[Rank 3] Philosophers - 사용가능 함수 정리 [Mandatory]

치춘 2021. 9. 4. 16:35

ㅡ추.추추추.추추추추.추추.추추추추추추.추추.추워

내가미쳐 진짜 마크다운 다깨지는거 돌겠네 노션짱 티스토리똥 💩💩💩💩💩💩💩💩💩💩💩💩


pthread.h

pthread_create

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
  • attr 변수에 저장된 속성대로 새 스레드를 현재 프로세스 내에 생성한다
    • attrNULL이면 디폴트 속성으로 생성된다
    • attr 내부 값이 중간에 변한다고 해서 이미 생성된 스레드의 속성이 변하진 않는다
  • 생성된 스레드는 start_routine에 지정된 함수 포인터에 해당하는 함수를 바로 실행시킨다
    • 만약 함수가 종료되면 (return 또는 라인 전부 실행완료) pthread_exit을 묵시적으로 호출한 것과 같은 동작을 한다
  • argstart_routine 함수의 인자값으로 들어갈 포인터
  • 제대로 동작했다면 (스레드가 생성되면) 0이 반환되고, 그 외의 경우엔 에러 코드가 반환된다
    • 에러 코드 EAGAIN: 시스템상에 스레드를 생성할 만큼의 자원이 없거나, 시스템이 지원하는 총 스레드 개수에 도달하여 또 다른 스레드를 생성할 수 없는 경우
    • 에러 코드 EPERM: 이 함수를 호출한 프로세스에게 스케줄링 인자를 건드릴 수 있는 권한이 없는 경우
    • 에러 코드 EINVAL: attr에 지정한 값이 유효하지 않을 때

pthread_detach

int pthread_detach(pthread_t thread);
  • pthread_create로 생성된 스레드는 종료할 때 사용했던 자원들을 해제하지 않으므로 프로세스에서 계속 자원을 잡아먹고 있는 것처럼 표시되는데, pthread_detachpthread_join을 이용하면 스레드 종료 시점에 자원이 반납된다
    • 반대로 얘기하면, pthread_detachpthread_join을 사용하지 않으면 메모리 누수 우려 있음
  • 스레드가 종료되지 않을 때는 효과가 없다 (pthread_detach가 스레드를 종료시킨다던가 하진 않는다)
  • pthread_detach가 한 스레드를 타겟으로 여러 번 호출되는 행동은 정의되지 않은 행동으로 간주된다
  • threadpthread_detach를 적용할 스레드
  • 제대로 동작했다면 0이 반환되고, 그 외의 경우엔 에러 코드가 반환된다
    • 에러 코드 EINVAL: 지정한 스레드가 join 불가능하다
    • 에러 코드 ESRCH: 변수에 지정한 스레드가 존재하지 않는다

pthread_join

int pthread_join(pthread_t thread, void **value_ptr);
  • pthread_detach와 마찬가지로 지정한 스레드가 종료되기 전까지 대기했다가, 스레드가 종료되면 스레드가 사용하였던 모든 자원을 반납하도록 한다
    • pthread_detach와의 차이점
      • pthread_join은 blocking 함수로, 메인 스레드에서 join을 호출하면 메인 스레드의 다음 코드 내용이 바로 실행되지 않는다. (join 함수에 인자로 넣은 스레드가 모두 종료될 때까지 메인 스레드가 대기한다)
      • 또한 메인 스레드가 종료되면 다른 스레드의 종료 여부와 상관없이 (대기하지 않고) 바로 자원이 회수되어 버린다
      • pthread_detach는 non-blocking 함수이고, 스레드에 연결된 함수의 리턴값은 받아올 수 없다
      • 또한 value_ptr을 통해 스레드 동작 함수의 리턴값을 받아와서 이를 이용할 수 있음
    • 지정한 스레드가 종료되기 전까지 기다린다는 것은 : 해당 함수를 호출한 스레드가 thread에 지정된 스레드가 종료될 때까지 pthread_join 함수는 실질적으로 동작하지 않는다
      • thread에 지정된 스레드가 같이 연결된 함수의 실행을 끝내면 pthread_join 함수를 통해 모든 자원을 반납한다는 의미
  • pthread_join이 한 스레드를 타겟으로 여러 번 호출되는 행동은 정의되지 않은 행동으로 간주된다
  • threadpthread_join을 적용할 스레드, value_ptrthread 스레드가 종료될 때 발생하는 리턴값이 담기는 포인터
  • 제대로 동작했다면 (스레드가 정상적으로 종료되었다면) 0이 반환되고, 그 외의 경우엔 에러 코드가 반환된다
    • 에러 코드 EINVAL: 지정한 스레드가 join 불가능하다
    • 에러 코드 ESRCH: 변수에 지정한 스레드가 존재하지 않는다
    • 에러 코드 EDEADLK: 스레드가 데드락에 걸림
 

[Rank 3] 철학자 - Joined & Detached 스레드 예제

스레드 함수 예제와 다르게 이번에는 메인 스레드와 별개의 스레드에서 하위 스레드를 생성하여 두 속성의 차이를 확인해보았다 pthread_join /* **************************************************************..

chichoon.tistory.com

pthread_mutex_init

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
  • attr 속성을 부여한 새로운 뮤텍스를 생성한다
    • attrNULL이면 디폴트 속성으로 생성된다
  • 제대로 동작했다면 (뮤텍스 생성이 성공하면) 0을 리턴하며 *mutex 인자에 뮤텍스의 아이디가 담긴다. 그 외의 경우엔 에러 코드가 반환된다
    • 에러 코드 EINVAL: attr에 지정한 값이 유효하지 않을 때
    • 에러 코드 ENOMEM: 뮤텍스를 새로 생성할 만큼 시스템에 메모리가 충분하지 않을 때

pthread_mutex_destroy

int pthread_mutex_destroy(pthread_mutex_t *mutex);
  • 지정한 mutex 포인터에 담긴 뮤텍스의 자원을 모두 해제한다
  • 제대로 동작했다면 (해제가 잘 되었다면) 0을 리턴하며, 그 외의 경우엔 에러 코드가 반환된다
    • 에러 코드 EINVAL: 지정한 뮤텍스 인자 mutex가 유효하지 않을 때
    • 에러 코드 EBUSY: 뮤텍스가 잠긴 상태

pthread_mutex_lock

int pthread_mutex_lock(pthread_mutex_t *mutex);
  • 지정한 mutex 포인터에 담긴 뮤텍스를 잠근다
    • 이미 잠겨 있다면, 해당 함수를 호출한 스레드는 뮤텍스 잠금이 해제될 때까지 블락된다
  • 제대로 동작했다면 (뮤텍스가 잘 잠겼다면) 0을 리턴하며, 그 외의 경우엔 에러 코드가 반환된다
    • 에러 코드 EINVAL: 지정한 뮤텍스 인자 mutex가 유효하지 않을 때
    • 에러 코드 EDEADLK: 현재 스레드가 뮤텍스를 기다리기 위해 블락될 경우, 데드락의 우려가 있음

pthread_mutex_unlock

int pthread_mutex_unlock(pthread_mutex_t *mutex);
  • 만약 현재 스레드가 지정한 mutex 포인터에 담긴 뮤텍스를 소유할 경우 (hold), 뮤텍스의 잠금을 해제한다
    • 스레드가 잠구지 않은 뮤텍스를 건드릴 경우는 정의되지 않은 행동으로 간주된다
  • 제대로 동작했다면 (뮤텍스 잠금이 잘 해제되었다면) 0을 리턴하며, 그 외의 경우엔 에러 코드가 반환된다
    • 에러 코드 EINVAL: 지정한 뮤텍스 인자 mutex가 유효하지 않을 때
    • 에러 코드 EPERM: 지정한 뮤텍스 인자 mutex가 현재 스레드가 소유 (hold) 한 뮤텍스가 아닐 때

sys/time.h

gettimeofday

int gettimeofday(struct timeval *restrict tp, void *restrict tzp);
  • 구조체 tp와 함께 사용된다
    • 해당 함수를 이용하여 tp 구조체를 세팅하면 tp.tv_sec에 초단위 시간, tv_usec에 마이크로초단위 시간이 들어간다
    • tv_sec은 1970년 1월 1일부터 현재 시각까지의 초가 long 타입으로 저장되어 있고, tv_usec은 이전 초부터 흐른 마이크로초가 int 타입으로 저장된다 (마이크로초는 초의 100만분의 1이기 때문에, tv_usec은 0부터 99만 9999까지의 수)
    • 이를 이용하여 코드 수행 시간을 재거나, 라인과 라인 사이의 시간 간격 등을 초 / 마이크로초 단위로 측정할 수 있다
  • 구조체 tzp는 timezone 관련 변수가 들어가도록 선언되어 있는데, GNU/Linux 환경에서는 쓸모가 없어져서 (obsolete) NULL로 세팅하는 것이 추천된다
  • 제대로 동작했다면 (시간을 잘 불러왔다면) 0이 반환되고, 그 외에 (에러상황) -1이 반환되며 errno 전역변수에 에러 코드가 저장된다

stdio.h

printf

int printf(const char *restrict format, ...);
  • 마참내! 프린트에프를 쓸 수 있게 되었다
  • format에 출력할 문자열이 들어가고, 중간 중간 변수로 대체될 플래그는
  • [%[플래그][폭][.정밀도][길이]서식지정자] 의 형식으로 작성된다

string.h

memset

void *memset(void *b, int c, size_t len);
  • b 포인터를 시작점으로 하여, len 바이트만큼 c 값 (unsigned char로 형변환됨) 으로 초기화
  • 초기에 인자로 받은 b가 Null일 경우 Crash
  • 그 외의 경우, 초기 포인터값을 반환

stdlib.h

malloc

void *malloc(size_t size);
  • 힙 메모리에 size만큼의 메모리를 동적으로 할당하고, 해당 주소값을 반환한다

free

void free(void *ptr);
  • malloc, calloc 등으로 할당한 메모리를 해제한다

unistd.h

write

ssize_t write(int fd, const void *buf, size_t count);
  • 우리의 오랜 친구.. 출력을 도와주는 write
  • fd는 파일 디스크립터 (문자열을 적을 위치, 0은 표준입력 1은 표준출력)count는 출력할 문자열의 길이
  • *buf는 출력할 문자열의 주소

usleep

int usleep(useconds_t microseconds);
  • microseconds 마이크로초만큼 스레드를 일시정지한다 (대기 상태). 만약 sleep 중간에 시그널이 발생하면 바로 복귀 후 남은 시간이 반환된다
  • 만약 15마이크로초를 쉬는 중에 (microseconds = 15) 5마이크로초만에 시그널이 발생하여 복귀하였을 경우, 리턴값은 10
Comments