Description

TEA2_BUILD 환경변수 에 문자열 '-x64'가 설정된 경우, 그리고 환경변수 DEBUG가 정의 되어있는지의 여부에 따라 KMA_EMA_LIBRARY 변수 값이 할당되는 Makefile script



괜찮은 녀석 발견.
앞으로 특별한 일이 없으면 특별히 신경쓸 것 없이 욘석을 바이너리 내부에 심고 사용해도 될듯 싶다.


  • URL :  http://www.postgresql.org/
  • license :  어떠한 제약없이 자유롭게 사용가능. BSD나 MIT와 유사한 라이센스. 상업적인 용도로도 사용할 수 있다.



 

1. Makefile 안에서 특정 명령어가 오류가 발생해도 다음 일을 계속 수행하게 하는 방법 : 명령어 앞에 -를 붙인다.

(ex) 특정 디렉토리를 생성해야 할경우, 처음 수행했을때에는 디렉토리 생성후 정상수행되지만 두번째부터는 오류가 발생하며 멈추게 된다. 그럴경우 아래와 같이 입력하면 오류가 발생해도 다음 명령어를 수행하게 된다. 다만 맨끝에 오류가 reporting 된다.

-mkdir target


2. 명령어가 수행되는 것을 화면에 출력하고 싶지 않다 : 명령어 앞에 @를 붙인다.

3. 다른 디렉토리에 있는 makefile 을 수행하고 싶다면 : make -C 옵션을 makefile 에 넣어라.

(ex) 현재 디렉토리에서 make를 입력했을때 자식 디렉토리인 sub-module/make 를 수행하고 싶다면 현재디렉토리에 있는 Makefile에서 그 명령어가 수행할 부분을 찾아 아래와 같이 넣는다.

...
      make -C ./sub-module/
...


4. PATSUBST 이용하여 특정 패턴을 치환하기

(ex) 현재 경로의 모든 cpp 파일을 o 로 바꾸어서 objects 에 넣는다.
OBJECTS = $(patsubst %.cpp, %.o, $(wildcard *.cpp))

5. Makefile 안에서 현재 경로명 얻기 : $(CURDIR)


구글보안처리에 관한 문서

한번쯤 읽어보고 아이디어를 얻기 좋은 내용인듯.



echo -n "STR"


  • Big Endian : 자릿수가 큰쪽 바이트가 먼저 저장. (ex) 3E1F 23A1 => 3E1F 23A1
    • 장점 : 사람이 이해하는 방식으로 표기하므로, 수치를 읽는데 자연스럽다.

  • Little Endian : 자릿수가 작은 쪽 바이트가 먼저 저장 (ex) 3E1F 23A1 => 1F3E A123
    • 장점 : 자릿수가 변하는 연산시 Big Endian 보다 빠르다. 자릿수 올림이 발생했을 경우( 예를 들면 F + 1 = 10 ), Big Endian의 경우는 자릿수가 밀려서 저장이 되어야 한다. 이는  performance issue 가 발생할 수 있으며 little Endian 을 채택한 경우 기존 자리는 그대로 있고 맨 뒤에 추가만 하면 되기 때문이다.

Byte Order Mark (BOM) : 현재 입력된 문자의 byte의 순서에 대한 정보가 담긴 Unicode Character. 파일의 맨 앞에 등장하며, 생략 가능하다.
 Encoding  Hexadecimal
 UTF-8  EF BB BF 
 UTF-16 Big Endian  FE FF
 UTF-16 Little Endian  FF FE 
 UTF-32 Big Endian  00 00 FE FF 
 UTF-32 Little Endian  FF FE 00 00 
 GB-18030 84 31 95 33 


  1. Favicon of http://searchall.tistory.com BlogIcon BAGE 2010.03.24 15:50 신고

    나중에 쉽게 찾아서 보려고 글을 퍼갑니다. 문제 된다면 퍼간 글에 댓글 남겨주세요.
    좋은 글 감사합니다.

    • Favicon of http://finsternis.tistory.com BlogIcon leanu 2010.03.24 18:14 신고

      저도 참고하면서 정리한거라 괜찮습니다.

      방문 감사합니다.

클라이언트가 연결을 종료했을때, 서버가 전에 사용했던 소켓으로 데이터를 전송하려고하면 SIGPIPE 가 발생한다. 기본적으로 서버는 "프로그램을 종료" 하므로 이를 막기 위해선 핸들링 함수를 연결하거나 신호를 무시해야 한다.

  • SIGPIPE 무시하기


  • SIGPIPE HANDLER 이용하기 : 핸들러는 void형에 int형 인자 한개를 받아야 한다.




