Time Machine 을 이용한 Real-Time System 에서의 Replay Debugging 에 대한 내용을 다룬 논문을 정리하였다.

ABSTRACT

이 논문은 standard component 를 사용한 결정적인(deterministic) replay 에 대한 새로운 방법을 소개한다. 우리의 방법은 산업 표준의 디버거를 사용한 산업 표준 리얼타임 시스템의 반복적인 디버깅을 용이하게 한다.
새로운 많은 기술을 기반으로 하는 방법으로서, 예를 들면, 인터럽트와 태스크의 결정적인 재생산을 위한 루프 반복 사이의 결정적인 차이를 위한 새로운 제작자 그리고 replay 세션에서 starting point 를 잘 정의하는 것으 검색할 수 있는 알고리즘, 타겟 시스템에서 replay 하기 위해 표준 디버거에서 조건적인 breakpoint 를 사용하기 위한 더 좋은 기술을 가진다.

우리는 또한 결정적인 모니터링을 위한 다른 방법과 우리 방법의 용이함을 산업의 case study 를 통해서 벤치마킹 결과를 보여주고, 논의할 것이다.
예전의 결정적인 replay 의 개념을 바탕으로 하는 실시간 시스템을 디버깅하는 문제점은 멀티 태스킹 프로그램의 task-switch 와 외부 입력(input) 같은 중요한 시스템 이벤트가 런타임 중에 record 되어지고, 후에 off-line 에서 replay 된다.
예전에는 표준이 아닌(non-standard) 하드웨어, 특별히 디자인된 컴파일러, 또는 수정된 RTOS 기반의 작업이었다. 비표준(non-standard) 컴포넌트의 신뢰는 이런 방법의 한계가 있다. 그럼에도 불구하고 이 아이디어는 20 년 동안 사용되어 왔고, 비 산업적인 애플리케이션을 위한 실시간 시스템 디버깅의 방법을 보여줘 왔다.

INTRODUCTION

테스팅은 실패(failure)에 노출되어 있다. 디버깅은 반면에 실패를 원인인 노출된 에러와 관계가 있다. 오염된 에러의 실행은 밖으로(output)으로 옮겨 갈 수 있다. 디버깅의 프로세스는 에러가 나서 실패한 곳으로 흔적을 따라간다. 에러를 노출시키기 위해서는 실패를 재생산할 수 있어야 하고 초기 시작 조건 뿐만 아니라 실패가 발생하는 초기화 상태로 부터 결정적인 실행에 대한 지식이 있어야 한다.
실시간이 아닌 순차적 프로그램의 요구조건은 실패를 재생산하기 위해서는 같은 입력과 같은 내부 상태가 적용 때문에 충분하다. 실시간 프로그램은 타이밍과 사건의 순서 때문에 좀더 복잡하다.
디버깅은 몇 가지 문제들은 순차적 프로그램(표준 상용 디버거)에서 실시간 멀티태스킹 프로그램으로 옮겨지면서 해결되어 졌다.
여기서는 두 가지 주제에 대해서 간단히 논의할 것이다.

single-tasking non-real-time 프로그렘에서 외부 context 의 독립적이고 서로 통신하는 개념이 더해진 single-tasking 실시간 프로그램으로 옮겨지고 있다. 시스템은 외부 context, context 와 상호작용하는 것을 샘플링(sampling) 하는 센서와 같다. 게다가, 시스템은 real-time clock, 외부와 내부 프로세스의 공유(shared) 시간을 준다. 만일 프로그램을 디버깅하려 한다면, 두 가지 문제에 부딪힐 것이다.

첫번째는 첫번째 실행으로 부터 sensor 값을 어떻게 재생산 할 것인가?
두번째는 어떻게 shared time base 를 보존할 것인가?

디버깅 phase 동안, 개발자는 breakpoint 를 설정하고, 실행의 single-step 이 필요하다. 그러나 실행의 중단(breaking) 은 오직 외부 프로세스가 계속될 동안 내부 실행의 프로세스를 break 할 것이다. 예를 들면, ABS-breaking 시스템은 차안에 있다. testing phase 동안에, 실패가 발견될 수 있다.
실패와 시스템이 실패가 되는 원인이 되는 버그를 찾고 재생산하기 위해, 디버거를 재실행한다. 그러나 어떤 지점의 breakpoint 를 지정해서 시스템의 실행을 breaking 하는 것은 halt 가 되는 원인이 될 수 있다. 자동차에서 본래 멈추지 않는다. 중간정도의 방법과 shared time base, 내부와 외부의 시스템은 잃을 것이다.
이것은 동시에 시스템의 상태를 점검하는 동안 결정적인 실패를 재생산할 수 있다.

