2008-10-08 4 views
8

나는 실행중인 프로그램의 상태를 디스크에 저장하고 다시 가져 오는 기본 원칙을 열심히 찾고있다. 현재 가지고있는 디자인에서 각 객체 (함수 포인터 목록, 저수준 집에서 만든 객체 지향의 C 레벨 객체, 그리고 이런 식으로하는 좋은 이유가 있습니다)은 명시 적 상태를 쓰기 및 복원 가능한 형식으로 내보내는 데 호출됩니다. 이 작업을 수행하는 핵심 속성은 객체와 관련된 모든 상태가 실제로 객체 데이터 구조에 캡슐화되어 있다는 것입니다.개체의 직렬화 : 스레드 상태가 관련 될 수는 없습니다. 맞습니까?

일부 개체에 사용자 수준 스레드가 연결된 활성 개체로 작업하는 다른 솔루션이 있습니다. 따라서 프로그램 카운터, 레지스터 내용 및 스택 내용이 갑자기 프로그램 상태가됩니다. 내가 볼 수있는 한, 임의의 시점에 디스크에 이러한 일을 직렬화하는 좋은 방법은 없습니다. 스레드는 프로그램 카운터 등으로 표현되는 것이없는 특별한 상태로 스스로 가야하므로 기본적으로 실행 상태 시스템 상태를 명시 적 객체 상태로 "저장"합니다.

필자는 일련의 직렬화 라이브러리를 살펴 보았으며 이것이 보편적 인 속성이라고 말할 수있는 한 알 수 있습니다.

핵심 질문은 다음과 같습니다. 아니면 실제로 그렇지 않은가요? 스레드 코드를 스레드에서 실행하는 측면에서 스레드 상태를 포함 할 수있는 저장/복원 솔루션이 있습니까?

가상 시스템에 전체 시스템 상태를 저장해도 실제로는 상태를 직렬화하는 것이 아니라 컴퓨터를 정지하고 옮기는 것입니다. 그것은 분명한 해결책이지만, 대부분의 경우 약간 중량이 있습니다.

몇 가지 질문을 통해 나는 우리가 어떻게 일하는가에 대한 아이디어를 설명 할만큼 명확하지 않다는 것을 분명히했습니다. 우리는 내부에서 실행되는 코드에 대한 매우 엄격한 규칙을 사용하여 시뮬레이터 시스템을 작성하고 있습니다. 특히 객체 생성과 객체 상태를 완전히 나눕니다. 인터페이스 함수 포인터는 시스템을 설정할 때마다 다시 작성되며 상태의 일부가 아닙니다. 상태는 내부 런타임 표현과 저장 표현 사이를 변환하는 정의 된 get/set 함수가있는 특정 임명 된 "속성"으로 만 구성됩니다. 오브젝트 간의 포인터의 경우, 모두 이름으로 변환됩니다. 그래서 우리의 디자인, 개체가 저장 장치에 다음과 같이 나와 있습니다

Object foo { 
    value1: 0xff00ff00; 
    value2: 0x00ffeedd; 
    next_guy_in_chain: bar; 
} 

Object bar { 
    next_guy_in_chain: null; 
} 

연결리스트 시뮬레이션 구조에서 정말 존재 결코, 각 개체는 어떤 종류의 하드웨어 장치를 나타냅니다.

문제는 일부 사람들이이를 원하지만 동작을 코드화하는 방법으로 스레드가 있다는 것입니다. 여기서의 "행동"은 실제로 시뮬레이션 단위의 상태를 돌연변이시킨 것입니다. 기본적으로, 우리가 말한 디자인은 이러한 모든 변경 사항은 불려지는 작업을 수행하고 반환하는 원자 적 완성 작업에서 이루어져야한다고 말합니다. 모든 상태는 객체에 저장됩니다. 반응 모델이 있거나 "실행 완료"또는 "이벤트 구동"이라고 부를 수 있습니다.

이것에 대한 다른 생각은 객체에 활성 스레드가 작동하도록하는 것입니다.이 스레드는 고전적인 유닉스 스레드와 같은 방식으로 영원한 루프에 앉아 종료하지 않습니다. 이것은 디스크에 합리적으로 저장할 수 있는지를 확인하려는 경우이지만, VM을 중간에 끼우지 않고 실행 가능한 것처럼 보이지는 않습니다.

