amitabul

Sunday, February 10, 2013

은전한잎 마크


은전한잎 마크 초안.


평면안
평면안2
평면안3
평면안4

Monday, February 26, 2007

클라이언트 프로그램 작성 절차

서버 프로그램 작성 절차

volatile 키워드

volatile 키워드

volatile

volatile 키워드는 const와 함께 변수의 성질을 바꾸는 역할을 하는데 이 둘을 묶어 cv 지정자(Qualifier:제한자라고 번역하기도 한다)라고 한다. const에 비해 상대적으로 사용 빈도가 지극히 낮으며 이 키워드가 꼭 필요한 경우는 무척 드물다. 어떤 경우에 volatile이 필요한지 다음 코드를 보자.

int i;
double j;

for (i=0;i<100;i++) {
j=sqrt(2.8)+log(3.5)+56;
// do something
}

이 코드는 루프를 100번 실행하면서 어떤 작업을 하는데 루프 내부에서 j에 복잡한 연산 결과를 대입하고 있다. j값을 계산하는 식이 조금 복잡하지만 제어 변수 i값을 참조하지 않기 때문에 i 루프가 실행되는동안 j의 값은 상수나 마찬가지이며 절대로 변경되지 않는다. 루프 실행중에는 상수이므로 이 값을 매 루프마다 다시 계산하는 것은 시간 낭비이다. 그래서 제대로 된 컴파일러는 이 루프를 다음과 같이 수정하여 컴파일한다.

j=sqrt(2.8)+log(3.5)+56;
for (i=0;i<100;i++) {
// do something
}

j의 값을 계산하는 식을 루프 이전으로 옮겨서 미리 계산해 놓고 루프 내부에서는 j값을 사용하기만 했다. 어차피 루프 내부에서 j값이 바뀌는 것이 아니므로 이렇게 코드를 수정해도 원래 코드와 완전히 동일한 동작을 할 것이다. 똑똑한 컴파일러는 프로그래머가 코드를 대충 짜 놓아도 속도를 높이기 위해 자동으로 최적화를 하는 기능을 가지고 있으며 이런 암묵적인 최적화 기능에 의해 프로그램의 성능이 향상된다.
그렇다면 위 두 코드가 정말로 완전히 동일할까 의심을 가져 보자. j는 분명히 루프 내부에서 상수이므로 미리 계산해 놓아도 아무 문제가 없음이 확실하다. 그러나 아주 특수한 경우 최적화된 코드가 원래 코드와 다른 동작을 할 경우가 있다. 어떤 경우인가 하면 프로그램이 아닌 외부에서 j의 값을 변경할 때이다.
도스 환경에서는 인터럽트라는 것이 있고 유닉스 환경에서는 데몬, 윈도우즈 환경에서는 서비스 등의 백그라운드 프로세스가 항상 실행된다. 이런 백그라운드 프로세스가 메모리의 어떤 상황이나 전역변수를 변경할 수 있으며 같은 프로세스 내에서도 스레드가 여러 개라면 다른 스레드가 j의 값을 언제든지 변경할 가능성이 있다. 또한 하드웨어에 의해 전역 환경이 바뀔 수도 있다.
예를 들어 위 코드를 실행하는 프로세스가 두 개의 스레드를 가지고 있고 다른 스레드에서 어떤 조건에 의해 전역변수 j값(또는 j에 영향을 미치는 다른 값)을 갑자기 바꿀 수도 있다고 하자. 이런 경우 루프 내부에서 매번 j값을 다시 계산하는 것과 루프에 들어가기 전에 미리 계산해 놓는 것이 다른 결과를 가져올 수 있다. i루프가 50회째 실행중에 다른 스레드가 j를 바꾸어 버릴 수도 있는 것이다.
이런 경우에 쓰는 것이 바로 volatile이다. 이 키워드를 변수 선언문 앞에 붙이면 컴파일러는 이 변수에 대해서는 어떠한 최적화 처리도 하지 않는다. 컴파일러가 보기에 코드가 비효율적이건 어쨌건 개발자가 작성한 코드 그대로 컴파일한다. 즉 volatile 키워드는 "잘난척 하지 말고 시키는 대로 해"라는 뜻이다. 어떤 변수를 다른 프로세스나 스레드가 바꿀 수도 있다는 것을 컴파일러는 알 수 없기 때문에 전역 환경을 참조하는 변수에 대해서는 개발자가 volatile 선언을 해야 한다. 위 코드에서 j 선언문 앞에 volatile만 붙이면 문제가 해결된다.