순차적 실시간 프로그램 디버깅에서 멀티태스킹 실시간 프로그램 디버깅으로 이동하면서 실행시에 단일(single) 프로세서 상에서 동시에 문제점들이 표면으로 드러나고 있다. 시스템이 태스크들로 구성되어 있을 때, 태스크는 서로 다른 일시적으로 기능적인 domain 들과 상호연동할 것이다.
스케줄링-이벤트와 하드웨어 인터럽트는 시스템의 태스크들 사이에 실행순서를 바꾼다. 게다가 자원을 공유하는 것은 동기화 매커니즘을 이용해서 race condition(동시에 read 하려고 하는) 하는 태스크들을 중재해야 한다.
더구나, 그림 1을 보면 진단의 탐침이 삽입과 이동은 비결정적 race 의 원인이 될 수 있다. 이것은 탐침 효과라고 하고, 관찰할 때마다 행동이 바뀔 수 있다.
위의 그림은 원래는 실패가 발생해야 하지만, 탐침을 추가함으로서 시간 바뀌어 실패를 재생산 할 수 없다.

우리는 결정적인 replay 기반의 디버깅 방법을 설명하고 있다. 우리는 Time Machine 라고 부른다. 예전과는 달리, 특별한 디버거, 수정된 RTOS 나 작업을 위한 코드 변환이 필요가 없다. 표준 off-the-shelf(언제든지 구할 수 있는) 디버거와 RTOS 면 충분하다.
런타임 동안, 인터럽트, task-switches, timing 그리고 데이터를 record 되어야 한다. 시스템 실행은 recorded history, 상세화의 단계를 사용함으로서 결정적으로 재실행이 가능하다. 시스템이 저장된 모든 계산한 데이터를 결정적으로 재실행한다면, 크기가 커질 것이다.
우리는 런타임 수행에 다음이 포함될 것이다. 인터럽트, task-switches, data 를 off-line 에 재생산할 수 있다.
우리는 어떻게 JTAG, BDM, ICE 이벤트가 발생했을 때 정확한 머신 코드를 위해 정확한 타이밍을 위한 CPU 명령어 레벨 시뮬레이터를 사용해서 앞 과 뒤 둘다 시스템을 디버깅할 수 있는지 보여줄 것이다.

이 논문의 기여는 다음과 같이 요약할 수 있다.

  1. 싱글 태스킹과 멀티 태스킹 실시간 시스템의 결정적인 replay 를 위한 첫번째 방법은 표준 규격 디버거와 RTOS 를 사용하는 것이다.
  2. 새로운 방법을 사용함으로서 카운터 명령(instruction) 없이 replay 를 실현하기 위해 컴파일러와 RTOS 에 독립적이다.
  3. 최근 산업 case study 의 벤치마킹 결과, 우리의 Time Machine 기술이 산업 로봇 컨트롤러 부분의 25 백만 라인에 성공적으로 적용했다.

RELATED WORK

관련연구가 concurrent 프로그램과 실시간 시스템의 replay 디버깅은 아주 오래 되었고, 빈약하다. 예전에는 의존적인 특별한 하드웨어나 컴파일러가 명령어 코드를 만들고 표준 하드웨어와 RTOS 상에 그들의 솔루션에 제한이 있다.
다른 방법은 특별한 하드웨어나 컴파일러에 의존하진 않지만, 오직 replay concurrent 프로그램 실행 이벤트가 연속해서 발생하는 경우는 부족하다.
그러나 우선순위, 비동기 인터럽트 또는 상호배제 오퍼레이션 같은 특별한 실시간 이벤트.
우리 결정적인 replay 기술의 초기 버전에서는 인터럽트의 replay, 태스크의 우선순위, 트랜젝션의 분배를 지원했었다. 그러나 이 작업은 RTOS 의 특별한 off-line 버전의 존재를 가정한다. 현재 상용 RTOS 시스템을 위한 그럴듯한 가정은 아니었다.
그것은 또한 유일한 제작자에 의지하고, 표준 컴포넌트들은 적당하지 않았다. 이 논문에서는 표준 컴포넌트를 위한 예전 결과를 만든다.