2009 년 10 월 업데이트 :이 문서는 2009 년 FDL 회의에서 게시되었으며 체크 포인트 및 SystemC에 대해서는 this paper을 참조하십시오.

답변

0

프로그램의 디스크 상태를 직렬화하려고 시도해서는 안됩니다. 프로그램 은 운영 체제가 허용하지 않는 한 해당 상태 인 ""을 완전히 제어 할 수 없기 때문에 운영 체제의 일부입니다.

은 가상 메모리 위치에 대한 포인터가 동일한 가상 메모리 위치를 다시 가리킬 수 있다고 보장 할 수 없습니다. (heap-begin/end, stack-begin과 같은 속성 제외) 가상 메모리에 대한 선택은 비 결정적입니다. sbrk 또는 malloc과 같은 상위 레벨 인터페이스를 통해 OS에서 요청한 페이지는 어디서나 시작됩니다.

  • 코드 깨끗하고 설계를 검사 :

    더 나은 어떤 상태 속성의 일부인가?

  • 저수준 언어를 사용하지 마십시오. 수행하려는 작업을 만드는 데 소요되는 오버 헤드가 결과에 가치가 없기 때문입니다.
  • C를 사용해야하는 경우 가능한 한 쉽게 생활을 유지할 수있는 방법을 고려해야합니다. offsetof 연산자부터 시작하여 오프셋 0에서 시작하는 첫 번째 멤버와 같은 속성 구조체를 고려해야합니다.

나는 당신이 링크 된 목록과 같은 특정 데이터 구조를,/직렬화 직렬화하는 데 소요되는 개발 시간을 단축 할 생각한다. 안심하십시오, 하려고하는 것은 사소한 것이 아니며 많은 작업이 필요합니다. 그렇게하기를 원한다면 운영 체제의 메모리 관리 코드와 OS의 페이징 메커니즘을 고려해야합니다. ;-)

EDIT 첨부 된 질문으로 인해 : 당신이 말한 디자인은 어떤 종류의 상태 기계처럼 들립니다. 객체 속성은 직렬화 가능하도록 설정되어 함수 포인터를 복원 할 수 있습니다.

먼저 객체의 스레드 상태와 관련된 : 경쟁 조건 등과 같은 일반적인 동시 프로그래밍 문제가있을 수있는 경우에만 문제가됩니다. 이러한 경우 뮤텍스, 세마포어와 같은 스레드 동기화 기능이 필요합니다. 그런 다음 언제든지 직렬화/비 직렬화 및 안전성에 대한 속성에 액세스 할 수 있습니다.

둘째, 객체 설정과 관련하여 : 바이너리 또는 다른 객체 표현이 있는지 확실하지는 않습니다. 바이너리 가정 : 메모리의 실제 구조를 나타낼 수 있다면 쉽게 직렬화 할 수 있습니다 (코딩 오버 헤드가 약간 듭니다). 개체의 시작 부분에 어떤 종류의 클래스 -ID 값을 삽입하고 실제 외장을 가리키는 참조 표가입니다. 첫 번째 sizeof (id) 바이트를 살펴보면 어떤 종류의 구조체인지 알 수 있습니다. 그러면 어떤 구조가 거기에 놓여 있는지 알 수 있습니다.

serialize/deserializing 할 때 다음과 같이 문제에 접근하십시오. 가상 구조적으로 채워진 (멤버 사이의 간격 없음) 구조의 길이를 검색하고 해당 크기를 할당하고 멤버를 차례로 읽고 쓸 수 있습니다. offsetof 또는 컴파일러에서 지원하는 경우 packed structs 만 사용하십시오.

대담한 핵심 질문으로 편집 : 아니요, 없습니다. C가 아닙니다

+0

글쎄, 여기 스레드는 SystemC라고하는 것, 즉 quickthreads 또는 Windows 섬유를 사용하는 기본적으로 협력적인 비 선점적인 스레딩입니다. 단일 OS 스레드. – jakobengblom2

0