volatile double j;

이 키워드가 반드시 필요한 상황에 대한 예제를 만들어 보이는 것은 굉장히 어렵다. 왜냐하면 외부에서 값을 바꿀 가능성이 있는 변수에 대해서만 이 키워드가 필요한데 그런 예제는 보통 크기가 아니기 때문이다. 잘 사용되지 않는 키워드이므로 여기서는 개념만 익혀 두도록 하자.

Labels:

Monday, February 19, 2007

static 키워드

지니야닷넷 :: 주제 보기 - static 키워드


static 지역 변수
- 일반 지역변수와 동일합니다. 단지 해당 변수의 생존 기간이 다릅니다. 일반 지역변수의 경우 해당 블록의 시작에서 변수가 생성되어서 블록을 벗어나게 되면 해당 변수는 소멸됩니다. 반면 static 변수의 경우 전역변수처럼 프로그램시작에서 끝까지 소멸되지 않고 있습니다.

static 전역 변수
- 일반 전역변수와 동일합니다. 하지만 해당 변수 사용 범위가 전체 프로젝트가 아닌 해당 파일내로 제한되게 됩니다. 해당 변수는 외부 파일로 노출되지 않기 때문에 파일 단위의 은닉성을 제공한다고 볼 수 있습니다.

static 함수
- 일반 함수와 동일합니다. 함수를 사용할 수 있는 범위가 해당 파일 안으로 제한되게 됩니다.

static 멤버 함수
- 클래스 멤버 함수와 달리 클래스 인스턴스 없이 호출할 수 있습니다. 일반 함수와 같다고 생각하시면 됩니다. 단지 함수 스코프가 해당 클래스 범위라고 생각하시면 됩니다.

Labels:

Joinc - Pthread(3)

Joinc - Pthread(3)

Pthread(3)
Posted on 2002/5/9
Topic: 기본라이브러리
article/Pthread_더_깊이위키 홈으로
article/Pthread_더_깊이
Docbook 원문


Pthread(3) - 더 깊이
윤 상배
dreamyun@yahoo.co.kr



--------------------------------------------------------------------------------

차례
1절. 소개
2절. 쓰레드 종류
2.1절. User Space 과 Kernel Space 쓰레드
2.1.1절. User Space쓰레드
2.1.2절. Kernel Space 쓰레드
3절. Pthread 에서의 세밀한 동기화
3.1절. 조건변수
3.1.1절. 조건변수 생성및 초기화
3.1.2절. 조건변수에 신호 보내기
3.1.3절. 조건변수를 통한 신호 기다리기
3.1.4절. 조건 변수 없애기(Destory)
4절. Thread-Specific Data
4.1절. 쓰레드간 전역변수 사용의 문제점
4.2절. Thread-Specific Data
4.2.1절. Thread-Specific Data 의 개념
4.2.2절. TSD 블럭의 할당(생성)
4.2.3절. TSD 블럭 에 대한 Access
4.2.4절. TSD 블럭 삭제
5절. 결론

--------------------------------------------------------------------------------

1절. 소개
그동안 Pthread(1) 과 Pthread(2) 를 통해서 pthread 에 대한 기본적인 개요와 사용방법을 알아 보았다. 이번문서는 pthread 에 대한 좀더 깊이있는 내용에 대해서 알아보도록 하겠다.

이 문서에서는 그동안의 Pthread 문서에서 다루지 못한 몇가지 이슈들과 다중 쓰레드 프로그래밍시 필요로하는 Condition variables 를 통한 좀더 정교한 쓰레드간 동기화 방법에 대해서 다루게 된다.