THE SYSTEM MODEL

시스템 소프트웨어는 RTOS 와 동시에 수행되는 태스크들, 인터럽트 루틴, 공유 메모리간에 또는 메세지들간의 통신으로 이루어 진다. 태스크와 인터럽트는 우선순위, blocking, 메세지 전달 그리고 공유 메모리의 의한 기능적 일시 부작용을 가질 수 있다. 우리는 on-line 우선순위 스케줄링을 지원하는 실시간 커널의 single 프로그램 시스템에서 멀티 태스킹 시스템까지 콘트롤할 수 있는 인터럽트를 허용한다.
우리는 동기 또는 비동기를 위한 시스템의 control-flow 이벤트를 정의한다. 동기적인 이벤트들은 잠재적인 blocking 시스템 콜에 의해서 정의된다.
우리가 알고 있는 semTask() 같은 들어가고(entry) 빠져나가는(exit) 시스템 콜.
비동기적인 이벤드들은 인터럽트 hit 나 우선순위 스케줄링에 의해서 정의된다. 이것은 시스템이 control-flow 가 어디서 변하는지 연역적으로 알기 힘들다.
우리는 명령어 수준의 시뮬레이터 디버거, JTAG, BDM, ICE 디버거를 접근할 수 있다는 것을 가정한다. 또한 디버거의 인터페이스 또는 scripting language 를 이용해서 매크로(macro) 또는 프로그램은 타겟 메모리에 접근하거나, breakpoint 를 조건적으로 지정할 수 있다고 가정한다.
우리는 non-ICE based system 에 대해서는 RTOS 가 실행하는 동안에 task switch 는 record 할 수 있는 hooks 을 가지고 있다고 가정한다(대부분 상용 RTOS 에서 실행).

THE MECHANISMS OF THE TIME MACHINE

time travel 과 결정적인 replay 를 달성하기 위해서 우리의 방법을 설명하고 의논할 것이다. Time Machine 디버깅 방법의 기본 요소는 다음과 같다.

  1. Recorder : task-switch, interrupts, data 에 관련한 필요한 모든 정보를 모으는 in-target 매커니즘
  2. Historian : recording 에서 자동적으로 분석하고, 관련있는 이벤트와 데이터, 그리고 breakpoint 와 predicate(단정)의 시간순의 timeline 을 만든다.
  3. Time Traveler : 디버거와 historian 으로 부터 제공되는 정보를 주어지고, historian 의 어떤 주어진 시간의 메모리의 유효범위를 위한 프로그램 상태의 재생성을 허용한다(상태변수, 전역변수, 프로그램 카운터 등).
  4. 이 프로세스는 target 실행가능한 코드의 변화 없이 수행된다. 같은 코드(RTOS 에 포함된)가 타겟에서 수행되고, 실행되는 동안, 디버거에서 실행을 replay 한다.

상태변수, 센서 값을 읽은 입력값 또는 local lock 을 접근하기 위한 이벤트들은 애플리케이션을 위해서 확인하고 record 된다. off-line 에서는 재생산하는 것이 가능하다. 외부 시스템을 분리하는 것과 시스템의 진행은 실시간 시스템의 결정적인 replay 를 수행할 때에 필요하다.
우리는 data-flow 모니터링 또는 recording 로서, 의존적인 data 는 recording application 의 프로세스라고 불린다. 오직 우리가 최근에 시스템을 재실행하는 것과 그 결과로서 모든 중간(intermediate) 변수값과 output 들은 재계산된 이래로 외부적인 input 과 외부적인 상태 변수들은 가치가 없다.

멀티 태스킹 실시간 시스템을 replay 하고 디버깅하기 위해서는 monitor 가 필요하며, 추가적으로 data-flow 와 system control-flow 가 필요하다.
본질적으로 control-flow 는 인터럽트와 task switch 가 일어날 때 일치한다. 예를 들면, 하나의 태스크에서 다른 태스크로 부터의 control 할 때 모든 전송되는 모든 것들 또는 인터럽트 서비스 루틴의 태스크로 부터의 모든 것들이다. 이런 이벤트를 확인하기 위해서, 우리는 timestamps 와 프로그램 카운터(PC) 를 사용하여 언제 그리고 어디서 발생했는지를 record 할 것이다. 그러나 PC 값으로 부터는 loop, 서브루틴, 반복되는 호출, 발생하는 이벤트를 위한 유일한 marker 를 정의하기 위해서 요구되어지는 추가적인 정보는 재방문(revisited) 될 수 있다. PC 는 유일한 marker 로서 충분하지 않다.

