제 17 장 멀티쓰레드 기반의 서버구현

26
HANNAM Univ. HANNAM Univ. 17 17 제 제제제제제 제제제 제제제제 제 제제제제제 제제제 제제제제 제제제제제제 제제제 제제제제제제 제제제 제제 제제 2 2 제제 제제제 제제 제제제 [email protected] [email protected] TCP/IP Socket Programming… TCP/IP Socket Programming…

Upload: morrie

Post on 15-Jan-2016

147 views

Category:

Documents


0 download

DESCRIPTION

TCP/IP Socket Programming…. 제 17 장 멀티쓰레드 기반의 서버구현. 데이터베이스 실험실 석사 2 학기 김기훈 [email protected]. 목차. 쓰레드란 무엇인가 쓰레드 생성하기 다중 쓰레드 생성하기 임계영역 & 쓰레드의 문제점 뮤텍스 (mutex) 세마포어 (Semaphore) 쓰레드 기반 서버 구현. Thread Stack. Thread Stack. Thread Stack. Thread Stack. Global Variables. Heap. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 제  17 장 멀티쓰레드 기반의 서버구현

HANNAM HANNAM Univ.Univ.

제 제 1717 장 멀티쓰레드 기반의 서버구현장 멀티쓰레드 기반의 서버구현

데이터베이스 실험실데이터베이스 실험실석사 석사 22 학기 김기훈학기 김기훈

[email protected]@dblab.hannam.ac.kr

TCP/IP Socket TCP/IP Socket Programming…Programming…

Page 2: 제  17 장 멀티쓰레드 기반의 서버구현

2

Network Lab.Network Lab.

HANNAM HANNAM Univ.Univ.

TCP/IP Socket Programming…TCP/IP Socket Programming…

목차목차쓰레드란 무엇인가

쓰레드 생성하기

다중 쓰레드 생성하기

임계영역 & 쓰레드의 문제점

뮤텍스 (mutex)

세마포어 (Semaphore)

쓰레드 기반 서버 구현

Page 3: 제  17 장 멀티쓰레드 기반의 서버구현

3

Network Lab.Network Lab.

HANNAM HANNAM Univ.Univ.

TCP/IP Socket Programming…TCP/IP Socket Programming…

쓰레드란 무엇인가쓰레드란 무엇인가 [1][1]경량화 된 프로세스

■ 프로세스와 마찬가지로 동시실행이 가능함■ 프로세스의 단점을 극복하기 위해 등장

프로세스와의 차이점■ 스텍을 제외한 나머지 메모리 공간을 공유■ 보다 간단한 컨텍스트 스위칭 (context switching)■ 일부메모리를 공유하므로 스레드간 통신이 편리

Global Variables

Heap

Thread Stack

Thread

Process

Global Variables

Heap

Thread Stack

Thread 1

Process

Thread Stack

Thread 1

Thread Stack

Thread 1

Page 4: 제  17 장 멀티쓰레드 기반의 서버구현

4

Network Lab.Network Lab.

HANNAM HANNAM Univ.Univ.

TCP/IP Socket Programming…TCP/IP Socket Programming…

쓰레드란 무엇인가쓰레드란 무엇인가 [2][2]프로세스와 쓰레드

Page 5: 제  17 장 멀티쓰레드 기반의 서버구현

5

Network Lab.Network Lab.

HANNAM HANNAM Univ.Univ.

TCP/IP Socket Programming…TCP/IP Socket Programming…

쓰레드 생성하기쓰레드 생성하기 [1][1]쓰레드를 생성하는 함수

■ Pthread_create 함수

▶ thread : 생성된 쓰레드의 ID 를 저장할 변수의 포인터를 인자로 전달▶ Attr : 생성하고자 하는 쓰레드의 특성 (attribute) 을 설정할 때 사용 , 일반적으로 Null 을 전달▶ Start_routine : 리턴타입과 인자가 void* 인 함수를 가르키는 포인터▶ Arg : 쓰레드에 의해 호출되는 함수에 전달하고자 하는 인자값을 넘겨줌

#include <pthread.h>

int pthread_create (pthead_t * thread, pthread_attr-t * attr, void * (* start_routine) (void *), void * arg);

