42Seoul의 Philosophers 과제에서 허용되는 External functions를 정리한 포스트이다.
#include <string.h>
void *memset(void *b, int c, size_t len);
특정 메모리의 내용(값)을 원한느 크기(len)만큼 특정 값(c)으로 세팅할 수 있는 함수이다.
int
타입으로 받지만 내부적으로 unsigned char
로 변환되어 저장된다.반환값
b
를 반환#include <stdio.h>
int printf(const char *format, ...);
여러 종류의 데이터를 다양한 서식에 맞춰 출력하는 함수
반환값
#include <stdlib.h>
void * malloc(size_t size);
void free(void *ptr);
malloc()
원하는 만큼 동적으로 메모리를 할당하여 주소값을 반환하는 함수이며, 동적으로 메모리를 할당할때 Heap(힙)영역에 할당 한다.
반환값
free()
반환값
#include <unistd.h>
ssize_t write(int fildes, const void *buf, size_t nbyte);
파일에 데이터를 출력하는 함수
반환값
#include <unistd.h>
int usleep(useconds_t microseconds);
지정한 시간(microseconds)만큼 대기한다.
반환값
#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 구조체만 채운다.
반환값
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
새로운 쓰레드(thread)를 생성하는 함수이다.
pthread_t
쓰레드는 프로세스 내 고유한 쓰레드 ID로 구분하게 되는데, 이 쓰레드 ID를 나타내는 데이터 타입으로 운영체제마다 다르게 구현되어 있다.
반환값
#include <pthread.h>
int pthread_detach(pthread_t thread);
쓰레드를 메인쓰레드에서 분리 시킨다. 이것은 쓰레드가 종료되는 즉시 쓰레드의 모든 자원을 되돌려(free)줄 것을 보증한다.
일반적으로 쓰레드를 pthread_create()
으로 생성하면, 쓰레드가 종료되어도 사용했던 자원이 해제되지 않는다. 따라서 pthread_detach()
를 이용해 쓰레드가 종료될 때 모든 자원을 해제한다.
반환값
#include <pthread.h>
int pthread_join(pthread_t thread, void **value_ptr);
특정 쓰레드가 종료될 때까지 기다렸다가 해당 쓰레드가 종료되면 쓰레드가 사용했던 자원을 해제하는 함수이다.
반환값
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
mutex 객체를 초기화 시키는 함수
fast
, recurisev
, error checking
의 종류가 있다. default로 fast
가 사용된다.반환값
#include <pthread.h>
int pthread_mutex_destroy(pthread_mutex_t *mutex);
뮤텍스 객체를 삭제하고 자원을 되돌려주는 함수이다.
더이상 사용하지 않는 뮤텍스는 반드시 이 함수를 이용해서 삭제해야 한다.
리눅스에서 쓰레드는 뮤텍스 객체와 별개로 되어 있다. 따라서 쓰레드가 종료되었다고 하더라도 뮤텍스 객체는 여전히 남아 있기 대문에 해당 함수를 호출해야지만 뮤텍스 객체가 삭제 된다.
반환값
#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);
(임계영역에 진입하기 위함)뮤텍스 lock을 요청한다.
만약 뮤텍스의 최근 상태가 unlocked라면 쓰레드는 lock을 얻고 임계영역에 진입하게 되고 리턴한다.
다른 쓰레드가 뮤텍스 lock을 얻은 상태라면 잠금을 얻을 수 있을 때까지 기다리게 된다.
반환값
#include <pthread.h>
int pthread_mutex_unlock(pthread_mutex_t *mutex);
뮤텍스 lock을 되돌려주는 함수이다.
만약 fast 뮤텍스라면 pthread_mutex_unlock()
는 언제나 unlocked 상태를 되돌려준다.
recursive 뮤텍스라면 잠겨있는 뮤텍스의 수를 감소시키고 이 수가 0이 된다면 뮤텍스 lock을 되돌려주게 된다.
반환값
#include <unistd.h>
pid_t fork(void);
현재 실행되는 프로세스에 대한 복사본을 만들어 자식 프로세스를 생성하는 함수이다.
반환값
#include <signal.h>
int kill(pid_t pid, int sig);
kill()
함수는 쉘에서 프로세스를 죽이는 kill 명령과는 달리 프로세스에 시그널을 전송한다. 물론, 프로세스에 SIGKILL
을 보내면 쉘 명령의 kill과 같은 역할을 할 수도 있다.
특정 프로세스 뿐만 아니라 같은 그룹 ID가 같은 모든 프로세스에게 동시에 시그널을 전송할 수 있으며, 권한 안에 있는 모든 프로세스에게도 시그널을 전송할 수 있다.
kill
대상 프로세스 IDpid 값에 따라 다음과 같이 처리된다.
pid | 의미 |
---|---|
양수 | 지정한 프로세스 ID에만 시그널을 전송 |
0 | 함수를 호출하는 프로세스와 같은 그룹에 있는 모든 프로세스에 시그널을 전송 |
-1 | 함수를 호출하는 프로세스가 전송할 수 있는 권한을 가진 모든 프로세스에 시그널을 전송 |
-1 이외의 음수 | 첫 번째 인수 pid 의 절대값 프로세스 그룹에 속하는 모든 프로세스에 시그널을 전송 |
반환값
#include <stdlib.h>
void exit(int status);
status
는 운영체제에 전달하며 main함수의 return값과 같은 역할이다.status
값은 에러 코드와 같으므로 정상 종료시 0을, 에러로 인한 종료시 0이 아닌 숫자, 대체로 1을 반환한다.#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *stat_loc, int options);
매개변수로 주어진 pid
번호의 자식 프로세스가 종료되거나, 시그널(signal) 함수를 호출하는 신호가 전달될 때까지 waitpid()
함수를 호출한 영역에서 일시 중지된다.
stat_loc
의 하위 8비트에는 0이 저장되며, 상위 8비트에는 프로세스가 종료되게 한 exit함수의 인자가 기록된다.stat_loc
의 하위 8비트에는 프로세스를 종료시킨 시그널 번호가 저장되며, 상위 8비트에는 0이 저장된다.waitpid()
옵션 정보WCONTINUED
: 중단 되었다가 재개된 자식 프로세스의 상태를 받는다.WNOHANG
: 자식 프로세스가 종료되었는지 실행 중인지 확인하고 바로 복귀한다. 즉, 부모 프로세스는 block되지 않은다.WUNTRACED
: 중단된 자식 프로세스의 상태를 받는다.pid 값에 따라 다음과 같이 처리된다.
pid | 의미 |
---|---|
양수 | 프로세스 ID가 pid인 자식 프로세스를 기다림 |
0 | 프로세스 그룹 ID가 호출한 프로세스의 ID와 같은 자식 프로세스를 기다린다. |
-1 | 임의의 자식 프로세스를 기다림 |
-1 이외의 음수 | 프로세스 그룹 ID가 pid의 절대값과 같은 자식 프로세스를 기다림 |
반환값
WNOHANG
을 사용하였고, 자식 프로세스가 종료되지 않았다면 0을 리턴#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);
이름있는 세마포어를 생성(초기화)하거나 접근하게끔 만드는 함수이다.
sem_open()
의 수행작업에 대한 설정값으로 아래 2가지 사용이 가능하다.O_CREAT
: 해당 세마포어가 존재하지 않으면 생성O_EXCL
: 이미 해당 세마포어가 존재하는 경우 에러만약 oflag
값으로 O_CREAT
값을 사용한다면 2개의 추가적인 parameter를 사용할 수 있다.
<sys/stat.h>
를 포함할 시 해당 헤더 내에 있는 매크로 값을 이용할 수 있다.S_IRWXR
: 그룹 접근S_IRWXO
: 타인 접근S_IRWXU
: 개인 접근SEM_VALUE_MAX
(<limits.h>
에 존재)를 초과할 수 없다.반환값
SEM_FAILED
반환 및 적당한 errno 설정#include <semaphore.h>
int sem_close(sem_t *sem);
세마포어와 관련된 시스템 리소스는 할당 해제하고 세마포어를 닫는다.
반환값
#include <semaphore.h>
int sem_post(sem_t *sem);
매개변수 sem
으로 참조된 세마포어의 lock을 해제하고 세마포어의 값을 1 증가시킨다.
함수 수행결과 세마포어의 값이 양수일 경우, 세마포어가 해제되기를 기다리며 블록된 쓰레드들를 깨운다.
반환값
#include <semaphore.h>
int sem_wait(sem_t *sem);
lock 수행을 통해 sem
으로 참조된 세마포어를 lock하고 세마포어의 값을 1 감소시킨다.
만약 현재 세마포어 값이 0
이라면 호출하는 쓰레드는 세마포어를 잠그거나 시그널에 의해 호출이 중단되기 전까지 sem_wait()
으로부터 돌아오지 않는다.
반환값
#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()
를 미리 호출해두어도 세마포어를 즉시 삭제하지 않는 것이다.
반환값