예전 작업에서, 하드웨어와 소프트웨어 instruction counter 는 이런 목적을 위해서 제안되어지고 있다. 그러나 상용 RTOS 를 다룰 때, 우리는 보통 소스코드를 접근하지 않음으로 부터, RTOS task context 을 사용함으로써, in 과 out 될 때 각 인터럽트와 태스크를 위한 instruction counter 값의 정확한 저장과 로드를 옵션으로 가지지 않는다. 그 결과, 다른 방법이 필요하다.

비동기 이벤트를 위해서, 우리 디자인의 실용적인 방법은 user-stack 체크섬의 part and/or register-bank 체크섬, stack pointer 의 값을 저장하기 위해서 OS 와 다른 생성(make)를 좀더 일반적으로 한다.
루프반복(loop-iteration) counter 는 레지스터에 저장되고, stack-checksum 은 여분에 저장되도록 제공된다. 그렇지 않으면, 유저스택의 subset 의 체크섬은 현재 실행되는 함수또는 태스크를 실행함으로써 스택의 부분으로 사용되어진다.
비동기 이벤트로서의 체크섬을 계산함으로써, 우리는 유일한 marker 를 정의할 수 있다. 4-tuple <t, PC, SP, CHKSUMS>
SP 는 스택 포인터로서, 함수 호출들을 구분짓는다. marker 는 유일하지는 않지만 애플리케이션의 큰 숫자를 가짐으로서 정확한 분별을 할 수 있다.
그것은 유일한 marker 에 충분하고 실용적인 접근이다.
레지스터 체크섬을 정확히 동작시키려면, 모든 활성화 구간(period)(예를 들면 무한 루프) 마다 그 레지스터들을 reset 하는 태스크가 필요하다.
스택 체크섬에 관해서는 컴파일러로 만들어진 코드는 항상 스택 공간이 0 으로 초기화 된다.
우리는 다른 플랫폼에 이 체크섬 방법을 성공적으로 적용시킬 수 있었다.

  1. 프로세서, 8/16 bit CISC Hitatchi H8, 32 bit RISC NEC V850, 32 bit CISC Intel Pentium
  2. 컴파일러, GNU GCC(Hitatchi H8, Intel x86), IAR Systems(Hitatchi H8, NEC V850).
  3. RTOS, VxWorks, Asterix

동기적인 이벤트를 위해서는 덜 정교한 방법이 필요하다. 우리는 per-task counter 을 사용하고, 증가되는 시간에 잠재적인 blocking system call 이 태스크에 의해서 불러낸다.
만일 태스크에 실제적으로 blocking 이 호출되면, counter 의 값은 유일한 marker 로서 record 되고, counter 는 reset 된다. 이 방법은 우리가 태스크가 실제적으로 block 되어졌을 때, 시스템 콜의 기원(invocation)의 진로를 쫓아갈 수 있을 것이다.

recording 하는 것은 간섭에 자유로운(intrusive-free) 하드웨어에서 부터 mobile software recorder 는 간섭하기 때문에 고정된(immobile) recorder 에 이르기까지 여러가지 방법이 있다. 게다가 시스템의 recording 매커니즘의 나머지 옵션은 black-box 기능성의 동등한 장점을 가진다.
비행기에 고용된 것과 비슷하다(일반적으로 주기적인 버퍼를 수행함).
우리는 3 가지 타입의 recording 방법을 제시한다. 리소스 가용성(available) 에 적당히 의존하고, 타겟 시스템의 아키텍처 그리고 black-box 기능성이든 아니든 요구되어지는 곳에 사용되는 방법이다.