멀티 플랫폼개발이나 , 컴파일러, 중요 라이브러리들을 점검하고자 할때
위와 같은 미리 정의된 매크로들을 사용한다.

아래의 링크에 잘 정리되어 있다. 

아래는 GNU C / C++ 의 버전을 체크하는 부분.

GNU C/C++

TypeMacroDescription
Identification __GNUC__ .
Version __GNUC__ Version
Version __GNUC_MINOR__ Revision
Version __GNUC_PATCHLEVEL__ Patch (introduced in version 3.0)

Please note that the meaning of the __GNUC__ macro has changed subtly over the years, from identifying the GNU C/C++ compiler to identifying any compiler that implements the GNU compiler extensions (see the Feature request - a macro defined for GCC discussion for further information). For example, the Intel C++ on Linux also defines these macros from version 8.1 (see the Intel C++ Compiler 8.1 for Linux Release Notes and Intel Compilers for Linux: Compatibility with GNU Compilers.)

Example

GNU C/C++__GNUC____GNUC_MINOR____GNUC_PATCHLEVEL__
2.7.x 2 7 .
3.0.2 3 0 2

Alternative Version

If you prefer a single version macro, you can define the following yourself.

#if defined(__GNUC__)
# if defined(__GNUC_PATCHLEVEL__)
#  define __GNUC_VERSION__ (__GNUC__ * 10000 \
                            + __GNUC_MINOR__ * 100 \
                            + __GNUC_PATCHLEVEL__)
# else
#  define __GNUC_VERSION__ (__GNUC__ * 10000 \
                            + __GNUC_MINOR__ * 100)
# endif
#endif

The format of this new macro is:

TypeMacroFormatDescription
Version __GNUC_VERSION__ VVRRPP VV = Version
RR = Revision
PP = Patch

Example of Alternative Version

GNU C/C++__GNUC_VERSION__
2.7.x 20700
3.0.2 30002



Visual C++ Version ( _MSC_VER )

 Visual C++ Version _MSC_VER value 
 9.0 1500 
 8.0 1400 
 7.1 1310 
 7.0 1300 
 6.0 1200 
 5.0 1100 


  1. Favicon of http://4four.us BlogIcon 승은 2009.10.13 22:46 신고

    도현씨 오랜만이에요 ㅎㅎ 웹서핑하다가 발견하고 반가운 마음에 댓글 남겨요. 잘 지내죠?

    • Favicon of http://finsternis.tistory.com BlogIcon leanu 2009.10.21 09:27 신고

      와우 승은씨
      요새 바쁘다보니 댓글단지도 모르고 있었네요 ㅋㅋ
      승은씨도 잘지내죠? 우리 언제봐요? ㅋㅋ
      다음해엔 얼굴 함 꼭 봐요~!

    • Favicon of http://sourkent.tistory.com BlogIcon 신키위 2009.10.21 09:41 신고

      호오... g++ 관련 프로젝트를 하고 있는걸로 예상됩니다. ㅋㅋㅋ

  2. Favicon of http://www.4four.us BlogIcon 승은 2009.10.21 10:18 신고

    가족이서 제주도 한 번 놀러와요. 딴 건 모르겠고(...) 맛집 정도는 몇 개 추천해줄게요. 근데 신키위님은 누구시죠? 짐작가는 이는 있으나 확실치가 않아서 말입니다.

    • Favicon of http://sourkent.tistory.com BlogIcon 신키위 2009.10.21 16:18 신고

      명현이요. ㅋㅋㅋㅋㅋㅋㅋㅋㅋ
      안그래도 저번주에 어머니가 이모들하고 제주도 갔었는데 생각도 못했네요. ㅋㅋㅋㅋㅋ

      도현씨 블로그는 만남의 광장~

요거 유용하네

$ find ./ -type f -exec sed -i ’s/findString/replaceString/g’ {} \;

참고로 {} 는 현재 선택한 파일이다. 그리고 exec 끝에 항상 \; 를 잊지 말것.

2개 이상의 명령어를 수행하고자 할때는 뒤에 -exec 를 덧붙이면 된다.

$ find ./ -type f -exec echo '-----[ ' {}\; -exec spec {} \;