--------------------------------------------------------------------------------

2절. 쓰레드 종류
2.1절. User Space 과 Kernel Space 쓰레드
Pthread 는 Posix Thread 로 Posix 에서 표준으로 규격화한 쓰레드 라이브러리이며, User Space 에서 작동하는 쓰레드 라이브러리이다. 즉 쓰레드 관리를 위해서 Kernel 이 관여를하지 않고 쓰레드 관련 라이브러리에서 대부분의 쓰레드 관리를 처리하게 된다. Kernel 이 직접 쓰레드를 관리하는 방식을 Kernel Space 쓰레드 라고 하는데, User Space 쓰레드 보다 비용이 좀더 많이 드는 관계로 최근에는 User Space 라이브러리를 좀더 선호하는 편이다.

Kernel Space 이 User Space 쓰레드 보다 비용이 더 많이 든다는데 의아해 할수도 있을것이다. 일반적으로 생각했을때 Kernel 은 좀더 시스템에 가까우므로 좀더 비용이 적고 빠를것 이라고 생각할수 있지만 실은 그렇지 않다. 보통 응용프로그램은 2가지 레벨에서 작동하게 된다. 하나는 Kernel Space 모드 이고 다른 하나는 User Space 모드이다. 이렇게 2가지 모드로 나누는 이유는 일반응용 프로그램이 시스템에 직접 접근하는 일을 막기 위함으로, 일반 응용 프로그램이 시스템에 접근하기 위해서는 System Call 을 불러서 Kernel 에게 시스템자원을 사용할것을 요청하는 방식으로 간접 접근해야 한다. 이때 커널은 보호모드 상태에서 System Call 을 처리해야 하므로 여러가지 연산을 가지게 되된다. 최종적으로 User 모드에서 Kernel 모드로 전환하는데 드는비용, 보호모드를 위한 여러가지 연산을 하는데 드는 비용등 3가지의 비용을 소비하게 된다.

반면 User Level 쓰레드는 대부분의 작업을 system call 을 사용하지 않고 사용자라이브러리 에서 대부분 처리하므로 Kernel Level 쓰레드가 가지는 비용을 줄일수 있다. 단점이라면 Kernel Level 쓰레드가 각 쓰레드를 보호해주는 반면 유저레벨 쓰레드는 보호를 받을수 없다는 점이다. 그러므로 유저레벨쓰레드 사용시에는 각 쓰레드를 보호하기 위한 여러가지 동기화 장치등을 사용해야 하며, 이것은 때때로 세밀하고 복잡한 코딩 기법을 요구한다.

어쨋든 현재 Unix 쪽은 Pthread 를 표준으로 가져가는것 같다.


--------------------------------------------------------------------------------

2.1.1절. User Space쓰레드
쓰레드를 유지하기 위해서는 여러가지 정보를 필요로 한다. 이러한 정보는 "프로그램 코드", Data, Stack, File I/O, Signal 테이블 등 크게 5가지이다. User Space 쓰레드는 이러한 정보를 커널에서 관리하도록 하지 않고 쓰레드 라이브러리에서 직접 처리하게 된다. 또한 각 쓰레드간 협력이 가능하도록 switch 기능을 제공하는데, 커널쓰레드보다 일반적으로 빠른 switch 기능을 제공한다.

단점은 SMPs (Symmetric MultiProcessor system)의 장점들을 이용할수 없다는 것이다. 즉 dual 혹은 quad 의 cpu를 사용하고 있는 시스템이라 할지라도, User Space 쓰레드로는 진정한 멀티쓰레드 프로그래밍을 할수 없다는 것이다. 오직 하나의 CPU에서만 작동할수 있을뿐이다. 그러므로 설사 CPU가 2개 혹은 4개 있다고 하더라도, 수행속도차이는 그리 크지 않게 된다. 또한 하나의 쓰레드에서 I/O 봉쇄가 일어나게 되면 다른 모든 쓰레드까지 봉쇄되게 된다.