성공 시 0, 실패 시 이외의 값 리턴

Page 6: 제  17 장 멀티쓰레드 기반의 서버구현

6

Network Lab.Network Lab.

HANNAM HANNAM Univ.Univ.

TCP/IP Socket Programming…TCP/IP Socket Programming…

쓰레드 생성하기쓰레드 생성하기 [2][2] thread1.c

void *thread_function(void *arg);

int main(int argc, char **argv){

int state; pthread_t t_id; void *t_return;

state = pthread_create(&t_id, NULL, thread_function, NULL); if(state != 0){ puts(" 쓰레드 생성 오류 "); exit(1); } printf(" 생성된 쓰레드 ID : %d \n", t_id); sleep(3); puts("main 함수 종료 ");

return 0;}void * thread_function(void *arg){ int i; for(i=0; i<3; i++){

sleep(2);puts(" 쓰레드 실행 중 ");

}}

실행결과

Process

Thread쓰레드 생성

종료 종료

Page 7: 제  17 장 멀티쓰레드 기반의 서버구현

7

Network Lab.Network Lab.

HANNAM HANNAM Univ.Univ.

TCP/IP Socket Programming…TCP/IP Socket Programming…

쓰레드 생성하기쓰레드 생성하기 [3][3]■ pthread_join 함수

▶ th : th 에 인자로 들어오는 ID 의 쓰레드가 종료할 때까지 실행 지연▶ thread_return : 쓰레드가 종료 시 반환하는 값에 접근할 수 있는 2

차원포인터

#include <pthread.h>

int pthread_join(pthead_t * th, void **thread_return););

성공 시 0, 실패 시 이외의 값 리턴

Page 8: 제  17 장 멀티쓰레드 기반의 서버구현

8

Network Lab.Network Lab.

HANNAM HANNAM Univ.Univ.

TCP/IP Socket Programming…TCP/IP Socket Programming…

쓰레드 생성하기쓰레드 생성하기 [4][4] thread2.c

int main(int argc, char **argv){ . . . void *t_return; state = pthread_create(&t_id, NULL, thread_function, NULL); . . .

printf(" 생성된 쓰레드 ID : %d \n", t_id);

/* 쓰레드 종료 시까지 main 함수의 실행을 지연 */ state = pthread_join(t_id, &t_return); /* 리턴 값 저장 */ if(state !=0 ){

puts(" 쓰레드 Join 오류 ");exit(1);

} printf("main 함수 종료 , 쓰레드 리턴 %s", (char*)t_return); free(t_return); return 0;}

void * thread_function(void *arg) { int i; char *p = (char*)malloc(20*sizeof(char)); strcpy(p, " 쓰레드 종료됨 !\n"); for(i=0; i<3; i++){

sleep(2);puts(" 쓰레드 실행 중 ");

} return p;}

실행결과

Process

Thread쓰레드 생성

종료

종료

JOIN

RETURN

대기상태

Page 9: 제  17 장 멀티쓰레드 기반의 서버구현

9

Network Lab.Network Lab.

HANNAM HANNAM Univ.Univ.

TCP/IP Socket Programming…TCP/IP Socket Programming…

다중 쓰레드 생성하기다중 쓰레드 생성하기 [1][1]임계영역 (Critical Section) 과 쓰레드에 안전한

함수의 호출■ 임계영역

▶ 두개 이상의 쓰레드에 의해서 동시에 실행되면 안 되는 영역■ 쓰레드 관점에서 볼 때 함수의 종류

▶ 쓰레드 불안전한 함수 (Thread-unsafe Function) 단일 쓰레드 모델에서는 사용 가능함 함수이지만 다중 쓰레드

모델에서는 사용할 수 없는 함수 (gethostbyname)▶ 쓰레드 안전한 함수 (Thread-safe Function)

다중 쓰레드 모델에서 사용 가능한 함수 (gethostbyname_r)

■ 불안전한 함수를 안전한 함수로 변경▶ 컴파일시 – D_REENTRANT 를 옵션으로 넣어 주는 방식으로 매크로를 선언

Page 10: 제  17 장 멀티쓰레드 기반의 서버구현

10

Network Lab.Network Lab.

HANNAM HANNAM Univ.Univ.