3가지 방법이 있으니 취향대로 선택하세요

      $ getconf GNU_LIBC_VERSION

      $ rpm -q glibc

      $ ls /lib/libc* 후에 육안으로 확인

  1. Favicon of http://blog.ggamsso.wo.tc BlogIcon 깜쏘 2009.09.29 13:13 신고

    getconf란 명령어가 있었군요.
    잘 써먹겟습니다.


Unicode(UCS2)로 구성된 한글은 초성 중성 종성으로 분리가 된다.

종성 = characterValue % 28
중성 = ( (characterValue - 종성 ) / 28 ) % 21
초성 = ( ( (characterValue - 종성 ) / 28 ) - 중성 ) / 21

이 값들은 인덱스 값이지 실제 Unicode 테이블표에 매치되지 않는다.
매치 시키려면 각각 초성 중성 종성의 시작 unicode 값들을 더해주면 된다.
( 초성 : 0x1100   , 중성 : 0x1161   , 종성 : 0x11A7 )

또한 초성 중성 종성의 값들로 원래의 글자값을 만들려면 다음의 공식을 이용하면 된다.
물론 각각의 값들은 인덱스 값이어야 한다. (실제 테이블 매치 값이면 각각의 값들을 빼준다.)

characterValue = ( (초성 * 21) + 중성) * 28 + 종성 + 0xAC00

한국어 자모와 글자에 대한 Unicode table 표를 참조하고 싶다면 아래의 링크로 들어간다.

자모 : http://www.unicode.org/charts/PDF/U1100.pdf
음절 : http://www.unicode.org/charts/PDF/UAC00.pdf


  1. Favicon of http://blog.ggamsso.wo.tc/ BlogIcon 깜쏘 2009.08.04 20:26 신고

    유니코드에 저런 면이 있어서 조합형 처럼 쓰기 편하죠.
    하지만 저런 면이 있어서 한글이 유니코드 영역의 1/4정도 차지하고 있죠.
    http://ko.wikipedia.org/wiki/%EC%9C%A0%EB%8B%88%EC%BD%94%EB%93%9C_%EB%B2%94%EC%9C%84_%EB%AA%A9%EB%A1%9D
    에서 아래 쪽에 그림으로 그려진 테이플을 보시면 AC00부터 D7AF까지 꽤 넓은 영역을 차지하고 있다는 것을 알 수 있죠.

    • Favicon of http://finsternis.tistory.com BlogIcon leanu 2009.08.05 09:36 신고

      ㅋㅋ 진짜 좀 많이 차지하네요. 그만큼 한글 구조의 과학성이 다른문자들과는 다르다는 것을 보여주는 한 예가 아닌가 싶어요. :)

  2. BlogIcon 코비 2012.10.09 15:10 신고

    초성 = ( (characterValue - 종성 ) / 28 ) / 21 이부분이 잘못된거 같아요.

    ==> 초성 = ( ( (characterValue - 종성 ) / 28 ) - 중성) / 21 : 이렇게해야 값이 잘 나오는거 같네요.

    맞나요?

    • Favicon of http://finsternis.tistory.com BlogIcon leanu 2012.10.10 17:41 신고

      네 맞습니다.

      중성 구하는 공식에는 종성을 빼고하면서
      초성 구할때는 중성의 값을 빼질 않았네요.

      정수형으로 딱 떨어지게 해야 하는데 빼먹었어요 >.<

      왠지 닉이 익숙한데요? ㅎ



처음에는 cd 로 경로를 이동하려고 입력하다가 자칫 파일을 고쳐볼 생각에 파일명까지 기입하는 실수를 간혹 저지른다.
이럴때 요 기호( !$ )를 쓰면 괜찮을듯 하다.

   $ cd test/stream/input/c++/stream.cpp
   -bash: cd: test/stream/input/c++/stream.cpp: 디렉토리가 아닙니다.
   $ vi !$