dual port ram 과 함께 ICE 를 사용한다. ICE 는 보통 CPU 를 대신한다. 그것은 CPU 타겟 소켓에 꼽혀지고(plugged-in), 그리고 시스템의 나머지와 인터페이스 한다.
보통 CPU으로 부터 다른 점은 보조의 output 이 사용가능하다는 점이다. 만일 ICE(Lauterbach, AMC)가 RTOS awareness(task control block structure and location 을 알고 있음)를 가진다면, history record 의 이 방식은 타겟 시스템의 중계가 필요없다. 오직 input 은 모니터링하기 위한 데이터의 위치가 필요할 뿐이다. ICE 는 가격과 공간의 제한 때문에 일반적으로 상품에 포함되지 않고 어떤 CPU 사이클이나 타겟 메모리를 훔치지 않음으로써 잠재적으로 간섭이 없다.
이런 타입의 history recorder 에서 애플리케이션은 그 결과로서 pre-deployment(미리 배치하는) lab 의 testing 과 debugging 에 가장 적당하다.

OS 와 애플리케이션 소프트웨어에 다수의 local 순환(circular) memory buffer 에 histories 를 저장하는 것을 설치한다.
이 타입의 시스템은 CPU 사이클과 이벤트들의 저장을 위한 메모리를 가정하는 현상을 간섭한다. 소프트웨어 방법의 한가지 장점은 시스템 안으로 부터 모니터링을 수행할 수 있다는 것이다. 이런 이유로 on-chip memory 와 caches 는 타입 1 의 recorder 를 사용한다면, 찾아내기 힘들다.
또한 replay 동안에 필요한 record data 를 복구할 수 없다. 예를 들면, 외관상으로 실험(sampled) 데이터와 상태 변수들.
control-flow 모니터링과 대조를 이루어, 자동적으로 실행할 수 있고, 애플리케이션에 독립적이고, data-flow 를 모니터링 하기 위해 monitor wrappers 를 사용해서 손수 확인(identified) 과 추적장치를 붙이는(tagged) 작업이 필요하다.
예를 들면,

Monitor(&var, log_entry, sizeof(var_type));

monitor wrappers 를 recording 하는 동안에 data-flow recording log 의 'var' 에서 'log_entry' 를 명시한다.
반대로 replay 를 수행하는 동안에는 'var' 에는 record 된 output 의 값이 할당된다. 모든 이런 코드 설치는 CPU 사이클을 가정해야 할 것이다. 그것은 반드시 탐침효과를 제거하기 위해서 post-deployment(배치한 후) 타겟 시스템에 남는다. 이 방법은 hardware 와 hybrid 방법과는 대조적으로 black-box 기능성을 허용한다.

이 방법은 hardware 지원과 최소한의 타겟 소프트웨어 코드 설치를 가진다. 소프트웨어 probe 는 특정한 주소에 history data 를 쓴다. 그리고 hardware 컴포넌트는 일반적으로 logic analyzer(예를 들면, Microtek) 의 형태로 이 주소 버스에 기웃거린다.
recording 시스템의 이 방법은 만일 모든 데이터 조정과 상태를 시스템의 external memory 에 반영할 수 있다면, 그리고 RTOS 와 data awareness(kernel data structures 와 variable locations)을 가진다면, 간섭에 자유롭다.
그러나 많은 마이크로 콘트롤러들과 CPU 는 on-chip memory 와 cache 를 가진다. 이런 이유로 시스템의 상태와 데이터의 변화가 external memory 에 반영되어지는게 필요가 없다.
그 결과로서, 이벤트와 데이터를 모니터된 것을 external memory 에 record 하고 stored 하는 도구를 수행하기 위해 필요하다. 일시적으로 cache 와 on-chip memory 는 bypassing 한다.
data-flow 모니터링은 software recorder 과 비슷하며, cache write-throughs 와 느린 external memory 의 접근 때문에 컴퓨터가 느려지는 단점이 있다.
이 방법의 history recorder 는 ICE 보다는 저렴하다. 그러나 타겟 시스템에 적용된 하드웨어를 모니터링하는 것은 아직
그러나 SoC 해결책은 영구히 상주될 수 있다.

애플리케이션의 control-flow 와 data-flow 을 한번 record 하면, historina 의 첫번째 작업은 timeline 의 발생과 만들어진 순으로 control-flow 이벤트를 정렬한다.
control-flow 이벤트는 비동기(태스크 우선순위 또는 인터럽트) 또는 동기(blocking system call) 이다.
각 비동기 control-flow 이벤트를 위해서, historian 은 conditional breakpoint 를 만들어낸다. 각 PC 값은 비동기 control-flow 이벤트가 발생했을 때의 값이고, breakpoint 는 설정된다.
이 breakpoint 는 record 된 유일한 marker 의 상태에 의해서 보호된다. 예를 들면, <t, PC, SP, CHKSUMS>.

