메인 컨텐츠로 가기

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관 보기.

developerWorks에 처음 로그인하면 developerWorks프로파일이 생성됩니다.귀하의 프로파일에서 동의하신 내용이 공개되지만 이 사항은 언제든지 변경 가능합니다. 귀하의 성명(숨김으로 체크되어 있어도 표시됩니다)과 디스플레이 이름은 게시한 컨텐츠나 사이트 엑세스시 표시됩니다.

모든 정보가 안전하게 전송되었습니다.

  • 닫기 [x]

처음 developerWorks에 로그인할 때 프로파일이 작성되므로, 이를 위해 디스플레이 이름을 선택해야 합니다. 선택하신 디스플레이 이름은 developerWorks에 게시한 컨텐츠에 표시됩니다.

3글자 이상 31글자 이하의 길이로 사용 가능합니다. dW커뮤니티 내에서는 보안상 이메일주소를 제외한 다른 이름을 지정하셔야 합니다.

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관 보기.

모든 정보가 안전하게 전송되었습니다.

  • 닫기 [x]

POSIX 스레드 프로그래밍에서 메모리 누수 방지하기

POSIX 스레드 메모리 누수를 발견하고 방지하기 위한 팁

Wei Dong Xie, IBM Systems Director Product Engineer, IBM
Author photo of Wei Dong Xie
For the past 3 years, Wei Dong has worked as a Product Engineer for IBM Systems Director with the responsibility of fixing issues reported by customers. Before he joined IBM, Wei Dong did a 10-month internship at Intel as a Linux developer. In 2007, he graduated from Nanjing University, China, with an MS degree.

요약:  POSIX 스레드(pthread) 프로그래밍은 C 프로그래밍 언어 유형, 함수 및 상수의 표준 세트를 정의하며 pthread는 스레드 관리를 위한 강력한 도구를 제공합니다. pthread의 기능을 최대한으로 활용하려면 일반적인 실수를 피할 수 있어야 합니다. 한 가지 일반적인 실수로는 결합 가능한 스레드를 결합하는 것을 잊어버리는 경우가 있습니다. 이 경우 메모리 누수가 발생하여 추가 작업을 수행해야 합니다. 간단한 팁을 제공하는 이 기사에서는 POSIX 스레드에 관한 기본 사항을 설명한 후 스레드 메모리 누수를 식별 및 발견하는 방법을 살펴본 후 메모리 누수 방지를 위한 조언을 제공합니다.

원문 게재일:  2010 년 8 월 25 일 번역 게재일:   2010 년 11 월 16 일
난이도:  초급 영어로:  보기 PDF:  A4 and Letter (29KB | 7 pages)Get Adobe® Reader®
페이지뷰:  5215 회
의견:  


POSIX 스레드 소개

스레드는 주로 프로그램 성능을 향상시키기 위해 사용한다. 스레드는 낮은 운영 체제 오버헤드와 적은 시스템 자원으로 작성 및 관리할 수 있다. 프로세스 내의 모든 스레드는 동일한 주소 공간을 공유하므로 프로세스 간 통신보다 더 쉽고 효율적으로 스레드 간 통신을 구현할 수 있다. 예를 들어, 한 스레드가 입/출력(I/O) 시스템 호출이 완료되기를 기다리고 있을 때 다른 스레드가 CPU 자원을 많이 사용하는 태스크를 수행할 수 있다. 스레드를 사용하면 중요한 태스크에 우선순위를 부여할 수 있으며 우선순위가 낮은 태스크를 인터럽트할 수도 있다. 가끔씩 발생하는 태스크를 정기적으로 스케줄된 태스크 사이에 배정하여 스케줄을 유연하게 조정할 수 있다. 마지막으로 pthread는 다중 CPU 시스템의 병렬 프로그래밍에 이상적이다.

POSIX 스레드 또는 pthread를 사용하는 주된 이유는 훨씬 더 단순하다. 그 이유는 바로 pthread가 표준화된 C 언어 스레드 프로그래밍 인터페이스의 일부로서 이식성이 매우 높기 때문이다.