TCP/IP Socket Programming…TCP/IP Socket Programming…

다중 쓰레드 생성하기다중 쓰레드 생성하기 [2][2]Thread3.c 실행결과

void *thread_summation(void *arg);

int sum=0;int sum1[]={1, 5};int sum2[]={6, 10};

int main(int argc, char **argv){

pthread_t id_t1, id_t2; void *t_return; pthread_create(&id_t1, NULL, thread_summation, (void *)sum1); pthread_create(&id_t2, NULL, thread_summation, (void *)sum2);

/* 쓰레드 종료 시까지 main 함수의 실행을 지연 */ pthread_join(id_t1, &t_return); pthread_join(id_t2, &t_return); printf("main 함수 종료 , sum = %d \n", sum); return 0;}void * thread_summation(void *arg){

int start = ((int*)arg)[0]; int end = ((int*)arg)[1];

for(; start<=end; start++){sum+=start;

}}

Process

Thread쓰레드 생성

종료

종료

JOIN

RETURN

Thread쓰레드 생성

종료

JOIN

Page 11: 제  17 장 멀티쓰레드 기반의 서버구현

11

Network Lab.Network Lab.

HANNAM HANNAM Univ.Univ.

TCP/IP Socket Programming…TCP/IP Socket Programming…

다중 쓰레드 생성하기다중 쓰레드 생성하기 [3][3]Thread4.c

#define NUMBER 10000

void *thread_increment(void *arg);int num=0;

int main(int argc, char **argv){

int i; pthread_t thread_id[10]; void *t_return;

for(i=0; i<10; i++) pthread_create(&thread_id[i], NULL, thread_increment, NULL);

/* 생성한 모든 쓰레드 종료 시까지 main 함수의 실행을 지연 */ for(i=0; i<10; i++) pthread_join(thread_id[i], &t_return); printf("main 함수 종료 , num=%d \n", num); return 0;}

void *thread_increment(void *arg){

int i; for(i=0; i<NUMBER; i++) num++;}

실행결과

Page 12: 제  17 장 멀티쓰레드 기반의 서버구현

12

Network Lab.Network Lab.

HANNAM HANNAM Univ.Univ.

TCP/IP Socket Programming…TCP/IP Socket Programming…

임계영역 임계영역 & & 쓰레드의 문제점쓰레드의 문제점 [1][1] 컴퓨터가 덧셈하는 원리

int i = 10int j = 20

j+=i

Page 13: 제  17 장 멀티쓰레드 기반의 서버구현

13

Network Lab.Network Lab.

HANNAM HANNAM Univ.Univ.

TCP/IP Socket Programming…TCP/IP Socket Programming…

임계영역 임계영역 & & 쓰레드의 문제점쓰레드의 문제점 [2][2]두 개의 쓰레드에 의한 덧셈 원리

int i = 10

. . . . .i+=10

Page 14: 제  17 장 멀티쓰레드 기반의 서버구현

14

Network Lab.Network Lab.

HANNAM HANNAM Univ.Univ.

TCP/IP Socket Programming…TCP/IP Socket Programming…

임계영역 임계영역 & & 쓰레드의 문제점쓰레드의 문제점 [3][3]임계영역

■ 두개 이상의 쓰레드에 의해서 공유되는 메모리 공간에 접근하는 코드영역

쓰레드의 동기화■ 공유된 메모리에 둘 이상의 쓰레드가 동시 접근하는 것을 막는

방법 ■ 둘 이상의 쓰레드 실행 순서를 컨트롤하는 방법

대표적인 동기화 기법■ 뮤텍스■ 세마포어

Page 15: 제  17 장 멀티쓰레드 기반의 서버구현

15

Network Lab.Network Lab.

HANNAM HANNAM Univ.Univ.

TCP/IP Socket Programming…TCP/IP Socket Programming…

뮤텍스뮤텍스 (Mutex)[1](Mutex)[1]뮤텍스

■ Mutual Exclusion 의 줄임말로 쓰레드들의 동시접근을 허용하지 않겠다는 의미

■ Pthread_mutex_t 타입변수를 가르켜 흔히 뮤텍스라고 함뮤텍스의 기본원리

