컴퓨터활용/티맥스

공통모듈의 필러 관리하기

멜번초이 2008. 10. 6. 10:15
개요

공통모듈을 개발하는 사람은 입출력 구조체에 필러를 미리 만들어 두는 것이 좋다. 특히 통합테스트 단계에서는 이관이라는 프로세스를 통하여 개발에서 단위테스트가 완료된 공통모듈을 별도의 실행환경인 테스트장비로 옮겨서 실행하기 때문에 절대적으로 필요하다.
모듈의 입출력 구조체 사이즈가 바뀌게 되면 이 모듈을 끌어다 쓰는 프로그램들도 모두 같이 이관되어 줘야 하는데 상황에 따라서는 이관할 수 없는 상황이 있을 수 있기 때문이다. 예를 들면 테이블스키마가 변경중이라 개발과 테스트의 테이블스키마가 다르거나  한참 로직을 변경하는 중이라 단위테스트가 완료되지 못 한 경우가 있을 수 있다.

데이타 타입별 사이즈

프로프레임에서 사용하는 구조체형 변수 타입인 PfmNumber 는 원래 24 byte 이고 long 은 8 byte이다. 그러나 필러는  char 형으로 선언해 놓을 수 밖에 없고 이 런 PfmNumber나 long 타입을 추가할 때 마다 필러의 사이즈를 줄여나가야 하는데 구조체 내부의  padding 문제 때문에 정확히 24 byte , 8 byte 씩 줄어들지 않는다는 것에 어려움이 있다.  패딩문제가 뭔가에 대하여서는 저의 이전 글을 참고.  패딩문제

 데이타 타입
 사이즈  용도  사용 예
 PfmNumber  24  실수  PfmNumber num;
 long  8  정수  long cnt;
 char  지정한 길이
 문자열  char name[20+1];

해결 방법

필러는 구조체의 끝에 만들고 추가될 때마다 sizeof 를 이용하여 사이즈를 계산하여 조심스럽게 맞춰야 한다.

1. 다음과 같이 구조체의 size를 찍는 코드를 넣은 후에 실행을 해 본다.

PFM_DBG("sizeof(mfeecal_comm_offr_in)  = [%ld]", sizeof(mfeecal_comm_offr_in));

2. 실행시켜 로그에 나온 구조체의 사이즈를 잘 기억해 놓는다. 본 예제의 구조체는 처음 정상적으로 동작 될 당시의 사이즈는 9104 byte 임을 확인할 수 있다.

[cbs]tail -f TX9812978_usr_20081006.log | grep sizeof
 sizeof(mfeecal_comm_offr_in)       = [9104]

3. 항목을 추가한다. 항목을 추가하기 전에 예비KEY의 필러 사이즈가 182 byte 였다.


4. 여기에 한도금액 number(18,3) 와 직원여부 char(1) 을 추가하고 저장한다. 저장할 때 구조체가 새로 생성된다.


5. 모듈을 새로 컴파일 한 후 실행을 시켜본다. 실행시킨 결과 size는 9136으로서 처음 9104에 비하여 32 byte 가 더 늘어 났다. 원리는 간단하다. 원래 보다 늘어난 길이 만큼  예비KEY에서 줄여주면 된다.

sizeof(mfeecal_comm_offr_in)       = [9136]

원래 사이즈 변화는  number 형 24 byte 와 char(1) 은 2 byte( null문자포함) 26 byte 만 늘어나는 이론적 계산이 나오지만 구조체 data type간 내부 padding 이 발생하여 실제로는 32 byte 의 gap이 발생되었다.

6. 예비KEY를 182 에서 150으로 사이즈 조정한 후 저장(구조체 생성) 한 후 다시 모듈을 재컴파일 dlupdate 한다.


7. 다시 모듈을 실행하면 원래 구조체 사이즈인 9104 가 찍혀 나오면서 모듈은 정상동작된다.  항상 예비KEY항목은 맨 마지막에 위치하도록 위치를 관리하는 것이 혼란을 줄일 수 있다.

이렇게 전체 구조체 사이즈의 변화없이 유지할 경우 이 모듈을 끌어다 쓰는 프로그램은 재컴파일을 하지 않아도 되는 것이다. 추가된 항목을 사용해야만 하는 프로그램만 로직 반영하고 재컴파일 하면 된다.


#pragma pack(1) 사용하기

이것저것 신경쓰기 귀찮으면 구조체를 선언할 때 pragma 옵션을 사용하여 1 byte 단위로 패딩없이 pack 시키도록 지정할 수 있다. 이렇게 할 경우 성능면에서 손해를 보게 된다. 또 OS나 컴파일러 마다 사용법이 서로 다르기 때문에 이식성 면에서도 손해를 보게 된다. 하지만 언제가 1 byte 씩 사용하므로 일정한 구조체 크기를 유지할 수 있기 때문에 속은 편하다. 일일이 sizeof 로 크기를 찍어보는 확인 작업을 반복하지 않아도 되기 때문이다.

#pragma pack(1)
struct test_s
{
  char a;
  int c;
} test;
#pragma pack(8)

구조체 선언할 때 1 byte 단위로 pack 시킨다고 지정해 주고 선언이 끝난 후에 적절히 4 byte나 8 byte 로 (원래대로) 확장(원복) 시켜 주는 방법이다.

<2008년10월5일>