블로그는 나의 힘!
[ Programing ]/OS - Linux2010. 6. 21. 12:59

다중 쓰레드인 프로그램 디버깅하기




  몇몇 OS에서, 단일 프로그램은 실행시 하나 이상의 쓰레드를 가질지도 모른다.

쓰레드의 정확한 의미는 OS마다 다르지만, 일반적으로 단일 프로그램에서 쓰레드는 다중 프로세스와 비슷하다.

-- 하나의 주소 공간을 공유하는것을 제외하고(즉, 그들은 같은 변수를 검사하고 수정한다.) 다른 한편으로, 
    각 쓰레드는 자신의 레지스터와 실행스택 그리고 각자의 메모리를 가진다.

 

GDB는 다중 쓰레드 프로그램을 디버깅할수 있는 기능을 제공한다.

  • 새 쓰레드에 대한 자동 알림
  • 쓰레드를 바꿀수 있는 명령어 `thread threadno'
  • 현재 쓰레드 목록 보는 명령어 `info threads'
  • 쓰레드 리스트에 명령어를 적용할수 있는 명령어 `thread apply [threadno] [all] args'
  • thread별 breakpoints


경고: 이 기능은 쓰레드를 지원하는 OS하의 모든 GDB 설정에서 이용할수 있는것은 아니다. 만일 여러분의 GDB가 쓰레드를 지원하지 않는다면, 이들 명령어는 효과가 없다. 예를 들어, 쓰레드 지원을 하지 않는 시스템은 `info threads'시 정보를 보여주지 않으며 다음과 같이 thread 명령시 이를 거절한다.:

(gdb) info threads (gdb) thread 1Thread ID 1 not known. Use the "info threads" command to see the IDs of currently known threads.




GDB의 쓰레드 디버깅 기능은 프로그램을 돌리는 동안 모든 쓰레드를 관찰할수 있도록 해준다.

--그러나 GDB가 제어를 가지고 있을때는 언제나, 특별히 하나의 쓰레드가 디버깅의 중심이다. 
   이 쓰레드는 current thread라 불린다. 디버깅 명령어는 현재 쓰레드의 관점에서 프로그램 정보를 보여준다.




GDB가 프로그램에서 새로운 쓰레드를 발견할때마다, `[New systag]' 형태로 쓰레드에 대한 타겟 시스템 식별자를 보여준다.
systag는 쓰레드 식별자이며 형태는 시스템에 의존한다. 

 예를 들어, LynxOS에서 
[New process 35 thread 27]

GDB가 새로운 쓰레드를 발견할때 볼수 있다.
대조적으로, SGI 시스템에서 systag는 단순히 `process 368'와 같다.
디버깅 목적으로, GDB는 자신의 쓰레드 수--항상 단일 정수--를 가지고 있다. 


 info threads 프로그램에 있는 현재 모든 쓰레드의 요약을 출력한다. GDB는 다음 순서로 각 쓰레드를 출력한다.:

  1. GDB에 의해 대입된 쓰레드 넘버
  2. 타겟 시스템의 쓰레드 식별자(systag)
  3. 그 쓰레드를 위한 현재 스택 프레임 요약
  4. GDB 쓰레드 넘버 왼쪽의 `*'는 현재 쓰레드를 가리킨다.

예를 들어, (gdb) info threads 3 process 35 thread 27 0x34e5 in sigpause () 2 process 35 thread 23 0x34e5 in sigpause () * 1 process 35 thread 13 main (argc=1, argv=0x7ffffff8) at threadtest.c:68 thread threadno 쓰레드 넘버 threadno를 현재 thread로 만들어라.

이 명령어 인자 threadno는 `info threads' 출력의 처음 필드에서 보여준 것 처럼 내부 GDB 쓰레드 넘버이다.
GDB는 선택한 thread의 시스템 식별자와 현재 스택 프레임 요약을 출력함으로써 응답한다;
 
(gdb) thread 2 [Switching to process 35 thread 23]0x34e5 in sigpause () `[New ...]'메세지에서 처럼,
`Switching to'의 텍스트의 형태는 쓰레드 식별을 위한 시스템 편리성에 의존한다.
thread apply [threadno] [all] args thread apply 명령어는 하나나 그 이상의 쓰레드 명령어를 적용할수 있도록 허용한다.

명령어 인자 threadno로 영향 받기를 원하는 쓰레드의 수를 지정한다. 
threadno는 `info threads' 출력의 처음 필드에서 보여 준 내부 쓰레드 중 하나 이다.
모든 쓰레드에 명령어를 적용할려면, thread apply all args를 사용해라.

 
GDB가 breakpoint, signal 때문에 프로그램을 중지시킬때마다,
GDB는 자동적으로 breakpoint나 signal이 일어난 쓰레드를 선택한다.
GDB는 쓰레드를 식별하기 위해 `[Switching to systag]' 형태의 메세지를 가지고 문맥 교환을 하도록 해준다.





다중 쓰레드 프로그램의 중지와 시작

여러분은 모든 쓰레드나 특정 쓰레드에 breakpoint를 설정할지 안할지를 선택할수 있다.
break linespec thread threadno
break linespec thread threadno if ... linespec는 소스 라인을 지정한다.;

쓰는 몇가지 방법이 있지만 효과는 몇몇 소스 라인을 항상 지정하는 것이다.


특정 쓰레드가 이 breakpoint에 도착할때 프로그램이 멈추길 원하면 breakpoint 명령어와 함께 `thread threadno'를 사용하라.
threadno는 `info threads' 쓰레드 목록에 보여진 것처럼 GDB에 의해 대입된 쓰레드 식별자중 하나이다.

만일 breakpoint를 설정할때 `thread threadno'를 지정하지 않는다면, breakpoint는 프로그램의 모든 쓰레드에 적용된다.

조건적 breakpoint에서 thread 식별자를 사용할수 있다. 
이런 경우, 다음처럼 breakpoint 조건 전에 `thread threadno'를 사용 하라.

(gdb) break frik.c:13 thread 28 if bartab > lim

프로그램이 어떤 이유때문에 GDB하에서 멈추었다면, 현재 쓰레드만이 아니라 실행중인 모든 쓰레드는 멈춘다. 
변경될것들에 대해 걱정없이 쓰레드를 바꾸는걸 포함하여 프로그램의 전체적인 상태를 검사하도록 허용한다.

거꾸로, 프로그램을 다시 시작할때 모든 쓰레드는 실행을 시작한다.
step이나 next같은 명령어를 가지고 단일 stepping을 할때도 마찬가지 이다.


GDB는 모든 쓰레드에 단일 stepping을 할수 없다.
쓰레드 스케줄링을 하는 것은 디버깅하는 타겟 OS(GDB에 의해 제어되지 않는다.)이기 때문에,
다른 쓰레드들은 현재 쓰레드가 단일 step을 완성하는 동안 한 문장 더 실행한다.

일반적으로 다른 쓰레드는 프로그램이 멈출때 문제점을 제외하기 보다는 문장 중간에 멈춘다.
continue나 단일-stepping후 다른 쓰레드에서 멈춘 프로그램을 발견할수 있다. 
처음 쓰레드가  요구를 마치기 전에 몇몇 다른 쓰레드가 breakpoint, 신호 또는 예외시에 돌아갈때 일어난다.

 
 
 
출저 :
 
Posted by Mister_Q