물론 이러한 문제들을 위한 해법역시 존재한다. I/O 봉쇄를 아예 라이브러리 차원에서 해결할수 있도록 도와주는 쓰레드 라이브러리도 있으며, I/O 작업을 비봉쇄 모드로 작업함으로써 봉쇄를 막을수도 있다. 그리고 몇몇의 SMPs 는 User Space 쓰레드로도 모든 SMP 자원을 이용할수 있도록 방법을 제공해 주기도 한다.


--------------------------------------------------------------------------------

2.1.2절. Kernel Space 쓰레드
커널에서 직접 쓰레드를 관리하며, 커널자체에서 쓰레드 정보를 가진다. 또한 각 프로세스 간의 스케쥴역시 커널에서 맡는다. 이경우 I/O 봉쇄같은 문제는 신경쓰지 않아도 되며, 또한 SMPs 자원을 제대로 활용할수 있다는 장점을 가진다.


--------------------------------------------------------------------------------

3절. Pthread 에서의 세밀한 동기화
우리는 이전의 Pthread(2) 문서에서 mutex 잠금을 이용한 데이타 동기화에 대해서 이미 알아보았다. 그러나 mutex 는 어디까지나 잠금을 위한 것으로 동기화시킬수 있는 범위는 좁은 범위로 한정되며, mutex 만 가지고는 세밀한 수준에서의 동기화는 어렵다. 그래서 mutex 와 더불어 다른 쓰레드 도구를 사용해야 한다. 이번장에서는 Condition variables(조건변수) 와 mutex 를 이용한 데이타 동기화에 대해서 알아보도록 하겠다.


--------------------------------------------------------------------------------

3.1절. 조건변수
뮤텍스가 잠금에 의해서 소극적인 동기화를 제공한다면, 조건변수는 "시그널 발생"과 "시그널에 대한 기다림" 을 통한 좀더 적극적인 동기화 방법을 제공한다. 이러한 시그널을 기다리기 위해서 pthread_cond_wait() 와 pthread_cond_timedwait() 2개의 함수를 제공한다. 이 함수들은 pthread_cond_signal()에 의해서 발생되는 시그널을 기다리고 있다가. 시그널이 도착하면 기다림을 멈추고 다음 루틴을 실행하게 된다. 이러한 시그널의 전달은 "조건변수" 를 통해서 이루어지게 된다. 아래는 이러한 순서를 간략하게 정리한 것이다(슈도코드형식). 임계영역에 들어간다.
{
요청을 기다린다.(pthread_cond_wait 를 이용해서 singal이 도착하는지 확인한다)
만약 요청이 도착한다면 (요청에 대한 해결이 끝날때 까지 요청영역을 임계영역으로 설정한다)
{
요청을 해결한다.
}
}
임계영역을 빠져나온다.


임계영역에 진입하고 빠져나오는 것은 mutex 를 사용한다. 위의 슈도코드를 보면 단순히 잠금만을 제공하는것이 아닌, 요청/해결 의 서버/클라이언트 모델을 구현할수 있으며, 다중의 요청/해결에 대한 동기화 문제까지 해결할수 있음을 알수 있다.


--------------------------------------------------------------------------------

3.1.1절. 조건변수 생성및 초기화
조건변수는 pthread_cont_t 의 타입으로 선언되어 있다. pthread_cond_t 는 다음과 같이 선언되어 있다. typedef struct
{
struct _pthread_fastlock __c_lock; // 구조체의 잠금을 위해서 사용된다.
_pthread_descr __c_waiting; // 쓰레드는 이 값의 상태변화를 기다린다.
} pthread_cond_t


pthread_cont_t 의 초기화를 위한 방법은 2가지가 있다. 첫번째는 프로그램의 시작시에 선언하고 초기화 해버리는 방법과, 프로그램 실행중에 함수를 호출해서 사용하는 방법이 있다. 프로그램 시작시에 선언해서 사용하기 위해서는 다음과 같은 방법을 사용한다. pthread_cond_t thread_con1 = PTHREAD_COND_INITIALIZER;


