[Philosophers] 과제 Exteranl funts 함수 정리

bolee·2022년 9월 8일
0

42seoul

목록 보기
20/27

42Seoul의 Philosophers 과제에서 허용되는 External functions를 정리한 포스트이다.

공통 함수

memset

#include <string.h>

void *memset(void *b, int c, size_t len);

특정 메모리의 내용(값)을 원한느 크기(len)만큼 특정 값(c)으로 세팅할 수 있는 함수이다.

  • b: 세팅하고자 하는 메모리의 시작 주소
  • c: 세팅하고 싶은 특정한 값이다. int 타입으로 받지만 내부적으로 unsigned char로 변환되어 저장된다.
  • len: 길이를 뜻하여, 이 길이는 byte 단위이다.

반환값

  • 성공: 첫 번째 인자로 들어간 b를 반환
  • 실패: NULL

printf

#include <stdio.h>

int printf(const char *format, ...);

여러 종류의 데이터를 다양한 서식에 맞춰 출력하는 함수

  • format: 출력할 데이터이다. 서식 문자를 통해 여러 데이터를 출력할 수 있다.
  • ...: 가변인자로, format 내 서식을 대체하여 출력될 데이터들이 들어온다.

반환값

  • 성공: 출력한 byte 수
  • 실패: -1 반환 및 적당한 errno 값 설정

malloc, free

#include <stdlib.h>

void * malloc(size_t size);
void free(void *ptr);

malloc()
원하는 만큼 동적으로 메모리를 할당하여 주소값을 반환하는 함수이며, 동적으로 메모리를 할당할때 Heap(힙)영역에 할당 한다.

  • size: 할당을 원하는 메모리 크기(byte 단위)

반환값

  • 성공: 할당한 메모리의 첫번째 주소
  • 실패: NULL

free()

  • 동적으로 할당된 메모리를 해제한다.

반환값

  • 없음

write

#include <unistd.h>

ssize_t write(int fildes, const void *buf, size_t nbyte);

파일에 데이터를 출력하는 함수

  • fildes: 데이터 전송 영역을 나타내는 파일 디스크립터
  • buf: 전송할 데이터를 가지고 있는 버퍼의 포인터
  • nbyte: 전송할 데이터의 바이트 수

반환값

  • 성공: 전달한 바이트 수
  • 실패: -1 반환 및 적당한 errno 값 설정

usleep

#include <unistd.h>

int usleep(useconds_t microseconds);

지정한 시간(microseconds)만큼 대기한다.

반환값

  • 성공: 0
  • 실패: -1 적당한 errno 값 설정

gettimeofday

#include <sys/time.h>

int gettimeofday(struct timeval *restrict tp, void *restrict tzp);

1970년 1월 1일 자정(0시) 이후의 초(second)와 마이크로초(microsecond) 또는 그리니치 시간으로의 초와 마이트로초를 각각의 구조체에 채워넣는 함수이다.

  • tp: timeval 구조체

    #include <sys/time.h>
    
    struct timeval {
        time_t		tv_sec;   /* seconds since Jan. 1, 1970 */
        suseconds_t	tv_usec;  /* and microseconds */
    };

    timeval 구조체는 시간 값을 초 및 마이크로초 단위로 지정한다.

  • tzp: timezone 구조체

    #include <sys/time.h>
    
    struct timezone {
        int	tz_minuteswest; /* of Greenwich */
        int	tz_dsttime;     /* type of dst correction to apply */
    };

    timezone 구조체는 현지 시간대(그리니치에서 서쪽으로 분 단위로 측정)를 나타내며, 0이 아닌 경우 일광 절약 시간(Daylight saving time)이 해당 연도의 해당 부분에 로컬로 적용됨을 나타내는 플래그를 나타낸다.

일광 절약 시간(Daylight saving time)
하절기에 표준시를 원래 시간보다 한 시간 앞당긴 시간을 쓰는 것을 말한다. 즉, 0시에 일광 절약 시간제를 실시하면 1시로 시간을 조정해야 하는 것이다.
실제 낮 시간과 사람들이 활동하는 낮 시간 사이의 격차를 줄이기 위해 사용한다.

둘다 NULL이 아닌 경우 두 구조체 모두 채운다.
tp가 NULL이고 tzp가 NULL이 아닌 경우 gettimeofday()는 tzp의 시간대 구조체를 채운다.
tp가 NULL이 아니고 tzp가 NULL이면 tp의 timeval 구조체만 채운다.