POSIX 스레드 프로그래밍에는 여러 장점이 있지만 몇 가지 기본 규칙을 명확히 알지 못하면 디버그하기가 어려운 코드를 작성하고 메모리 누수가 발생할 수 있는 위험이 있다. 먼저 결합 가능한 스레드 또는 분리된 스레드일 수 있는 POSIX 스레드부터 검토해 보자.

결합 가능한 스레드

새 스레드를 작성하려면 스레드의 종료 방법을 알아야 하고 결합 가능한 스레드가 필요하다. 결합 가능한 스레드의 경우, 시스템이 스레드 종료 상태를 저장할 수 있는 개인용 저장소를 할당한다. 상태는 스레드 종료 후 업데이트된다. 스레드 종료 상태를 검색하려면 pthread_join(pthread_t thread, void** value_ptr)을 호출한다.

시스템이 스택, 스레드 ID, 스레드 종료 상태 등이 포함된 각 스레드에 대한 기본 저장소를 할당한다. 이 기본 저장소는 스레드가 종료되고 다른 스레드에 결합될 때까지 프로세스 공간에 유지된다(재활용되지 않음).

분리된 스레드

대부분의 경우에는 스레드를 작성한 후 일부 태스크를 스레드에 지정한 다음 계속해서 다른 작업을 처리한다. 이러한 경우에는 스레드의 종료 방법을 신경 쓰지 않아도 되므로 분리된 스레드를 사용하는 것이 좋다.

분리된 스레드의 경우에는 시스템이 스레드 종료 후 자동으로 기본 자원을 재활용한다.


누수 인식하기

결합 가능한 스레드를 작성했지만 결합하는 것을 잊어버린 경우 해당 자원 또는 개인용 메모리는 회수되지 않은 채로 프로세스 공간에 계속 유지된다. 결합 가능한 스레드는 항상 결합해야 한다. 그렇지 않으면 심각한 메모리 누수가 발생할 수 있다.

예를 들어, RHEL4(Red Hat Enterprise Linux)의 스레드에는 10MB 스택이 필요하다. 이는 곧 스레드를 결합하지 않았을 경우 적어도 10MB가 누수된다는 것을 의미한다. 수신 요청을 처리하기 위한 관리자-작업자 모드 프로그램을 설계한다고 가정해 보자. 이 프로그램에서는 작성된 후 개별 태스크를 수행하고 종료되는 많은 작업자 스레드가 필요하다. 이러한 스레드가 결합 가능한 스레드일 경우 pthread_join()을 호출하여 스레드를 결합하지 않으면 작성된 각 스레드에서 종료 후 상당한 용량의 메모리가 누수된다(적어도 스택당 10MB). 누수된 메모리의 크기는 더 많은 작업자 스레드가 작성된 후 결합되지 않고 종료될수록 증가한다. 게다가 새 스레드를 작성하는 데 사용할 수 있는 메모리가 없으면 프로세스에서 새 스레드를 작성할 수 없게 된다.

Listing 1에서는 결합 가능한 스레드의 결합을 잊어버린 경우 작성되는 심각한 메모리 누수를 보여 준다. 또한 이 코드를 사용하여 한 프로세스 공간에서 공존할 수 있는 스레드 본체의 최대 수를 확인할 수도 있다.


Listing 1. 메모리 누수 작성하기
#include<stdio.h>
#include<pthread.h>
void run() {
   pthread_exit(0);
}

int main () {
   pthread_t thread;
   int rc;
   long count = 0;
   while(1) {
      if(rc = pthread_create(&thread, 0, run, 0) ) {
         printf("ERROR, rc is %d, so far %ld threads created\n", rc, count);
         perror("Fail:");
         return -1;
      }
      count++;
   }
   return 0;
}

Listing 1에서는 pthread_create()를 호출하여 기본 스레드 속성을 지닌 새 스레드를 작성한다. 기본적으로 새로 작성되는 스레드는 결합 가능한 스레드이다. 이 코드는 실패가 발생할 때까지 결합 가능한 새 스레드를 계속 작성한다. 그런 다음 오류 코드와 실패 이유를 출력한다.

Red Hat Enterprise Linux Server 릴리스 5.4에서 [root@server ~]# cc -lpthread thread.c -o thread 명령을 사용하여 Listing 1의 코드를 컴파일하면 Listing 2와 같은 결과가 표시된다.