PTHREAD_COND_INITIALIZER 은 {__LOCK_INITIALIZER, 0} 으로 디파인 되어 있다. 위의 초기화를 사용하게 되면 pthread_cont_t 구조체를 위의 값으로 초기화 하게 된다. 또다른 방법은 프로그램 시행중에 사용하는 방법으로 pthread_cond_init() 함수를 사용하면 된다.


--------------------------------------------------------------------------------

3.1.2절. 조건변수에 신호 보내기
우리는 조건변수에 신호를 보냄으로써, 조건변수를 (신호를)기다리는 다른 쓰레드를 깨울수 있게 된다. 보통은 이러한 신호를 보내서 깨우고자 하는 쓰레드가 하나일수도 있지만, 동시에 여러개의 쓰레드를 깨워야할 필요도 있을것이다. 다음은 이러한 시그널을 보내는 함수들이다. int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);


pthread_cond_signal 은 하나의 쓰레드를 깨우기 위한, pthread_cond_broadcast 는 모든 쓰레드를 깨우기 위한 신호를 보내기 위해서 사용된다.

성공적으로 시그널이 전달되면 0이 리턴된다.


--------------------------------------------------------------------------------

3.1.3절. 조건변수를 통한 신호 기다리기
신호를 보내는 쓰레드가 있다면, 이 신호를 받기 위해 기다리는 쓰레드도 있어야 할것이다. 신호를 받기 위해서는 pthread_cond_wait()와 pthread_cond_timewait() 두개의 함수가 사용된다. 이두개의 함수는 신호가 전달될때까지 기다리게 된다. int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);


첫번째 아규먼트는 신호를 기다리기 위한 "조건변수" 이며 2번째는 mutext 변수이다. 이 두개의 함수는 실행되면 mutext 잠금을 풀고(unlock) 신호를 기다린다. 그러다가 신호가 전달되면 뮤텍스 잠금을 얻은 다음 해당영역을 실행하게 된다.

pthread_cond_wait 와 pthread_cond_timedwait 의 다른점은 timeout 을 기다리는지에 따라서 구별된다. pthread_cond_timedwait 는 기다림의 시간을 설정하여서 일정한 시간동안 시그널이 도착하지 않으면 ETIMEDOUT 값을 리턴한다. 반면 pthread_cond_wait 는 시그널이 도착할때까지 무한정 기다린다.

지금까지의 설명한 내용의 이해를 돕기 위해 간단한 흐름도를 그려보았다. 아래의 흐름도는 pthread_cond_wait()를 사용했을경우다. // 뮤텍스 와 조건변수를 초기화 한다.
pthread_mutext_t request_lock = PTHREAD_MUTEX_INITILIZER;
pthread_cond_t producer_cv = PTHREAD_COND_INITIALIZER;

// 임계 영역에 대한 뮤텍스 잠금을 얻는다.
int rc;
rc = pthread_mutext(&mutext_a);
if (rc)
{
perror("mutext lock error ");
phread_exit(NULL);
}

// 조건변수 producer_cv 에 대한 시그널을 기다린다.
// wait 에 들어가기전에 mutext 는 request_lock에 대한 잠금을
// 얻는다.
mutext_rc1 = pthread_cond_wait(&producer_cv,&request_lock)
if
{
// mutext 잠금이 이루어진다.
// 코드 실행
}

// 뮤텍스 잠금을 돌려준다.
pthread_mutex_unlock(&request_lock);




다음은 pthread_cond_timedwait()를 사용했을때의 흐름도이다. pthread_cond_wait()와 비교해서 시간설정을 위한부분이 들어가고, 타임아웃이 발생했을때 처리하는 부분이 들어가는걸 빼고는 나머지 부분은 동일하다. ...
struct timeval now;
struct timespec timeout;
int done;
...
rc = pthread_mutext(&mutext_a);
if(rc)
{
...
}

// timeout 시간 설정을 위해서 사용한다.
gettimeofday(&now);
timeout.tv_sec = noew.tv_sec + 5
timeout.tv_nsec = now.tv_usec * 1000;

// timeout 시간동안 signal 을 기다린다.
rc = pthread_cond_timedwait(&got_request, &request_mutext, &timeout);