break at PC(event) if(SP == SP(event) &&
CHKSUMS_REGS(event) == (R0+R1+R2+...+Rn) &&
CHKSUMS_STACK(event) == (*(SP) +*(SP+1)+*(SP+2)+*(SP+m)))

동기적인 이벤트들은 그 반면에, 유일한 개인적인 breakpoint 에 의해서 표현할 수 없다. 대신에 각 bolcking system call 의 entry point 는 애플리케이션에 의해 사용되고, 동기적인 이벤트를 breakpoint 하기 위해 일으킬 수도 있다.
동기적 유일한 marker 의 조절(control)과 match 는 Time Traveller tool 에 의해서 관리되어 진다. 실행하는 태스크에서 다음의 태스크까지 조절(control) 을 전송함으로써.

timeline 은 control-flow 와 비슷하고, data-flow 를 위해 모은다. 데이터와 control-flow 사이의 매끄러운 상관관계를 허용하기 위해, 모니터링 활동들을 밀접하게 통합한다. 그로 인해 시스템 콜을 모니터링하고, data-flow 를 모니터링하는 것은 또한 수행된다. 앞으로의 세션들에서 우리는 replay 가 초기화 되어지는 것으로부터 시스템 콜 포인트를 이벤트에 매핑하는 것을 보여줄 것이다. 데이터 복구는 replay 동안에 on-target 을 조작할 수 있다. software 또는 hybrid recorders, 또는 data breakpoint 를 설정하기 위한 ICE 디버거 환경에 의한, read 오퍼레이션이 수행될 때, 우리는 읽기 전의 값을 복구하거나, 가로챌 수 있는 경우에 monitor-wrapper 를 사용함으로써 조작할 수 있다.

data-flow 와 control-flow timeline 을 사용하기 위해서는 결정적인 재실행을 완수하기 위해서 historian 에 의해 만들어야 한다. 그것은 replay 를 위해 서로의 starting point 를 찾는 것는 중요하다. 다른 말로, 우리는 control-flow log entry 와 replay 재실행을 시작하기 위해 data instance(단계)를 이해할 필요가 있다. 대부분의 방법은 시스템이 start-up 으로 부터 replay 을 시작한다.
애플리케이션의 모든 static 정보는 알고 있다. 그러나 시작부터 실패까지의 entire history 를 capture 하기 위해 상식을 벗어난 긴 recording 을 위한 보통의 호출이다. 좀더 합당한 방법은 recording 을 위해서 순환적인(cyclic) buffer 의 세트를 사용하는 것이다.
non-startup 상태로 부터 replay 를 시작하는 것이 가지는 문제점은 가지고 있다.

결정적인 replay 의 기본 아이디어는 record 되었던 실행환경과 완전히 동일한 상태에서 애플리케이션을 실행하는 것이다. 기본 요구조건은 control-flow 와 data-flow 정보가 replay context 의 시작이 사용가능하도록 구성하는 것이다. 예를 들면, 그림 3a 의 시나리오이다.
cyclic buffer 의 넓이 때문에, control-flow timeline 은 t1 에서 t_sysfail 까지 거리이다. 가장 짧은 data flow timeline 은 t2 에서 t_sysfail 까지 거리이다.
이 경우에 t1 과 t2 사이의 replay starting point 는 사용가능한 data flow 정보가 없기 때문에 정확하지 않다. 비슷하게, 그림 3d는 사용가능한 control-flow 정보가 없다는 것을 보여준다.

replay starting point 의 사용가능한 data flow 의 요구조건은 어떤 record data 를 선택하는 것에 신중해야 한다. 모든 태스크는 하나 또는 그 이상의 replay 를 위한 잠재적인 starting point 를 가진다. 이 starting point 들은 blocking system call 또는 task activation 을 할 수 있다.
특정한 point 의 태스크의 replay 를 시작하기 위해서는 존재하는 최소 하나의 control-flow log 의 entry, 태스크 상태의 정보와 input 은 point 의 재실행 log 로부터 되찾기 위해 필요하다.
그림 4 는 태스크 프로그램이다. 이 태스크는 두 개의 잠재적인 blocking system call(msgQReceive and msgQSend) 을 가지고 있다.