언제나 많은 도움을 받고 있는 kldp site ( http://www.kldp.org )

vi / vim 단축키와 관련해서 정말로 좋은 자료가 있길래 감사의 인사글을 남기고 이곳으로 가져왔다.

내가 모르는 기능은 없는지 한번 살펴보아야 겠다.

출처 : Mr.Dust 님의 글 , ( http://kldp.org/node/102947 )




SVG file
Introduction
---------------------------------------------------------------------------------------------
  Unix 나 프로그램을 종료하게 되는 경우 Ctrl-C 를 이용하게 된다. 만약 프로그램에서 파일에 무언가를 쓰고 있는 중간에 갑작스런 종료를 하게 된다면, 파일에 손상이 생겨서 다음번에 사용할 수 없을수도 있다. 그렇다면 그런 신호에 대한 뒷처리(예를 들면, 파일을 종료하거나...)를 하고 싶을때는 어떻게 해야 할까? 바로 Signal 처리에 답이 있다.

  p.s "kill -9" 같이 강제 종료하는 것에 대한 signal처리는 운영체제 상으로 금지되어 있다.( 즉 신호감지를 못한다.) 왜냐하면 이것마저도 제어권을 프로그램에게 넘겨버린다면, 한번 실행되면 종료할 수 없는 프로그램을  만들수도 있기 때문이다. 우리가 처리하고자 하는 신호는 SIGTERM (기본 소프트웨어 종료 신호) SIGINT (Ctrl+C 시 발생하는 신호) 이렇게 두가지 이다. 따라서 이번에 다루는 내용은 완전한 transaction 처리라고는 할 수 없다.


Source & How to use it
---------------------------------------------------------------------------------------------

   우선 소스를 보자

/// @file TerminationMananager.h
/// @author Dohyun Yun
/// @brief A Class to manage termination control.

#include <iostream>
#include <signal.h>

class TerminationManager
{
public:

    static int catchTerminationSignal(void handler(int))
    {
        struct sigaction act;
        act.sa_handler = handler;
        sigemptyset(&act.sa_mask);
        act.sa_flags = 0;

        if (sigaction(SIGINT, &act, 0) < 0)
        {
            std::cerr << "error: Cannot register SIGTERM" << std::endl;
            return -1;
        }

        if (sigaction(SIGTERM, &act, 0) < 0)
        {
            std::cerr << "error: Cannot set SIGTERM" << std::endl;
            return -1;
        }

        return 0;
    }

};

#include <TerminationManager.h>

static void handler(int signo)
{
    std::cerr << "Warning : Signal occurs (" << signo << ")" << std::endl;
}

int main()
{
    TerminationManager::ccatchTerminationSignal(handler);
    while(1){};
    return 0;
}

사용법은 간단하다. 맨 아래 main 함수를 보면 함수의 copy본을 TerminationManager에 등록하게 되는데, sigaction 에서 정의한 SIGINT 와 SIGTERM을 부른 경우 handler함수를 호출하게 되는 형식으로 진행된다. 이때 유의할 점은 클래스들의 소멸자는 당근 안불려진다는 사실이다. (당연하다. 갑자기 종료인데..)

http://www.joinc.co.kr/modules/moniwiki/wiki.php/RTS

asio C++ Library 란 cross-platform기반의 네트워크 프로그래밍 라이브러리이다.

Modern C++ 기반의 디자인을 사용하여 asynchronous I/O 를 안정적으로 지원해준다고 하니

사용법을 익힌다면 소켓제어와 관련된 부분에 골머리를 썩지 않아도 될듯 싶다.

버전은 boost 기반과 non-boost 기반으로 받을 수 있다.

이 역시 boost와 마찬가지로 표준 라이브러리는 아니므로

잘 고려하여 이용해보라.

<asio c++ library 공식 사이트>

http://asio.sourceforge.net/

<Unix 계열>

https://computing.llnl.gov/tutorials/pthreads/

http://www.joinc.co.kr/modules/moniwiki/wiki.php/article/Pthread_API_Reference

<Windows 계열>

http://msdn.microsoft.com/ko-kr/library/172d2hhw(VS.80).aspx

sort 는 대부분 단독으로 쓰이지 않고 파이프를 이용해서 입력 값을 조물락조물락 거린다.

일반 : sort <파일명>

중복된 열을 제거하고 출력 : sort <파일명> -u       또는     <파일명> | sort -u

중복된 데이터만 추출 : sort <파일명> | uniq -d

중복되지 않은 데이터만 출력 : sort <파일명> | uniq -u

<개념 한가지>
Blocking : 어떤 대상이 이용가능할때까지 대기하는 상태

NoneBlocking : 어떤 대상이 이용가능하지 않으면 리턴값을 발생시키고 다음으로 넘어가는 상태



fork() 를 통해 받는 pid 는

명령어에서 ps 를 쳐서 확인할 수 있는 프로세스 id 가 아니라

구분하기위해 임의로 발급한 아이디다.

발급받은 값이 0 이면 자식 프로세스이고, 0 이 아니면 부모 프로세스이다.

수행중인 녀석의 실제 프로세스 id 를 확인하려면 getpid() 를 사용하면 된다.



pipe() 함수를 이용하면 프로세스간 값을 주고 받을수 있으며

일반적으로 자식 프로세스가 자신의 프로세스 아이디를 getpid()를 통해 얻은후

pipe 통신으로 부모에게 전달한다.

여기서 구현한 파이프는 일방통행이므로 한개만 생성해도 문제가 없지만,

일반적으로 2개의 프로세스가 통신할 때에는 2개의 파이프를 설정하여 통신한다.

왜냐하면 파이프는 (First In First Out) 으로 집어넣고 가저가므로

멀티프로세스나 멀티쓰레드 프로그램을 하는경우

누가 가져가는지 보장을 할 수 없기 때문이다.

만약 데이터가 없는데 파이프를 통해 read를 수행한 경우

값이 들어올때까지 block 이 되기 때문에

파이프의 0번째 녀석을 nonblocking mode로 set 해주어야 한다.

이때 사용하는 녀석이 fcntl() 함수이다.

파이프에 대한 개념을 잘 설명한 문서들을 첨부한다.



kill()은 프로세스에 메시지를 전달해 주는 함수로

해당 프로세스 아이디와 보낼 메시지를 넣으면 그 프로세스가 해당 동작을 수행한다.

  1. Favicon of http://blog.daum.net/impnees?t__nil_loginbox=blog1 BlogIcon 임프 2008.05.02 11:12 신고

    퍼갈께요~

  2. Favicon of http://blog.naver.com/wodnis BlogIcon wodnis 2011.07.04 06:18 신고

    퍼갈게요~ 문제가 있다면 지우겠습니다^^
    http://blog.naver.com/wodnis

    • Favicon of http://finsternis.tistory.com BlogIcon leanu 2011.09.06 09:22 신고

      ㅎㅎ 괜찮습니다.
      왠지 과제가 나온거 같네요 ㅎ
      즐플 하십시오~!

vi, vim
  1. Favicon of http://finsternis.tistory.com BlogIcon leanu 2008.03.25 17:32 신고

    파일이름은 반드시 .vimrc 로 해야 한다.

    root directory 에 복사하면 된다.

<port 1234 를 udp로 open>
sudo iptables -A INPUT -p udp --dport 1234 -j ACCEPT

<port 1234 를 close>
sudo iptables -A INPUT -p udp --dport 1234 -j DROP


ps.1 unix 나 다른버전의 linux 인경우 root 계정으로 로그인한 후 sudo 를 뺀 나머지를 입력하면된다.

ps.2 tcp로 열고 싶은경우 udp -> tcp 로 바꾸어 주면 된다.

popen : 명령어 수행 (파이프 생성)

<원형>

     FILE *popen(const char *comstring, const char *type);

     int pclose(FILE *strm);


<인자>

     comstring : 수행할 명령어

     type : 부모와의 통신형태

     strm : 폐쇄할 파일 스트림

<리턴값>

     성공 : 열린 파일 스트림 포인터

     실패 : NULL

<함수 설명>

     popen() 도 system() 함수처럼 지정한 명령어를 수행한다. 그러나 호출 프로세스와 명령어 사이에 통신을 할 수 있는 파이프를 생성한다는 점이 system() 함수와 다르다. popen()을 호출하면 지정한 명령어를 수행하기 위해 fork()와 execl()을 수행한 후 파일 스트림을 반환하고 사용자는 그 반환된 파일 스트림을 이용해 표준 출력이나 표준 입력을 처리할 수 있다.그리고 어느 것을 지정할 지는 type 로 정한다.

     fp = popen("ls -l *","r");

     popen() 은 "ls -l *"명령어를 수행한다. system()함수는 이것을 화면에 뿌리지만 "r"을 이용하면 표준 출력되는 문자열을 다음과 같이 fp포인터를 이용해 읽을 수 있다.

          fgets(buff, buffsize, fp);

     또한 이와 반대로 표준 출력에 쓸 수도 있는데 이때 주의할 것은 popen()은 항상 pclose()로 닫아야 한다.

  1. BlogIcon jiyoun 2017.05.08 07:27 신고

    안녕하세요.
    popen에 대해서 study중인데 궁금한게 있어서요.
    popen호출 시 내부동작은 fork()와 execl()가 호출되어 동작하는데, execl() 실행에서 /bin/sh 즉, 쉘을 실행하여 와일드카드 확장을 이용할 수 있다고 들었습니다.
    이때 쉘을 이용하면 쉘에 대한 process는 fork된 process와 다른 process가 되는건가요?

    • Favicon of http://finsternis.tistory.com BlogIcon leanu 2017.05.11 10:16 신고

      어떤 내용의 질문인지 파악이 잘 안되네요 ㅜ.ㅜ

      혹시 어떤 작업을 하시길 원하시기에 popen에 대한 문의를 하셨는지 배경 설명을 해주시면 답변을 드릴 수 있을것 같습니다 :)

이전 글에서 설명한 메모리 테스트 방법은 기본적으로 메모리의 내용을 파괴하면서 진행하는 방법이기에 롬이나 하이브리드(플래시, EEPROM) 메모리에는 적용할 수 없다. 그러나 롬이나 하이브리드 메모리에서도 여전히 메모리가 장착되지 않았거나 잘못 장착되는 경우가 있을 수 있고 물리적 전기적인 충격으로 손상되거나 배선 문제 등으로 인해 정상 동작하지 않는 경우가 생길 수 있다. 그러므로 이런 류의 비휘발성 메모리의 경우에도 문제가 없으리라고 가정해서는 안된다.

그런데 이런 비휘발성 메모리의 경우는 그 용도가 의미있은 초기 데이터(그것이 프로그램이던 순수 데이터이던)를 저장하는 것이기에 단순히 메모리 칩의 물리적인 동작 여부를 검사하는 것보다 저장되어 있는 데이터의 내용이 손상되지 않았다는 것을 증명하는 것이 더 바람직하다. 이런 데이터 내용 검증을 위해 사용할 수 있는 방법이 체크썸이나 CRC이다.


체크썸

체크썸은 단순히 데이터 블럭을 내용을 바이트 또는 워드 단위로 캐리를 버리면서 전부 더한 값이다. 이 체크썸을 데이터 블럭과 함께 저장해 놓으면 나중에 데이타 블럭의 오류 여부를 어느 정도 감지할 수 있다. 그러나 데이터 블럭의 내용이 어떤 요인에 의해 전부 0으로 초기화되는 경우, 체크썸도 함께 0으로 바뀌기 때문에 오류를 감지하지 못한다. 이런 문제 때문에 TCP/IP 패킷 헤더 등에서 사용되는 체크썸은 최종 단계에 체크썸의 보수를 취해서 저장한다. 체크썸은 간단한 반면 오류 감지 능력이 대단히 빈약하다. 즉, 동일한 비트 위치에서 발생되는 홀수 개의 비트 오류는 감지하지만 짝수 개의 비트 오류에 대해서는 전혀 감지하지 못한다.


CRC(Cyclic Redundancy Check)

CRC는 생성 다항식(generator polynominal)이라 불리는 고정 크기의 키 값(제수, divider)으로 데이터 블럭의 값을 차례대로 나누어서 그 나머지를 누적시키는 일종의 해시 함수이다. 이때 생성 다항식을 어떤 값으로 선택하느냐에 따라 데이터 블럭 내의 오류 패턴을 검출하는 능력에 영향을 미치게 된다. 보통 한 두개의 비트 오류는 물론 연속적으로 비트 오류가 발생되는 버스트 에러까지도 99.99% 이상 감지한다.

국제 표준으로 아래 3가지의 생성 다항식이 채택되어 있다. 각각의 표준에는 체크썸의 비트 수, 생성 다항식, 생성 다항식을 이진수로 표현한 제수, 나머지의 초기값, 최종 나머지에 적용할 XOR 값이 명시되어 있다. CRC32는 이더넷에서 MAC 프레임의 오류 검출에 사용되는 방식이다.


1) CCITT