// pthread_cond_timedwait 가 넘겨준 값을 이용해서 분기한다.
switch(rc)
{
// 시그널이 발생했을때..
case 0:
...
break;
// timeout 동안 시그널이 발생하지 않았을경우
case ETIMEDOUT:
...
break;
// 그밖의 경우(에러)
default:
...
break;
}
pthread_mutext_unlock(&request_mutex);





--------------------------------------------------------------------------------

3.1.4절. 조건 변수 없애기(Destory)
더이상 사용할 필요가 없는 조건변수는 없애주도록 하자. 이렇게 함으로써 시스템자원의 낭비를 막을수 있다. 조건변수를 없애기 위해서는 pthread_cond_destroy() 함수를 이용한다. 조견변수를 없애기 전에 조건변수를 사용하는 쓰레드가 없음을 확인해야 한다. // 조건변수 got_request 를 삭제한다. 리턴값이 EBUSY일경우는
// 아직 사용하는 쓰레드가 있으서 조건변수 삭제에 실패했을경우이다.
int rc = pthread_cond_destory(&got_request);
if (rc == EBUSY)
{
....
}





--------------------------------------------------------------------------------

4절. Thread-Specific Data
4.1절. 쓰레드간 전역변수 사용의 문제점
일반적인 단일 쓰레드 프로그래밍을 할때, (비록 권장하지는 않지만) 전역변수를 사용하는 경우가 종종 있을것이다. 전역변수를 씀으로써 그렇지 않을때 보다 코드를 훨씬 쉽게 기술할수도 있기때문이다.

멀티쓰레드 프로그램에서도 이러한 전역 변수가 필요할때가 있다. 그런데 전역변수를 쓰는데 약간의 문제가 발생한다. 이유는 모든 쓰레드가 전역변수를 공유해 버리기 때문에, 쓰레드별 전역변수를 사용할수 없기 때문이다. fork 를 이용한 멀티 프로세스 모델에서는 프로세스간 전역변수 공유가 되지 않기 때문에, 각 프로세스 개별적인 전역변수를 사용할수 있는것과는 대조적이다.

그럼 어떻게 해야지 쓰레드 개별적으로 전역변수를 사용하게 할수 있는지 알아보도록 하겠다.


--------------------------------------------------------------------------------

4.2절. Thread-Specific Data
4.2.1절. Thread-Specific Data 의 개념
이러한 문제의 해결을 위해 등장한것이, Thread-Specific Data (이하 TSD)이다. 같은 전역변수가 서로 다른 메모리 영역을 가르키게 하는 방법을 사용하는데, 다른 메모리 영역의 주소를 가리키는 각각의 다른 key 를 사용함으로써, 쓰레드간 개별적인 전역변수를 엑세스하게끔 만들어준다.

이것은 간단한 데이타베이스 형태인 key-value 관계로 나타낼수 있는데, 각각의 key 에 이름을 부여하고 이 key 가 value 를 가리킨다. 이 value 는 메모리 영역이 될것이다.

+-----------------------------------+
Process

Global_data
+-------+-------+-------+
data1 data2 data3
+-------+-------+-------+
^ ^ ^


key1 key2 key3

+---+ +---+ +---+

A B C
+---+ +---+ +---+
+-----------------------------------+


위의 그림은 쓰레드 A, B, C각 하나의 전역변수인 Global_data 에 어떻게 자신만의 전역데이타를 읽고 쓸수 있는지에 대한 개념을 나타낸것이다.


--------------------------------------------------------------------------------

4.2.2절. TSD 블럭의 할당(생성)
pthread_key_create() 함수를 이용해서 모든 쓰레드에서 효력을 가지는 새로운 key를 할당받을수 있다. 최초에 key 를 만들게 되면 이 key 는 기본적으로 NULL을 가르키게 된다. 나중에 쓰레드는 이 key 값을 변경하게 됨으로써 자신이 원하는 메모리 영역을 참조할수 있게 된다. 다음은 이 함수가 어떻게 사용되는지에 대한 간단한 예이다. pthread_key_t 는 unsigned int 형이다. int rc;
pthread_key_t list_key;