While(FOREVER)
{
msgQReceive();
monitor();
...
msgQSend();
...
}

둘다, task switch 의 원인이 될때, control-flow buffer 에 record 된다. 그러나, 오직 calls(msgQReceive) 의 하나는 직접적인 그 다음의 data flow monitoring call 을 가진다. store(on-line) 또는 restores(during replay) 태스크 상태와 input. 이 사실은 이 호출이 replay 를 위한 적당한 starting point 를 만든다. 태스크 상태의 옳은 복구를 보장할수 있는 가능성을 가지고 있지 않은 다른 호출로 부터 start 하는 동안에.
system calls 의 반대로서, control-flow 우선순위 또는 인터럽트 이벤트들은 비동기적으로 발생되는 사실 때문에 replay starting point 로서 적당하지 않다. task context entire 에 관련되고, 필요한 start 상태를 캡쳐하기 위해서.

모든 blocking system call 에서 breakpoint 를 설정하는 것으로 인하여, 우리는 애플리케이션의 결정적인 재실행을 초기화할 수 있다.
첫째로 애플리케이션이 디버거와 timeline index 에서 reset 된다. index pointing 은 match 하기 위한 현재 control-flow 이벤트는 control-flow timeline 의 첫번째 적당한 starting point 를 설정할 수 있다. 그래서 각 태스크는 breakpoint 가 historian 이 만든 timeline 의 적당한 starting point 에 match 될 때까지 replay 되어 수행한다. 이 point 에서 중단된 태스크의 record 된 data flow 는 애플리케이션으로 다시 쓰여진다.
timeline index 는 증가되어지고, 다음 태스크는 실행을 위해 셋업된다. 일단 모든 설치된 태스크의 data flow 는 애플리케이션에 다시 쓰여지면, replay 세션은 초기화 phase 가 완료된다.

초기화 준비(ready)되면, replay 는 각 control-flow 이벤트가 성공적으로 match 되면, timeline index 는 증가됨으로서 앞쪽으로 (한발) 나아간다.
게다가, historian timeline 의 현재 태스크를 위한 이후의 비동기적 이벤트의 겨웅에, 그 상응하는 conditional breakpoint 가 설정된다. 그것은 breakpoint 가 hit 되는 것에 따라 이벤트를 replay 하는 것을 가능하게 만든다.
비동기 이벤트를 나타내는 breakpoint 가 hit 되고 성공적으로 match 되면, 그것은 replay 세션의 성능을 강화하기 위해서 지워진다.
사용자의 관점으로부터 이 결정적인 replay 디버그 세션은 record 된 멀티태스킹 실시간 애플리케이션의 정확한 실행을 모방하고 있는 규칙적인 순차적 프로그램 처럼 정확하게 동작할 것이다. 우리는 single step 을 할 수 있고, 어떤 breakpoint 의 숫자든 추가할 수 있고, 탐침효과 없이 data 를 검사할 수 있다(그림 5). 우리는 디버거(Time Machine 라 불림)를 사용해서 시간의 앞과 뒤로 jump 할 수 있고, 새로운 유일한 marker와 새로운 보호하는 breakpoint 를 만들므로서 bookmark 를 정의할 수 있다. 우리는 실시간의 external process 의 의존성을 제거하고, historian 에 의해서 생산되는 가상 data-flow 와 control-flow timelines 과 함께 애플리케이션의 일시적이고 기능적인 context 를 바꿨던 이래로, 우리는 시스템의 history 를 되풀이하여 replay 할 수 있다.