체크썸 크기  : 16 비트

생성 다항식  : X^16 + X^12 + X^5 + 1

제 수        : 0x1021

나머지 초기값: 0xFFFF

최종 XOR값   : 0x0000


2) CRC16

체크썸 크기  : 16 비트

생성 다항식  : X^16 + X^15 + X^2 + 1

제 수        : 0x8005

나머지 초기값: 0x0000

최종 XOR값   : 0x0000


3) CRC32

체크썸 크기  : 32 비트

생성 다항식  : X^32 + X^26 + X^23 + X^22 + X^16 + X^12 + X^11 +

               X^10 + X^8 + X^7 + X^5 + X^4 + X^2 + X^1 + 1

제 수        : 0x04C11DB7

나머지 초기값: 0xFFFFFFFF

최종 XOR값   : 0xFFFFFFFF


아래의 C 코드는 CCITT 방식의 CRC를 계산할 수 있는 코드이다. CRC16이나 CRC32를 계산하려면 원하는 방식에 맞게 CRC 파라미터에 대한 3개의 상수 정의(POLYNOMIAL, INITIAL_REMAINDER, FINAL_XOR_VALUE)와 체크썸 크기에 대한 타입 정의(width)를 수정하면 된다.

CRC16 표준으로 바꾸려면 3개의 상수를 각각 0x8005, 0x0000, 0x0000으로 바꾸면 된다.