// clean_list 는 사용자 정의 함수로, 나중에 데이타가 필요없을때
// 데이타를 제거(free) 하기 위해서 필요한 함수이다.
extern void* clean_list(void*);

// key 를 생성하며 데이타 제거를 위한 함수를 지정해준다.
// cleanup_list 함수는 NULL 로 지정될수도 있으며,
// 이경우 나중에 key 를 삭제하더라도 데이터가 제거되지는 않는다.
rc=pthread_key_create(&list_key, cleanup_list);


pthread_key_create()를 실행한후에 list_key 는 새로 만들어진 key 를 가르킨다. pthread_key_create 는 성공적으로 실행될경우 0을 반환하고 그렇지 않을경우에는 적당한 에러코드를 반환하도록 되어있다. 생성할수 있는 key 의 숫자는 제한되어 있는데, 생성할수 있는 최대크기는 PTHREAD_KEYS_MAX 에 정의 되어 있다. 이값은 OS 마다 다를수 있으며 보통 1024 의 크기를 가진다.


--------------------------------------------------------------------------------

4.2.3절. TSD 블럭 에 대한 Access
key 를 만들었다면 이제 value 에 엑세스를 해야 한다. 엑세스를 위해서 pthread_getspecific()와 pthread_setspecific()두개의 함수가 제공된다. 첫번째 함수는 key 에 대한 value를 가져오기 위해서 사용되며, 두번째 함수는 key 에 value 를 세팅하기 위해서 사용된다. value 는 (void *)형으로 원하는 어떤 데이타라도 넘길수 있도록 되어있다. 다음은 간단한 사용 예이다.
phtread_key_t a_key;
int rc;

int *p_num = (int *)malloc(sizeof(int));
(*p_num) = 4;

rc = pthread_setspecific(a_key, (void *)p_num);
...
// 만약 a_key 에 대해서 p_num 값을 가져오고 싶다면
{
int *p_keyval = (int *)pthread_getspecific(a_key);

if (p_keyval != NULL)
{
printf("value of 'a_key' is: %d\n", *p_keyval);
}
}





--------------------------------------------------------------------------------

4.2.4절. TSD 블럭 삭제
더이상 사용할 필요가 없는 TSD 블럭은 pthread_key_delete()를 이용해서 삭제한다. 주의 할것은 이것은 key 를 삭제하는 것이지 실제 데이타의 메모리를 삭제하지는 않는다는 것이다. 데이타 메모리의 삭제는 pthread_key_create() 로 key 를 만들때 지정한 데이타 삭제 함수가 이용된다. 만약 데이타 삭제 함수가 NULL 이였다면 데이타 삭제는 일어나지 않을것이다. int rc = pthread_key_delete(key);





--------------------------------------------------------------------------------

5절. 결론
지금까지 Pthread 에 대한 몇가지 이슈들을 살펴보았는데, 여전히 다루지 못한 사항들이 있습니다. 그리고 실제로 어떻게 응용이 가능한지에 대한 방향제시도 좀 미약하구요. 이러한 부족한 점들은 나중에 다루게 될 "다중 연결 서버구성"의 쓰레드 편을 다루면서 보강하도록 하겠습니다.

이 문서들은 인터넷상의 온라인문서들과 man 페이지들을 참고해서 만들었읍니다. 그리고 제 스스로 쓰레드에 대해서 그리 깊은 지식을 가지고 있지 않음으로, 잘못된 내용이 있을수 있습니다. 이러한 내용은 게시판 등 에댓글을 남겨주시면 수정하도록 하겠습니다.

Labels:

Saturday, February 17, 2007

초딩 춤


Saturday, December 16, 2006

사진 강의실

Nikon Series E lenses - the Zoom lenses

Friday, December 08, 2006

사진과 여행 > 사진교실

디시인사이드 컨텐츠

팝코넷 | 카메라 강좌

Thursday, December 07, 2006

번지점프를 하다

번지점프를 하다

Labels: