=== 시간 함수 ===
int usleep(useconds_t microseconds)
마이크로초 만큼 쓰레드 대기
헤더
- unistd.h
파라미터
- microseconds: 1 / 1000 * 1000 초
반환
- 성공 시: 0 반환
- 실패 시: -1 반환
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#include <stdio.h>
#include <unistd.h>
int main(void)
{
int i = 0;
while (i < 3)
{
usleep(1000 * 1000);
i++;
printf("%d초 째 대기 중\n", i);
}
return (0);
}
|
cs |
int gettimeofday(struct timeval *tp, void *tzp)
현재 시간을 마이크로단위로 얻을 수 있음
반환으로 얻는 것이 아닌 레퍼런스로 얻음
헤더
- sys/time.h
파라미터
- time_ptr: 현재 시스테메 시간을 저장하기 위한 구조체 포인터
- timezone_ptr: 사용되지 않음
반환
- 성공 시: 0 반환
- 실패 시 : -1 반환
cf)
struct timeval {
long tv_sec; // 초
int tv_usec; // 마이크로초
}
1
2
3
4
5
6
7
8
9
10
|
#include <stdio.h>
#include <sys/time.h>
int main(void)
{
struct timeval my_time;
gettimeofday(&my_time, NULL);
printf("time : %ld\n", my_time.tv_sec);
printf("macro time : %d\n", my_time.tv_usec);
return (0);
}
|
cs |
=== 쓰레드 함수 ===
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)
새로운 쓰레드를 생섬함
헤더
- pthread.h
파라미터
- thread: 쓰레드 식별값 (고유 아이디)
- attr: pthread옵션 (옵션을 사용하지 않으면 NULL)
- start_routine: 쓰레드 함수 (루틴 함수)
- arg: 쓰레드 함수에서 사용할 인자 (void*형이지만 쓰레드 함수에서 캐스팅하여 사용)
반환
- 성공 시: 0 반환
- 실패 시: 에러 넘버
int pthread_detach(pthread_t thread)
부모 쓰레드로부터 분리 -> 부모쓰레드가 해당 쓰레드를 기다리지 않음
독립된 thread는 종료시 자동으로 리소스 해제
헤더
- pthread.h
파라미터
- thread: 쓰레드 식별값 (고유 아이디)
반환
- 성공 시: 0 반환
- 실패 시: 에러 넘버
int pthread_join(pthread_t thread, void **value_ptr)
특정 thread가 종료될 때까지 기다리다가, 그 thread가 종료되면 리소스를 해제시킴
이미 종료된 thread면 기다리지 않음
헤더
- pthread.h
파라미터
- thread: 쓰레드 식별값 (고유 아이디)
- value_ptr: pthread_create의 쓰레드 함수(start_routine)의 반환값을 받음
반환
- 성공 시: 0 반환
- 실패 시: 에러 넘버
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>
void *routine(void *thread_number)
{
int i;
int cnt;
i = 0;
while (i < 5)
{
usleep(1000 * 1000);
i++;
printf("thread(%d): %d초 대기\n", *(int *)thread_number, i);
}
printf("thread end\n");
return (thread_number);
}
int main(void)
{
pthread_t thread1;
pthread_t thread2;
int number1;
int number2;
void *ret;
number1 = 1;
number2 = 2;
if (pthread_create(&thread1, NULL, routine, (void *)&number1))
{
fprintf(stderr, "thread(1): pthread_create error: %s", strerror(errno));
return (errno);
}
if (pthread_create(&thread2, NULL, routine, (void *)&number2))
{
fprintf(stderr, "thread(2): pthread_create error: %s", strerror(errno));
return (errno);
}
printf("detach thread2\n");
pthread_detach(thread2); // main thread에서 join하지 않아도 알아서 진행하고 종료함
printf("waiting for a thread\n");
pthread_join(thread1, &ret); // thread1을 대기함, routine의 값을 ret에 넣어줌
printf("main end: %d\n", *(int *)ret);
return (0);
}
|
cs |
=== 뮤텍스 함수 ===
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
새로운 뮤텍스를 생성함
헤더
- pthread.h
파라미터
- mutex: 초기화 받을 mutex객체
- attr: 초기화 할 때 뮤텍스의 특징을 정의할 수 있는 속성 (기본으로 사용하려면 NULL)
반환
- 성공 시: 0 반환
- 실패 시: 에러 넘버
int pthread_mutex_destroy(pthread_mutex_t *mutex)
뮤텍스가 할당받은 리소스를 해제시킴
헤더
- pthread.h
파라미터
- mutex: free시킬 뮤텍스
반환
- 성공 시: 0 반환
- 실패 시: 에러 넘버
int pthread_mutex_lock(pthread_mutex_t *mutex)
기본적으로는 뮤텍스를 lock시킴
이미 뮤텍스가 lock인 상태이면 block상태로 들어가서 mutex를 사용할 수 있을 때 까지 대기함
헤더
- pthread.h
파라미터
- mutex: lock시킬 뮤텍스
반환
- 성공 시: 0
- 실패 시: 에러 넘버
int pthread_mutex_unlock(pthread_mutex_t *mutex)
현재 쓰레드가 뮤텍스를 잡고 있으면 unlock시킴
자신이 홀드하고 있는 뮤텍스가 아닌 것을 unlock시키면 undefined
헤더
- pthread.h
파라미터
- mutex: unlock시킬 뮤텍스
반환
- 성공 시: 0
- 실패 시: 에러 넘버
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>
pthread_mutex_t mutex;
void *routine(void *thread_number)
{
int i;
int cnt;
pthread_mutex_lock(&mutex);
printf("thread(%d): mutex lock\n", *(int *)thread_number);
i = 0;
while (i < 5)
{
usleep(1000 * 1000);
i++;
printf("thread(%d): %d초 대기\n", *(int *)thread_number, i);
}
printf("thread end\n");
pthread_mutex_unlock(&mutex);
printf("thread(%d): mutex unlock\n", *(int *)thread_number);
return (thread_number);
}
int main(void)
{
pthread_t thread1;
pthread_t thread2;
int number1;
int number2;
void *ret;
number1 = 1;
number2 = 2;
printf("pthread create\n");
pthread_create(&thread1, NULL, routine, (void *)&number1);
pthread_create(&thread2, NULL, routine, (void *)&number2);
printf("mutex init\n");
pthread_mutex_init(&mutex, NULL);
printf("waiting for threads\n");
pthread_join(thread1, &ret); // thread1을 대기함, routine의 값을 ret에 넣어줌
pthread_join(thread1, &ret); // thread1을 대기함, routine의 값을 ret에 넣어줌
printf("mutex destroy\n");
pthread_mutex_destroy(&mutex);
printf("main end\n");
return (0);
}
|
cs |
=== 세마포어 함수 ===
sem_t *sem_open(const char *name, int oflag, [mode], [value])
named semaphore 생성
헤더
- semaphore.h
파라미터
- name: 생성 또는 접근하고자 하는 세마포어 이름
- oflag: O_CREATE와 O_EXCL의 조합
- mode: 허가권, open()와 동일
- value: 세마포어의 수 (초기값)
반환
- 성공 시: 세마포어 디스크립터
- 실패 시: SEM_FAILED
cf) oflag
-> O_CREAT: create the semaphore if it does not exist
-> O_EXCL: error if create and semaphore exists
int sem_close(sem_t *sem)
세마포어 사용종료
세마포어를 사용 하도록 시스템이 할당한 자원들을 모두 해제
헤더
- semaphore.h
파라미터
- sem: 해제시킬 sem포인터
반환
- 성공 시: 0
- 실패 시: - 1
int sem_post(sem_t *sem)
세마포어를 unlock
세마포어의 value값이 1 증가
해당 세마포어를 대기중인 스레드는 깨어남
헤더
- semaphore.h
파라미터
- sem: unlock할 세마포어
반환
- 성공 시: 0
- 실패 시: -1
int sem_wait(sem_t *sem)
세마포어를 lock
세마포어의 value값이 1 감소
만약 세마포어의 value값이 0이라면 wait호출자는 block상태 (대기)
헤더
- semaphore.h
파라미터
- sem: lock할 세마포어
반환
- 성공 시: 0
- 실패 시: -1
int sem_unlink(const char *name)
name인 이름을 가진 세마포어를 "제거"
프로세스가 참조하고 있다면 unlink되지 않는다고 함
헤더
- semaphore.h
파라미터
- name: 제거해야할 세마포어name
반환
- 성공 시: 0
- 실패 시: -1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
sem_t *sem;
void *routine(void *num)
{
sem_wait(sem);
for (int i = 0; i < 3; ++i)
{
printf("%d: use semaphore\n", *(int *)num);
usleep(1000 * 1000);
}
sem_post(sem);
return (num);
}
int main(void)
{
int ret;
pthread_t tid[4];
int num[4];
sem = sem_open("test_sem", O_CREAT | O_EXCL, 0644, 3);
if (sem == SEM_FAILED)
{
fprintf(stderr, "sem error\n");
return (-1);
}
for (int i = 0; i < 4; ++i)
{
num[i] = i;
pthread_create(&tid[i], NULL, routine, (void *)&num[i]);
}
for (int i = 0; i < 4; ++i)
pthread_join(tid[i], NULL);
ret = sem_close(sem);
printf("sem_close: %d\n", ret);
ret = sem_unlink("test_sem");
printf("sem_unlink: %d\n", ret);
return (0);
}
|
cs |
프로세스와 세마포어 예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/wait.h>
int main(void)
{
pid_t pid;
int num;
int status;
sem_t *sem;
sem_unlink("test_sem");
sem = sem_open("test_sem", O_CREAT | O_EXCL, 0644, 1);
for (int i = 0; i < 4; ++i)
{
pid = fork();
num = i;
if (pid == 0)
break ;
}
if (pid == 0) /* child */
{
sem_wait(sem);
for (int i = 0; i < 3; i++)
{
printf("%d\tcritical sections\n", num);
sleep(1);
}
sem_post(sem);
}
else /* parent */
{
while (wait(&status) > 0);
printf("child ended\n");
}
return (0);
}
|
cs |
'42cursus' 카테고리의 다른 글
webserv 하루 일기 (2) | 2021.06.02 |
---|---|
philosophers[철학자] - 룰 그리고 쓰레드, 뮤텍스, 세마포어, 프로세스 (0) | 2021.02.26 |
minishell - 간단한 정리 (0) | 2021.02.18 |
minishell - 명령어와 외부함수 정리하기 (command & External functions, 42seoul) (0) | 2021.01.25 |
ft_services - 가이드 및 참고자료 정리하기 (42seoul) (0) | 2021.01.07 |