Listing 2. 메모리 누수 결과
[root@server ~]# ./thread
ERROR, rc is 12, so far 304 threads created
Fail:: Cannot allocate memory

이 코드를 실행하면 304개의 스레드가 작성된 후 더 이상 작성되지 않는다. 오류 코드는 12이며, 이는 메모리가 없음을 의미한다.

Listing 1 및 2에서 살펴본 대로 결합 가능한 스레드를 생성한 후 결합하지 않으면 종료된 결합 가능한 각 스레드가 프로세스 공간을 계속 차지하고 있기 때문에 프로세스 메모리가 누수된다.

RHEL의 POSIX 스레드는 10MB 크기의 개인용 스택을 사용한다. 다시 말해서 시스템이 적어도 10MB의 개인용 저장소를 각 pthread에 할당한다. 이 기사의 예제에서는 프로세스 종료 전까지 304개의 스레드가 작성되었으며, 이러한 스레드는 304*10MB 즉, 약 3GB의 메모리를 차지한다. 한 프로세스의 가상 메모리 크기는 4GB이며, 프로세스 공간의 1/4은 Linux 커널용으로 예약되어 있다. 결론적으로 3GB 메모리 공간을 사용자 공간으로 사용할 수 있다. 따라서 3GB 메모리가 죽은 스레드에 의해 사용되며, 이는 심각한 메모리 누수이다. 그리고 이러한 메모리 누수가 얼마나 빨리 발생하는지 쉽게 알 수 있다.

결합 가능한 각 스레드를 결합하는 pthread_join()을 호출하는 코드를 추가하여 누수를 해결할 수 있다.


누수 발견하기

다른 메모리 누수와 마찬가지로 프로세스가 시작될 때는 문제점이 명확히 나타나지 않을 수 있다. 따라서 여기에서는 소스 코드에 액세스하지 않고도 그러한 문제점을 발견할 수 있는 방법을 설명한다.

  1. 프로세스의 스레드 스택 수를 계산한다. 이 수에는 실행 중인 활성 스레드와 종료된 스레드의 수가 포함된다.
  2. 프로세스의 실행 중인 활성 스레드 수를 계산한다.
  3. 두 수를 비교한다. 기존 스레드 스택 수가 실행 중인 활성 스레드 수보다 크고 프로그램이 계속 실행되는 동안 이러한 두 수의 차이가 커지면 메모리 누수가 발생하고 있는 것이다.

그리고 대부분의 경우 이러한 메모리 누수는 결합 가능한 스레드를 결합하지 않았을 때 발생한다.

pmap을 사용하여 스레드 스택 수 계산하기

실행 중인 프로세스에서 스레드 스택의 수는 프로세스에 있는 스레드 본체의 수와 같다. 스레드 본체는 실행 중인 활성 스레드와 결합 가능한 죽은 스레드로 구성되어 있다.

pmap은 프로세스 메모리에 대한 정보를 보고하는 데 사용되는 Linux 도구이다. 다음 명령을 결합하여 스레드 스택 수를 확인할 수 있다.

[root@server ~]# pmap PID | grep 10240 | wc -l

(10240KB는 Red Hat Enterprise Linux Server 릴리스 5.4의 기본 스택 크기이다.)

/proc/PID/task를 사용하여 활성 스레드 수 계산하기

스레드가 작성되어 실행될 때마다 /proc/PID/task에 한 항목이 추가된다. 스레드가 종료되면 결합 가능한 스레드이거나 분리된 스레드이거나 상관 없이 /proc/PID/task에서 해당 항목이 제거된다. 따라서 다음 명령을 실행하여 활성 스레드 수를 확인할 수 있다.

[root@server ~]# ls /proc/PID/task | wc -l.

출력 비교하기

pmap PID | grep 10240 | wc -l의 출력을 검사한 후 ls /proc/PID/task | wc -l의 출력과 비교한다. 모든 스레드 스택 수가 활성 스레드 수보다 크고 프로그램이 계속 실행되는 동안 두 수의 차이가 커지면 누수 문제점이 있는 것으로 판단할 수 있다.