■ 임계영역에 들어갈 때 뮤텍스를 잠그고 들어감■ 임계영역을 빠져 나올 때 뮤텍스를 풀고 나옴

뮤텍스 조작함수■ 초기화 : pthread_mutex_init (pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)■ 잠금 : pthread_mutex_lock (pthread_mutex_t *mutex)■ 잠금 해제 : pthread_mutex_unlock (pthread_mutex_t *mutex)■ 소멸 : pthread_mutex_destroy (pthread_mutex_t *mutex)

Page 16: 제  17 장 멀티쓰레드 기반의 서버구현

16

Network Lab.Network Lab.

HANNAM HANNAM Univ.Univ.

TCP/IP Socket Programming…TCP/IP Socket Programming…

뮤텍스뮤텍스 (Mutex)[2](Mutex)[2]뮤텍스의 동기화 원리

Thread A

임계영역

Thread B

Thread B

임계영역

Thread A 진입상태

임계영역

Thread B 진입

pthread_mutex_lock 함수 호출 후

임계영역에 진입

Pthread_mutux_lock 함수 호출 후 대기상태

Thread A

2.Thread B 진입

1. Pthread_mutex_unlock 함수 호출 후 임계 영역 탈출

[1]

[2]

[3]

Page 17: 제  17 장 멀티쓰레드 기반의 서버구현

17

Network Lab.Network Lab.

HANNAM HANNAM Univ.Univ.

TCP/IP Socket Programming…TCP/IP Socket Programming…

뮤텍스뮤텍스 (Mutex)[3](Mutex)[3]mutex.c

void *thread_increment(void *arg);char thread1[] = "A Thread";char thread2[] = "B Thread";pthread_mutex_t mutx;int number = 0;

int main(int argc, char **argv){ pthread_t t1, t2; void *thread_result; int state; state = pthread_mutex_init(&mutx, NULL); if(state){

puts(" 뮤텍스 초기화 실패 ");exit(1);

} pthread_create(&t1, NULL, thread_increment, &thread1); pthread_create(&t2, NULL, thread_increment, &thread2); pthread_join(t1, &thread_result); pthread_join(t2, &thread_result); printf("최종 number : %d \n", number); pthread_mutex_destroy(&mutx); return 0;}

void *thread_increment(void * arg) { int i; for(i=0; i<5; i++){ pthread_mutex_lock (&mutx); sleep(1); number++; printf (" 실행 : %s, number : %d \n", (char*)arg, number); pthread_mutex_unlock (&mutx); }} 실행결과

Page 18: 제  17 장 멀티쓰레드 기반의 서버구현

18

Network Lab.Network Lab.

HANNAM HANNAM Univ.Univ.

TCP/IP Socket Programming…TCP/IP Socket Programming…

세마포어세마포어 (Semaphore)[1](Semaphore)[1]세마포어

■ sem_t 타입의 변수를 가르켜 흔히 세마포어라고 함세마포어의 기본원리

■ 정수를 가짐■ 정수 값이 0 이면 실행 불가능■ 세마포어가 1 이상이면 실행 가능■ 세마포어는 0 미만은 될수 없고 1 이상은 가능

세마포어 조작 함수■ 초기화 : sem_init (sem_t *sem, int pshared, unsigned int value)■ 소멸 : sem_destory (sem_t *sem)■ 증가 : sem_wait (sem_t *sem)■ 감소 : sem_post (sem_t *sem)

Page 19: 제  17 장 멀티쓰레드 기반의 서버구현

19

Network Lab.Network Lab.

HANNAM HANNAM Univ.Univ.

TCP/IP Socket Programming…TCP/IP Socket Programming…

세마포어세마포어 (Semaphore)[2](Semaphore)[2]세마포어의 동기화 원리

Thread A

Data

Thread A

1.새로운 데이터를저장 후 세마포어하나 증가

Thread B

Thread B

2. 세마포어 값을하나 감소 시킨 후 ,데이터를 가져간

다 .

Data

2.새로운 데이터를저장 후 세마포어하나 증가

3. 실행 상태로 돌아와세마포어를 하나 감소후 데이터 얻음 .

1. 세마포어가 현재 0 이므로 sem_wait 함수 호출 시대기 상태로 진입