CRC32 표준으로 바꾸려면 3개의 상수를 각각 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF으로 바꾸고 체크썸 크기(width)에 대한 타입 정의를 unsigned long으로 바꾸면 된다.


/*
 * The CRC parameters.  Currently configured for CCITT.
 * Simply modify these to switch to another CRC standard.
 */
#define POLYNOMIAL          0x1021
#define INITIAL_REMAINDER   0xFFFF
#define FINAL_XOR_VALUE     0x0000
 
/*
 * The width of the CRC calculation and result.
 * Modify the typedef for an 8 or 32-bit CRC standard.
 */
typedef unsigned short width;
 
#define WIDTH   (8 * sizeof(width))
#define TOPBIT  (1 << (WIDTH - 1))
 
/*
 * An array containing the pre-computed intermediate result for each
 * possible byte of input.  This is used to speed up the computation.
 */
width  crcTable[256];
 
/*****************************************************************
 * Function:    crcInit()
 *
 * Description: Initialize the CRC lookup table.  This table is used
 *              by crcCompute() to make CRC computation faster.
 * Notes:       The mod-2 binary long division is implemented here.
 * Returns:     None defined.
 *****************************************************************/
void crcInit(void)
{
    width  remainder;             
    width  dividend;             
    int    bit;                 
 
    /* Perform binary long division, a bit at a time. */
    for (dividend = 0; dividend < 256; dividend++)
    {
        /* Initialize the remainder. */
        remainder = dividend << (WIDTH - 8);
 
        /* Shift and XOR with the polynomial. */
        for (bit = 0; bit < 8; bit++)
        {
            /* Try to divide the current data bit. */
            if (remainder & TOPBIT)
                remainder = (remainder << 1) ^ POLYNOMIAL;
            else
                remainder = remainder << 1;
        }
 
        /* Save the result in the table. */
        crcTable[dividend] = remainder;
    }
}
 