이 섹션에서는 산업 로봇 콘트롤 시스템 상에서 수행한 결과를 설명한다. 연구되어진 개발자는 ABB Robotics 로서 세계에서 가장 큰 회사이다. 시스템은 몇개의 컴퓨팅 콘트롤 시스템, 시그널 프로세싱 시스템과 I/O unit 으로 구성되어 있다. 우리는 대략 VxWorks 에서 실행하는 25 만 라인의 C 코드로 이루어진 시스템의 motion control part 에 Time Machine 를 적용했다. motion control subsystem 은 hard real-time 시스템으로서, 약 70 개의 태스크가 수행한다.(매 4 ms 마다 태스크가 활성화됨) 그리고 복수의 인터럽트를 제어하는 디바이스 드라이버의 구분이다.
시스템 콜이 호출되어 control-flow 가 변경 되는 지점을 모니터링 한다(msgQReceive, msgQSend, semGive, semTake and taskDelay).
이 시스템 콜에 설치는 timestamp, system call identifier, counter 에 의해 제한된다. system call msgQReceive 를 위해서 우리는 data-flow recording 을 포함시켰다. 지금까지의 모든 추가는 애플리케이션 코드상에서 수행한 것이다.
애플리케이션 코드를 추가해야 했던 유일한 수동(manual) 수단은 태스크의 상태를 캡쳐하기 위해, blocking system call 후의 data-flow monitor 를 호출하는 것이다.(특정한 local 과 global 변수)
코드가 재실행하게 된 offline 인 이래로 recording 의 양은 충분하다.
이 사례연구에서 시스템의 아키텍처 때문에, 각 msgQReceive call 후의 상태를 충분히 캡쳐할 수 있었다.(그림 6)
실행 오버헤드와 메모리 사용량의 관하여 모니터링한 것의 비용을 보여준다. control-flow recording 에 관해서 종합적인 비용을 요약하면, 프로세스 사용량의 약 0.05 % 그리고 dataflow recording 은 4 % 보다 적고, data 사용량은 약 2 MB 정도 된다.

FUTURE WORK

우리는 다른 운영체제, 다른 하드웨어, 다른 디버거, 다른 컴파일러 상에서 time machine 방법을 성공적으로 적용시켰다.
우리는 연구했지만, 그러나 데이터를 재실행하고, 재전송하고, 데이터가 외부 프로세스를 기점으로하는 것이 신중하게 타겟 시스템 dataflow 를 분석하는 것이 필요하다. 결정적인 재실행또는 너무 많이 record 하는 것을 금지할지도 모르는 상태에서 앞장서지 않는다. 사라진 정보는 시작할 주소를 가지며, 심각한 문제이다. 다른 문제는 거대한 정보를 애플리케이션을 replay 하는데 사용하는 것이다. 예를 들면, 실시간 데이터베이스.
애플리케이션의 상태변수(data base)는 아주 크고, 그것을 제어하는 알고리즘이 요구된다.

CONCLUSIONS

이 논문의 contribution 의 요약은 결정적인 replay 방법 이다. 표준 일반 디버거와 표준 일반 운영체제을 위한 방법.
우리는 case study 를 통해 효용성을 입증했다. 우리는 recording 을 위한 다른 방법을 보였고, post deployment 디버깅을 위한 black-box functionality 를 소개했다. 우리는 실행시간 동안 recording 함으로써, task-switch 와 인터럽트의 정확한 위치와 시간을 만들기 위해 표준 디버거를 이용해 conditional breakpoint 를 어떻게 사용하는지 보였다.
우리는 함수호출 뿐만 아니라, 루프들 사이에서 차이점을 위한 새롭고 실용적인 유일한 marker 매커니즘을 보였다.
게다가 우리는 산업 case study 를 통해서 벤치마킹한 결과를 보였다.

추가할 점

잊어버리기 전에 정리한다.
이 논문에서는 크게 control-flow 와 data-flow 에 대해서 설명하고 있다. control-flow 는 프로그램의 실행 순서를 바꿀 수 있는 이벤트(인터럽트)를 의미하고, data-flow 는 일반 변수값의 변화를 설명하고 있다.
control-flow 의 경우에는 OS 레벨에서의 수정이 필요하고, data-flow 는 애플리케이션 레벨에서 monitor-wrapper 를 선언해서 수행한다.
hybrid recorder 의 경우, 기존의 software recorder 와 logic analyzer 방식을 합친 방식이다.
이 논문에서는 instruction counter 를 사용하지 않았다고, 설명하고 있다. 기존의 경우, timestamp 와 pc 값을 가지고도 유일한 marker 를 생성할 수 있었지만, 여기서는 instruction counter 을 사용하지 않고 체크섬(각각의 레지스터의 값을 모두 더한 것)이라고 하는 것을 이용해서 유일한 marker 를 만들 수 있다고 설명하고 있다. instruction counter 를 사용하지 않음으로서 오버헤드를 줄였다고 설명하고 있다.

  • computer/rtcclab/replay_debugging_of_real-time_systems_using_time_machines.txt
  • Last modified: 3 years ago
  • by likewind