[1] [2]

Page 20: 제  17 장 멀티쓰레드 기반의 서버구현

20

Network Lab.Network Lab.

HANNAM HANNAM Univ.Univ.

TCP/IP Socket Programming…TCP/IP Socket Programming…

세마포어세마포어 (Semaphore)[3](Semaphore)[3]semaphore.c

void *thread_snd(void *arg);void *thread_rcv(void *arg);sem_t bin_sem;int number = 0;char thread1[] = "A Thread";char thread2[] = "B Thread";char thread3[] = "C Thread";

int main(int argc, char **argv){ pthread_t t1, t2, t3; void *thread_result; int state; state = sem_init(&bin_sem, 0, 0); //bin_sem은 0 으로 설정 if(state != 0){

puts(" 세마포어 초기화 실패 ");exit(1);

} pthread_create(&t1, NULL, thread_snd, &thread1); pthread_create(&t2, NULL, thread_rcv, &thread2); pthread_create(&t3, NULL, thread_rcv, &thread3); pthread_join(t1, &thread_result); pthread_join(t2, &thread_result); pthread_join(t3, &thread_result); printf("최종 number : %d \n", number); sem_destroy(&bin_sem); return 0;}

void *thread_snd(void * arg){ int i; for(i=0; i<4; i++){ while(number != 0); sleep(1); number++; printf(" 실행 : %s, number : %d \n", (char*)arg, number); sem_post(&bin_sem); }}

void *thread_rcv(void * arg){ int i; for(i=0; i<2; i++){ sem_wait(&bin_sem); number--; printf(" 실행 : %s, number : %d \n", (char*)arg, number); }}

실행결과

Page 21: 제  17 장 멀티쓰레드 기반의 서버구현

21

Network Lab.Network Lab.

HANNAM HANNAM Univ.Univ.

TCP/IP Socket Programming…TCP/IP Socket Programming…

세마포어세마포어 (Semaphore)[4](Semaphore)[4]semaphore2.c

void *thread_snd(void *arg);void *thread_rcv(void *arg);sem_t bin_sem bin_sem2;int number = 0;char thread1[] = "A Thread";char thread2[] = "B Thread";char thread3[] = "C Thread";

int main(int argc, char **argv){ pthread_t t1, t2, t3; void *thread_result; int state; state = sem_init(&bin_sem, 0, 0); //bin_sem은 0 으로 설정 if(state != 0){

puts(" 세마포어 초기화 실패 ");exit(1);

} pthread_create(&t1, NULL, thread_snd, &thread1); pthread_create(&t2, NULL, thread_rcv, &thread2); pthread_create(&t3, NULL, thread_rcv, &thread3); pthread_join(t1, &thread_result); pthread_join(t2, &thread_result); pthread_join(t3, &thread_result); printf("최종 number : %d \n", number); sem_destroy(&bin_sem); return 0;}

void *thread_snd(void * arg){ int i; for(i=0; i<4; i++){ number++; printf(" 실행 : %s, number : %d \n", (char*)arg, number); sem_post(&bin_sem); sem_wait(&bin_sem2); }}

void *thread_rcv(void * arg){ int i; for(i=0; i<2; i++){ sem_wait(&bin_sem); number--; printf(" 실행 : %s, number : %d \n", (char*)arg, number); sem_post(&bin_sem2);

}}

실행결과

Page 22: 제  17 장 멀티쓰레드 기반의 서버구현

22

Network Lab.Network Lab.

HANNAM HANNAM Univ.Univ.

TCP/IP Socket Programming…TCP/IP Socket Programming…

쓰레드 기반 서버 구현쓰레드 기반 서버 구현 [1][1]chat_server.c

#define BUFSIZE 100void *clnt_connection(void *arg);void send_message(char *message, int len);void error_handling(char * message);int clnt_number = 0;int clnt_socks[10];pthread_mutex_t mutx;