반환값

  • 성공: 0
  • 실패 -1 반환 및 적당한 errno 값 설정

pthread_create

#include <pthread.h>

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);

새로운 쓰레드(thread)를 생성하는 함수이다.

  • thread: 쓰레드가 성공적으로 생성되었을 때 생성된 쓰레드를 식별하기 위해 사용되는 쓰레드 식별자 즉, 쓰레드 ID가 이 포인터가 가리키는 버퍼에 담긴다.

    pthread_t
    쓰레드는 프로세스 내 고유한 쓰레드 ID로 구분하게 되는데, 이 쓰레드 ID를 나타내는 데이터 타입으로 운영체제마다 다르게 구현되어 있다.

  • attr: 쓰레드 특성을 지정하기 위해 사용하며, 기본 쓰레드 특성을 이용하고자할 경우 NULLL 사용
  • start_rotine: 분기시켜 실행할 쓰레드 함수
  • arg: start_rotine 쓰레드 함수의 매개변수

반환값

  • 성공: 0
  • 실패: 에러 코드

pthread_detach

#include <pthread.h>

int pthread_detach(pthread_t thread);

쓰레드를 메인쓰레드에서 분리 시킨다. 이것은 쓰레드가 종료되는 즉시 쓰레드의 모든 자원을 되돌려(free)줄 것을 보증한다.
일반적으로 쓰레드를 pthread_create()으로 생성하면, 쓰레드가 종료되어도 사용했던 자원이 해제되지 않는다. 따라서 pthread_detach()를 이용해 쓰레드가 종료될 때 모든 자원을 해제한다.

  • thread: 쓰레드 식별자

반환값

  • 성공: 0
  • 실패: 에러 코드

pthread_join

#include <pthread.h>

int pthread_join(pthread_t thread, void **value_ptr);

특정 쓰레드가 종료될 때까지 기다렸다가 해당 쓰레드가 종료되면 쓰레드가 사용했던 자원을 해제하는 함수이다.

  • thread: 쓰레드 식별자
  • value_ptr: 쓰레드의 리턴값이다. value_ptr이 NULL이 아닌 경우 해당 포인터로 쓰레드의 리턴값을 받아올 수 있다.

반환값

  • 성공: 0
  • 실패: 에러 코드

Mandatory Part 전용 함수

pthread_mutex_init

#include <pthread.h>

int	pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);

mutex 객체를 초기화 시키는 함수

  • mutex: mutex 객체
  • attr: mutex의 특징을 지정하기 위해 사용하며, mutex 특성(종류)에는 fast, recurisev, error checking의 종류가 있다. default로 fast가 사용된다.
    • PTHREAD_MUTEX_INITIALIZER -> fast mutex(하나의 쓰레드가 하나의 lock만을 얻을 수 있는 일반적인 형태)
    • PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP -> recursive mutex(lock을 얻은 쓰레드가 다시 lock을 얻을 수 있다. 이 경우 lock에 대한 카운트가 증가함)
    • PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP -> mutex 에러 체크용

반환값

  • 성공: 0 및 mutex에 새로운 mutex Id 설정
  • 실패: 에러 코드

pthread_mutex_destroy

#include <pthread.h>

int	pthread_mutex_destroy(pthread_mutex_t *mutex);

뮤텍스 객체를 삭제하고 자원을 되돌려주는 함수이다.
더이상 사용하지 않는 뮤텍스는 반드시 이 함수를 이용해서 삭제해야 한다.
리눅스에서 쓰레드는 뮤텍스 객체와 별개로 되어 있다. 따라서 쓰레드가 종료되었다고 하더라도 뮤텍스 객체는 여전히 남아 있기 대문에 해당 함수를 호출해야지만 뮤텍스 객체가 삭제 된다.

  • mutex: mutex 객체

반환값

  • 성공: 0
  • 실패: 에러 코드

pthread_mutex_lock

#include <pthread.h>

int	pthread_mutex_lock(pthread_mutex_t *mutex);

(임계영역에 진입하기 위함)뮤텍스 lock을 요청한다.
만약 뮤텍스의 최근 상태가 unlocked라면 쓰레드는 lock을 얻고 임계영역에 진입하게 되고 리턴한다.
다른 쓰레드가 뮤텍스 lock을 얻은 상태라면 잠금을 얻을 수 있을 때까지 기다리게 된다.

  • mutex: mutex 객체

반환값

  • 성공: 0
  • 실패: 에러 코드

pthread_mutex_unlock

#include <pthread.h>