/*****************************************************************
 * Function:    crcCompute()
 *
 * Description: Compute the CRC checksum of a binary message block.
 * Notes:       This function expects that crcInit() has been called
 *              first to initialize the CRC lookup table.
 * Returns:     The CRC of the data.
 *****************************************************************/
width crcCompute(unsigned char *message, unsigned int nBytes)
{
    unsigned int   offset;
    unsigned char  byte;
    width          remainder = INITIAL_REMAINDER;
 
    /* Divide the message by the polynomial, a byte at time. */
    for (offset = 0; offset < nBytes; offset++)
    {
        byte = (remainder >> (WIDTH - 8)) ^ message[offset];
        remainder = crcTable[byte] ^ (remainder << 8);
    }
 
    /* The final remainder is the CRC result. */
    return (remainder ^ FINAL_XOR_VALUE);
}

crcInit() 함수는 CRC 계산을 비트 단위가 아닌 바이트 단위로 하기 위해 한 바이트가 가질 수 있는 나머지 값을 미리 구하는 함수이다. 이 중간 결과는 전역 변수(crcTable)에 저장되어 crcCompute() 함수에서 사용된다. crcCompute()를 호출하여 CRC 계산을 하기 위해선 crcInit()이 먼저 실행되어 crcTable이 만들어져 있어야 한다. crcInit()은 프로그램이 실행될 때 최초로 한 번만 실행되면 된다. 또는 미리 실행하여 구한 crcTable 값을 롬에 저장하여 사용할 수도 있다.


참고)

[Programming Embedded Systems in C and C++], 1999, O\'Reilly, Michael Barr

(2000년, 한빛미디어, 이석주 역)


김인대

+ Recent posts