int main(int argc, char **argv){ int serv_sock; int clnt_sock; struct sockaddr_in serv_addr; struct sockaddr_in clnt_addr; int clnt_addr_size; pthread_t thread; . . . . while(1){ clnt_addr_size = sizeof(clnt_addr); clnt_sock = accept(serv_sock, (struct sockaddr*) &clnt_addr, &clnt_addr_size); pthread_mutex_lock(&mutx); clnt_socks[clnt_number++] = clnt_sock; pthread_mutex_unlock(&mutx); pthread_create(&thread, NULL, clnt_connection, (void*)clnt_sock); printf("새로운 연결 , 클라이언트 ip : %s \n", inet_ntoa(clnt_addr.sin_addr)); } return 0;}

void *clnt_connection(void *arg){ int clnt_sock = (int)arg; int str_len = 0; char message[BUFSIZE]; int i; while((str_len = read(clnt_sock, message, sizeof(message))) != 0)

send_message(message, str_len); pthread_mutex_lock(&mutx); for(i=0; i<clnt_number; i++){ /*클라이언트 연결 종료 시 */ if(clnt_sock == clnt_socks[i]){ for(; i<clnt_number-1; i++)

clnt_socks[i] = clnt_socks[i+1]; break; } } clnt_number--; pthread_mutex_unlock(&mutx); close(clnt_sock); return 0;}void send_message(char * message, int len){ int i; pthread_mutex_lock(&mutx); for(i=0; i<clnt_number; i++)

write(clnt_socks[i], message, len); pthread_mutex_unlock(&mutx);}

Page 23: 제  17 장 멀티쓰레드 기반의 서버구현

23

Network Lab.Network Lab.

HANNAM HANNAM Univ.Univ.

TCP/IP Socket Programming…TCP/IP Socket Programming…

쓰레드 기반 서버 구현쓰레드 기반 서버 구현 [2][2]chat_client.c

#define BUFSIZE 100#define NAMESIZE 20void *send_message(void *arg);void *recv_message(void *arg);void error_handling(char * message);char name[NAMESIZE]="[Default]";char message[BUFSIZE];

int main(int argc, char **argv){ int sock; struct sockaddr_in serv_addr; pthread_t snd_thread, rcv_thread; void *thread_result;. . . . sock=socket(PF_INET, SOCK_STREAM, 0);. . . .

pthread_create(&snd_thread, NULL, send_message, (void*)sock); pthread_create(&rcv_thread, NULL, recv_message, (void*)sock); pthread_join(snd_thread, &thread_result); pthread_join(rcv_thread, &thread_result); close(sock); return 0;}

void *send_message(void *arg){ /* 메시지 전송 쓰레드 실행 함수 */ int sock = (int)arg; char name_message[NAMESIZE+BUFSIZE]; while(1){

fgets(message, BUFSIZE, stdin);if(!strcmp(message, "q\n")){ /* 'q' 입력 시 종료 */

close(sock);exit(0);

}sprintf(name_message, "%s %s", name, message);write(sock, name_message, strlen(name_message));

}}void *recv_message(void *arg){ int sock = (int)arg; char name_message[NAMESIZE+BUFSIZE]; int str_len; while(1){ str_len = read(sock, name_message, NAMESIZE+BUFSIZE-1); if(str_len == -1) return 1; name_message[str_len] = 0; fputs(name_message, stdout); }}

Page 24: 제  17 장 멀티쓰레드 기반의 서버구현

24

Network Lab.Network Lab.

HANNAM HANNAM Univ.Univ.

TCP/IP Socket Programming…TCP/IP Socket Programming…

쓰레드 기반 서버 구현쓰레드 기반 서버 구현 [3][3]chat_server.c & chat_client.c

server

Client MR.Lee

ClientThoma

s

실행결과

Page 25: 제  17 장 멀티쓰레드 기반의 서버구현

25

Network Lab.Network Lab.

HANNAM HANNAM Univ.Univ.

TCP/IP Socket Programming…TCP/IP Socket Programming…

참고문헌참고문헌 “TCP/IP 소켓 프로그래밍” , 윤성우 저 “ 운영체제 (Understanding operating Systems)”,

김희철 , 박영민 , 이금석 , 조병호 , 최의인 공역

Page 26: 제  17 장 멀티쓰레드 기반의 서버구현

26

Network Lab.Network Lab.

HANNAM HANNAM Univ.Univ.

TCP/IP Socket Programming…TCP/IP Socket Programming…

Q & AQ & A