int	pthread_mutex_unlock(pthread_mutex_t *mutex);

뮤텍스 lock을 되돌려주는 함수이다.
만약 fast 뮤텍스라면 pthread_mutex_unlock()언제나 unlocked 상태를 되돌려준다.
recursive 뮤텍스라면 잠겨있는 뮤텍스의 수를 감소시키고 이 수가 0이 된다면 뮤텍스 lock을 되돌려주게 된다.

  • mutex: mutex 객체

반환값

  • 성공: 0
  • 실패: 에러 코드

Bonus Part 전용 함수

fork

#include <unistd.h>

pid_t fork(void);

현재 실행되는 프로세스에 대한 복사본을 만들어 자식 프로세스를 생성하는 함수이다.

반환값

  • 성공:
    • 부모 프로세스: 자식 프로세스의 pid 리턴(0보다 큰 값)
    • 자식 프로세스: 0 리턴
  • 실패:
    • 부모 프로세스: -1 리턴
    • 자식 프로세스는 생성되지 않는다.

kill

#include <signal.h>

int kill(pid_t pid, int sig);

kill() 함수는 쉘에서 프로세스를 죽이는 kill 명령과는 달리 프로세스에 시그널을 전송한다. 물론, 프로세스에 SIGKILL을 보내면 쉘 명령의 kill과 같은 역할을 할 수도 있다.

특정 프로세스 뿐만 아니라 같은 그룹 ID가 같은 모든 프로세스에게 동시에 시그널을 전송할 수 있으며, 권한 안에 있는 모든 프로세스에게도 시그널을 전송할 수 있다.

  • pid: kill 대상 프로세스 ID
  • sig: 시그널 번호

pid 값에 따라 다음과 같이 처리된다.

pid의미
양수지정한 프로세스 ID에만 시그널을 전송
0함수를 호출하는 프로세스와 같은 그룹에 있는 모든 프로세스에 시그널을 전송
-1함수를 호출하는 프로세스가 전송할 수 있는 권한을 가진 모든 프로세스에 시그널을 전송
-1 이외의 음수첫 번째 인수 pid 의 절대값 프로세스 그룹에 속하는 모든 프로세스에 시그널을 전송

반환값

  • 성공: 0
  • 실패: -1 반환 및 적당한 errno 값 설정

exit

#include <stdlib.h>

void exit(int status);
  • 프로세스를 종료시키는 함수
  • 종료하기 전에 모든 열려진 파일들을 자동으로 닫는다.
  • 출력 버퍼 속에 데이터가 있으면 그것을 쓰기 완료시킨다.
  • 주로 에러가 났을 때 강제 종료시키기 위해 if문 속에서 사용된다.
  • 입력 인자로 전달하는 status는 운영체제에 전달하며 main함수의 return값과 같은 역할이다.
  • status값은 에러 코드와 같으므로 정상 종료시 0을, 에러로 인한 종료시 0이 아닌 숫자, 대체로 1을 반환한다.

waitpid

#include <sys/wait.h>

pid_t waitpid(pid_t pid, int *stat_loc, int options);

매개변수로 주어진 pid 번호의 자식 프로세스가 종료되거나, 시그널(signal) 함수를 호출하는 신호가 전달될 때까지 waitpid() 함수를 호출한 영역에서 일시 중지된다.

  • pid: 감시 대상인 자식 프로세스 ID
  • stat_loc: 자식 프로세스의 종료 상태 정보
    • 정상 종료 시: stat_loc의 하위 8비트에는 0이 저장되며, 상위 8비트에는 프로세스가 종료되게 한 exit함수의 인자가 기록된다.
    • 비정상 종료 시: stat_loc의 하위 8비트에는 프로세스를 종료시킨 시그널 번호가 저장되며, 상위 8비트에는 0이 저장된다.
  • options: waitpid() 옵션 정보
    • WCONTINUED: 중단 되었다가 재개된 자식 프로세스의 상태를 받는다.
    • WNOHANG: 자식 프로세스가 종료되었는지 실행 중인지 확인하고 바로 복귀한다. 즉, 부모 프로세스는 block되지 않은다.
    • WUNTRACED: 중단된 자식 프로세스의 상태를 받는다.
    • 0: 자식 프로세스가 종료될 때까지 block

pid 값에 따라 다음과 같이 처리된다.