누수 예방하기

결합 가능한 스레드는 프로그래밍 동안 결합되어야 한다. 프로그램에서 결합 가능한 스레드를 작성할 때 pthread_join(pthread_t, void**)을 호출하여 스레드에 할당된 개인용 저장소를 재활용하는 것을 잊지 말아야 한다. 그렇지 않으면 심각한 메모리 누수가 발생한다.

프로그래밍 이후 테스트 단계 동안 pmap/proc/PID/task를 사용하여 그러한 누수가 있는지 여부를 확인할 수 있다. 누수가 있으면 소스 코드를 검사하여 모든 결합 가능한 스레드가 결합되었는지 확인한다.

이렇게만 하면 된다. 간단한 예방 작업을 수행하면 나중에 추가 작업을 하지 않아도 되고 메모리 누수도 방지할 수 있다.


참고자료

교육

제품 및 기술 얻기

  • 자신에게 가장 적합한 방법으로 IBM 제품을 평가해 보자. 시험판 제품을 다운로드하거나 온라인으로 제품을 사용해 보거나 클라우드 환경에서 제품을 사용하거나 SOA Sandbox에서 SOA(Service Oriented Architecture)를 효과적으로 구현하는 방법을 배울 수 있다.

토론

  • My developerWorks 커뮤니티에 참여하자. 개발자 중심 블로그, 포럼, 그룹 및 Wiki 검색 중에 다른 developerWorks 사용자와 의견을 교환해 보자.

필자소개

Author photo of Wei Dong Xie

For the past 3 years, Wei Dong has worked as a Product Engineer for IBM Systems Director with the responsibility of fixing issues reported by customers. Before he joined IBM, Wei Dong did a 10-month internship at Intel as a Linux developer. In 2007, he graduated from Nanjing University, China, with an MS degree.

잘못된 도움말 신고

부정사용 신고

감사합니다. 이 항목은 운영자가 관심을 표시했습니다.


잘못된 도움말 신고

부정사용 신고

제출실패 신고. 나중에 다시 실행해주세요.


디벨로퍼웍스 로그인


IBM ID가 필요하세요?
IBM ID를 잊으셨습니까?


비밀번호를 잊으셨습니까?
비밀번호 변경

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관.

 


developerWorks에 처음 로그인하면 developerWorks프로파일이 생성됩니다.귀하의 프로파일에서 동의하신 내용이 공개되지만 이 사항은 언제든지 변경 가능합니다. 귀하의 성명(숨김으로 체크되어 있어도 표시됩니다)과 디스플레이 이름은 게시한 컨텐츠나 사이트 엑세스시 표시됩니다.

화면상에 보여지는 닉네임을 정하세요.

처음 developerWorks에 로그인할 때 프로파일이 작성되므로, 이를 위해 디스플레이 이름을 선택해야 합니다. 선택하신 디스플레이 이름은 developerWorks에 게시한 컨텐츠에 표시됩니다.

3글자 이상 31글자 이하의 길이로 사용 가능합니다. dW커뮤니티 내에서는 보안상 이메일주소를 제외한 다른 이름을 지정하셔야 합니다.

3개의 &이나 대쉬를 포함해주시고 31글자내로 제한해주세요.


developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관.

 


아티클 순위

의견

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=20
Zone=리눅스
ArticleID=580244
ArticleTitle=POSIX 스레드 프로그래밍에서 메모리 누수 방지하기
publish-date=08252010
author1-email=xieweid@cn.ibm.com
author1-email-cc=

태그

Help
검색 필드를 사용하여 My developerWorks 내에서 해당 태그가 사용된 모든 종류의 컨텐츠를 검색하십시오.

태그를 더 많이 보거나 적게 보기 위해 슬라이더 막대를 사용하십시오.

인기 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 최고 인기 태그를 보여줍니다.

내 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 귀하의 태그를 보여줍니다.

검색 필드를 사용하여 My developerWorks 내에서 해당 태그가 사용된 모든 종류의 컨텐츠를 검색하십시오. 인기 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 최고 인기 태그를 보여줍니다. 내 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 귀하의 태그를 보여줍니다.