C++에서 closure이 필요합니다.당신이 지적한대로 당신이 할 수 있도록 언어에 내장 된 메커니즘이 없습니다. 내가 아는 한 이것은 완전히 일반적인 방식으로하는 것은 기본적으로 불가능합니다. 일반적으로 VM이없는 언어로하는 것은 어렵습니다. 기본적으로 실행 환경/상태를 유지하는 클로저 객체를 만들 것을 제안한 것처럼 뭔가를함으로써 가짜로 만들 수 있습니다. 그런 다음 이것을 알려진 상태에있을 때 직렬화합니다.

또한 함수 포인터에 문제가 발생합니다. 기능은 각로드의 다른 메모리 주소에로드 될 수 있습니다.

1

가상 머신의 상태를 저장하고 똑같은 방법으로 복원 할 수 있다는 것은 정말로 원하는 것입니다.

이전 실행과 동일한 데이터로 실행중인 프로그램을 시작하려면 영구 데이터를 저장하고 복원해야합니다. 각 스레드의 정확한 상태는 실제로는 안됩니다 문제는 어쨌든 빠르게 변하기 때문이며 다음 번에는 사물의 실제 주소가 달라집니다. 데이터베이스를 사용하면 어쨌든이 기능을 제공합니다.

+0

전혀 아닙니다. 예를 들어, 다른 유형의 호스트와 같이 상태를 다른 구현으로 복원 할 수 있어야합니다. 스레드 상태는 버스 프로토콜과 같은 일부 상태 시스템을 코딩하는 데 사용되는 경우 중요합니다. – jakobengblom2

2

동기화 문제 (일부 문제는 여기 http://java.sun.com/j2se/1.3/docs/guide/misc/threadPrimitiveDeprecation.html에 설명되어 있음)가 발생하므로 프로그램의 "일부 스레드"만 직렬화한다고 생각하지 않습니다. 전체 프로그램을 일관되게 유지하는 유일한 방법은 일관성있는 상태를 유지하는 것입니다.

당신이 들여다 볼 수있는 것은 직교성 지속성입니다. 몇 가지 프로토 타입 구현이 있습니다

http://research.sun.com/forest/COM.Sun.Labs.Forest.doc.external_www.PJava.main.html

http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.17.7429

그러나 그들 중 누구도 더 이상 유지하지 나 (AFAIK) 매력을 많이 얻고있다. 결국 체크 포인트가 최선의 해결책이 아닌 것 같습니다. 내 프로젝트에서 http://www.siebengeisslein.org 경량 트랜잭션을 사용하여 스레드 상태를 유지할 필요가 없도록 이벤트를 전달하는 방법을 시도하고 있습니다 (트랜잭션이 끝날 때 스레드 호출 스택이 다시 비어 있고 작업이 중간 트랜잭션, 모든 것이 롤백되므로 스레드 호출 스택도 중요합니다). OODBMS와 비슷한 것을 구현할 수 있습니다.

일을 보는 또 다른 방법은 연속입니다 (http://en.wikipedia.org/wiki/Continuation, http://jauvm.blogspot.com/). 이들은 정의 된 코드 위치에서 실행을 일시 중단하는 방법입니다 (그러나 반드시 스레드 상태를 지속하지는 않습니다).

나는 이것이 당신에게 몇 가지 출발점을 제공하기를 희망한다. (그러나이 afaik에는 즉시 사용할 수있는 해결책이 없다.)

편집 : 설명을 읽은 후 : 반드시 OODBMS를 조사해야합니다. 자체 트랜잭션에서 각 이벤트를 보내고 스레드는 신경 쓰지 않습니다.

0

스레드 상태를 구현 세부 사항으로 간주하여 아마 직렬화 할 수 없습니다. 객체의 상태를 저장하려고합니다. 객체의 상태를 반드시 유지해야하는 것은 아닙니다.

이 접근 방식을 사용하려는 이유의 예로 히트가없는 업그레이드를 고려해보십시오. 응용 프로그램의 버전 N을 실행 중이고 버전 N + 1로 업그레이드하려면 객체 직렬화를 사용하여 수행 할 수 있습니다. 그러나 "버전 N + 1"스레드는 버전 N 스레드와 다를 수 있습니다.

1

프로그램 상태를 serialize하는 것보다 더 나은 방법은 데이터 검사 점을 사용하여 Crash Only Software을 구현하는 것입니다. 데이터 검사 점을 수행하는 방법은 구현 및 문제 도메인에 따라 다릅니다.

관련 문제