pid의미
양수프로세스 ID가 pid인 자식 프로세스를 기다림
0프로세스 그룹 ID가 호출한 프로세스의 ID와 같은 자식 프로세스를 기다린다.
-1임의의 자식 프로세스를 기다림
-1 이외의 음수프로세스 그룹 ID가 pid의 절대값과 같은 자식 프로세스를 기다림

반환값

  • 성공: 자식 프로세스 pid
  • 실패: -1 반환 및 적당한 errno 설정
  • 0: WNOHANG을 사용하였고, 자식 프로세스가 종료되지 않았다면 0을 리턴

sem_open

#include <semaphore.h>

sem_t *sem_open(const char *name, int oflag);
sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);

이름있는 세마포어를 생성(초기화)하거나 접근하게끔 만드는 함수이다.

  • name: 생성 또는 접근하고자 하는 세마포어의 이름
  • oflag: sem_open()의 수행작업에 대한 설정값으로 아래 2가지 사용이 가능하다.
    • O_CREAT: 해당 세마포어가 존재하지 않으면 생성
    • O_EXCL: 이미 해당 세마포어가 존재하는 경우 에러

만약 oflag 값으로 O_CREAT값을 사용한다면 2개의 추가적인 parameter를 사용할 수 있다.

  • mode: 세마포어에 대한 권한 설정 값으로 8진수 값으로 넣으면 되는데, <sys/stat.h>를 포함할 시 해당 헤더 내에 있는 매크로 값을 이용할 수 있다.
    • S_IRWXR: 그룹 접근
    • S_IRWXO: 타인 접근
    • S_IRWXU: 개인 접근
  • value: 세마포어 초기 값으로 0보다 큰 양수여야 한다. unlock된 세마포어의 수를 의미하며, 이 값은 SEM_VALUE_MAX(<limits.h>에 존재)를 초과할 수 없다.

반환값

  • 성공: semaphore descriptor
  • 실패: SEM_FAILED 반환 및 적당한 errno 설정

sem_close

#include <semaphore.h>

int sem_close(sem_t *sem);

세마포어와 관련된 시스템 리소스는 할당 해제하고 세마포어를 닫는다.

  • sem: 대상이 되는 세마포어

반환값

  • 성공: 0
  • 실패: -1 반환 및 적당한 errno 설정

sem_post

#include <semaphore.h>

int sem_post(sem_t *sem);

매개변수 sem으로 참조된 세마포어의 lock을 해제하고 세마포어의 값을 1 증가시킨다.
함수 수행결과 세마포어의 값이 양수일 경우, 세마포어가 해제되기를 기다리며 블록된 쓰레드들를 깨운다.

  • sem: unlock할 세마포어

반환값

  • 성공: 0
  • 실패: -1 반환 및 적당한 errno 설정

sem_wait

#include <semaphore.h>

int sem_wait(sem_t *sem);

lock 수행을 통해 sem으로 참조된 세마포어를 lock하고 세마포어의 값을 1 감소시킨다.
만약 현재 세마포어 값이 0이라면 호출하는 쓰레드는 세마포어를 잠그거나 시그널에 의해 호출이 중단되기 전까지 sem_wait()으로부터 돌아오지 않는다.

  • sem: lock할 세마포어

반환값

  • 성공: 0
  • 실패: -1 반환 및 적당한 errno 설정
#include <semaphore.h>

int sem_unlink(const char *name);

세마포어는 open 후 close를 한다고 해서 시스템 상에서 없어지지 않는다.
물론 시스템을 재부팅하게 되면 기존에 이용하고 있던 semaphore들은 삭제되지만, 그 전까지는 컴퓨팅 자원을 소모하고 있게 된다.
따라서 사용하지 않는 세마포어에 대해서는 반드시 sem_unlink()를 통해 삭제해줘야 한다.

sem_unlink()는 세마포어의 최초 sem_open() 호출 직후에 바로 호출되기도 한다.
이에 따라 세마포어가 생성되자마자 삭제되는 것처럼 보이지만, 실제로는 그렇지 않다. 프로세스 혹은 쓰레드에 의해 참조되고 있지 않는 세마포어는 즉시 삭제되지만, 단 하나의 작업이라도 세마포어를 sem_open() 하여 사용하고 있다면 sem_close()를 통해 세마포어의 참조 값이 0이 되기 전까지는 삭제되지 않는다.
따라서 sem_unlink()를 미리 호출해두어도 세마포어를 즉시 삭제하지 않는 것이다.

  • name: 세마포어의 이름

반환값

  • 성공: 0
  • 실패: -1 반환 및 적당한 errno 설정

0개의 댓글