336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

이제 할일은 문제의 ./util 과 ./examples 이다!!
일단 ./util/grapicsTest디렉토리로 이동해 make를 해보자

[root@localhost graphicsTest]# make
arm-linux-gcc -c -O -I/usr/src/kernels/2.6.25.6-27.fc8-i686/include/ -I../../include graphicsTest.c
graphicsTest.c:7:21: GL/gl.h: 그런 파일이나 디렉토리가 없음
graphicsTest.c:8:23: GL/glut.h: 그런 파일이나 디렉토리가 없음
graphicsTest.c: In function `draw':
graphicsTest.c:101: error: `GLfloat' undeclared (first use in this function)
graphicsTest.c:101: error: (Each undeclared identifier is reported only once
graphicsTest.c:101: error: for each function it appears in.)

                        ....생략....

graphicsTest.c:130: warning: data definition has no type or storage class
graphicsTest.c:132: warning: parameter names (without types) in function declaration
graphicsTest.c:132: warning: data definition has no type or storage class
graphicsTest.c:133: error: parse error before '}' token
make: *** [graphicsTest.o] 오류 1
[root@localhost graphicsTest]#
아마도 요런 에러가 날것임(오류가 완전 틀리다면 make clean후 make)
뭐 경우에따라 완전 똑같은 오류가 나지는 않을것이다

이경우 처음부터 살펴보면
         ▷ graphicsTest.c:7:21: GL/gl.h: 그런 파일이나 디렉토리가 없음
             graphicsTest.c:8:23: GL/glut.h: 그런 파일이나 디렉토리가 없음
요런 에러가 보이는데 간단하다!! 경로를 못찾아서 그런것이라 Makefile에서
경로를 맞춰주던지 귀찮음 디렉토리 내에 헤더파일들을 때려박고
#include "gl.h" 요런식으로 주면 된다.
한가지 주의할 점은 헤더파일을 디렉토리내에 복사할경우 의존적인 헤더들까지 같이 복사해 주어야 한다는 사실이다!!

------------------  미완된 글입니다 ------------------
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

아래 사이트에서 Linux용 ARToolKit을 다운 받는다http://www.hitl.washington.edu/artoolkit/documentation/usersetup.htm
※참고로 호스트에서 컴파일할경우 위 링크의 설명대로 컴파일 하면 간단히 된다

다운받은후 압축을 푼다

파일중 Configure파일이 있는데 바로 실행하지 말고 에디터를 이용하여
파일을 열어보면 다음과 같다.


   ...

    echo "Select a video capture driver."
    echo "  1: Video4Linux"
    echo "  2: Video4Linux+JPEG Decompression (EyeToy)"
    echo "  3: Digital Video Camcoder through IEEE 1394 (DV Format)"
    echo "  4: Digital Video Camera through IEEE 1394 (VGA NONCOMPRESSED Image Format)"
    echo "  5: GStreamer Media Framework"
    echo -n "Enter : "
    read ANS
    if [ "$ANS" = "1" ]
    then
                echo
                echo "Color conversion should use x86 assembly (choose 'n' for 64bit systems)?"
                echo -n "Enter : "
                read ANS
                if [ "$ANS" = "y" ]
                then
                        CCVT_OBJ="ccvt_i386.o"
                elif [ "$ANS" = "n" ]
                then
                        CCVT_OBJ="ccvt_c.o"
                else
                        echo "Please enter y or n."
                        exit 0
                fi
        VIDEO_DRIVER="VideoLinuxV4L"
        #CFLAG="-O -I/usr/X11R6/include"
        CFLAG="-O -I/root/work/kernel/rebis2.6/include/"
        LDFLAG="-L/usr/X11R6/lib"
        ARFLAG="rs"
        RANLIB=""

        LIBS="-lglut -lGLU -lGL -lXi -lXmu -lX11 -lm"
        CONFIG="AR_INPUT_V4L"
   ...
1: Video4Linux"
2: Video4Linux+JPEG Decompression (EyeToy)"
3: Digital Video Camcoder through IEEE 1394 (DV Format)"
4: Digital Video Camera through IEEE 1394 (VGA NONCOMPRESSED Image Format)
이렇게 네개의 메뉴가 있고 선택에 따라 생성되는 Makefile 이 달라진다
때문에 자시가 사용할 모드(아마도 주로 1번을 사용하게 될 것이다)의 부분을 찾아
위의 예(빨간부분) 처럼 수정을 해야 한다

물론 CFLAG외에도 LIBS관련된 옵션들도 수정을 해야하는데 후에 이야기를 하겠다

자!! 일단 ./Configure를 실행해보자!!
그럼 각각 폴더에 Makefile이 생길 것이다
일단 해야 할일은 Makefile을 추적하여 컴파일 해야할부분을
arm-linux-gcc로 바꿔줘야 한다.

   ./lib 경로 의 Makefile들은 CC=arm-linux-gcc로 바꿔주기만하면 쉽게 컴파일 될것이고
   ./util 과 examples 경로는 cc를 $(cc) 로바꾸고 cc=arm-linux-gcc를 추가해주면 끝!

이제 make를 실행해보자!!
제일 상위의 Makefile 경로대로 일단 ./lib 경로의 폴더들 부터 하나하나 make 를 해보자
정확한 기억은 아니지만 ./lib폴더는 문제없이 쉽게 크로스 컴파일이 될것이다.

삽질의 시작은 여기부터 이다!! 이제 ./util디렉토리와 ./examples폼더를 컴파일 해야한다!!

....그런데

좀 길어 질것 같은 관계로 일단 여기서 1부끝!!!
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
장치(Device)
Video4Linux는 다음의 장치(Device) 파일들을 제공한다. 이것들은 보통 /dev/bttv로서 알려져 있는 캐릭터형의 장치(Device)이며,
많은 사람들을 위해서 /dev/bttv는 /dev/video0 에의 기호 연결(Symlink)이 되어 있다.


장치(Device) 파일명 마이너 번호의 범위 기능
/dev/video 0-63 비디오 capture를 위한 인터페이스(Interface)
/dev/radio 64-127 AM/FM 라디오 장비
/dev/vtx 192-223 Teletext 인터페이스(Interface) 칩(Chips)
/dev/vbi 224-239 Raw VBI 데이터(Intercast/Teletext)

Video4Linux를 이용하는 프로그램은, 우선 장치(Device) (파일)을 열고 검색해서, 이용하길 원하는 기능을 찾아낸다. 기능의 검색으로 각 인터페이스(Interface)가 무엇을 지원하고 있는지를 알 수 있다. 이 API는 비디오 캡쳐 카드를 위해서만 정의되었다. 라디오 카드(Radio Card)의 경우에는 이 부분집합을 이용한다. Teletext의 인터페이스(Interface)에는 이미 정의되고 있는 VTX API를 이용한다.

기능의 검색의 Ioctl(Capability Query Ioctl)
비디오 장치(Device)가 지원하는 기능에 관한 정보를 얻으려면 VIDIOCGCAP ioctl()을 이용한다. ioctl에 struct video_capability를 건네주면 내용을 돌려준다. struct video_capability에는 이하에 주는 항목이 포함되어 있다.

name[32] 이 장치(Device)의 규범적인(Canonical) 이름
type 인터페이스(Interface)의 타입
channels radio/tv 의 입력 소스의 수(만약 사용 가능하면)
audios 오디오 장치(Device)의 수(만약 사용 가능하면)
maxwidth 최대의 capture폭(단위:픽셀)
maxheight 최대의 capture 높이(단위:픽셀)
minwidth 최소의 capture폭(단위:픽셀)
minheight 최소의 capture 높이(단위:픽셀)

type의 항목은 장치(Device)의 기능에 관한 정보가 플래그(Flag)로서 리스트(List)되어 있다. 이것에는 다음의 것이 있다.

이름 설명
VID_TYPE_CAPTURE 메모리상에 capture 하는 기능이 있다
VID_TYPE_TUNER 어떤 형식(Some Form)의 Tuner가 있다
VID_TYPE_TELETEXT teletext의 기능을 가지고 있다.
VID_TYPE_OVERLAY frame buffer상에 이미지를 오버레이 하는 기능이 있다
VID_TYPE_CHROMAKEY chroma-key로 오버레이 하는 기능이 있다
VID_TYPE_CLIPPING 오버레이의 클리핑을 하는 기능이 있다
VID_TYPE_FRAMERAM 오버레이는 frame buffer의 메모리를 덧쓰기하는 기능이 있다
VID_TYPE_SCALES 하드웨어가 이미지의 크기변환(Image Sacling)을 지원한다.
VID_TYPE_MONOCHROME 그레이 스케일(Grey Scale)만 Captuer한다.
VID_TYPE_SUBCAPTURE 이미지의 일부분만을 capture 할 수 있다

capture 장치(Device)가 돌려주는 최소와 최대의 사이즈는, 그 범위내에서 가능한 모든 높이와 폭의 비율이나 사이즈를 사용할 수 있는 것은 아니다. capture 사이즈를 설정하는 경우, 요구된 사이즈를 넘지 않는 범위에서 가능한 최대의 사이즈로 설정된다. 예를 들면 quickcam은 3개의 고정적인 설정 밖에 사용할 수 없다.

Frame buffer
capture 카드로부터 frame buffer에 직접 데이터를 쓰게 하기 위해서는, frame buffer의 베이스 주소(Base Address), 사이즈(Size), 구조(Organisation)를 장치(Device) 드라이버에 가르쳐 두지 않으면 안된다. 이것은 특권 모드(Proviliged)의 ioctl()이며, 사실은 X서버 자신이 설정해야 할 것이다.
VIDIOCSFBUF ioctl로 capture 장치(Device)를 위한 frame buffer의 파라미터를 설정한다. capture 카드가 frame buffer에의 직접적인 쓰기를 지원하고 있지 않는 경우, 이 ioctl()는 지원되지 않는다. VIDIOCGFBUF ioctl( ) 는 현재 설정되어 있는 파라미터를 돌려준다. 두 경우 모두 struct video_buffer를 사용해 파라미터를 얻어온다.

void *base 버퍼의 물리 베이스 주소(Base Physical Address)
int height frame buffer의 높이
int width frame buffer의 폭
int depth frame buffer의 깊이(Depth)
int bytesperline 인접한 다음의 같은 옆위치까지의 메모리상에서의 바이트(Byte) 수

이러한 값은 frame buffer의 물리적인 레이아웃을 반영한다. 실제로 표시되고(Visible) 있는 영역은 실제의 frame buffer보다 작을수도 있다. 사실, XFree86에서 이런 것은 보통이다. XFree86 의 DGA는 이 ioctl 로 설정하는 파라미터를 제공할 수 있다. 베이스 주소를 NULL로 설정해서, frame buffer에 액세스를 할 방법이 없다는 것을 나타낼 수 있다.

Capture Windows
capture하는 영역은 struct video_window를 사용해서 결정한다. 이 구조체는 capture 하는 영역과 필요하면 클리핑(Clipping)하는 영역을 설정한다. VIDIOCGWIN ioctl 로 현재의 설정된 값을 가져 올 수 있어서 VIDIOCSWIN 로 새로운 값을 설정할 수 있다.
VIDIOCSWIN 의 ioctl 에 성공했을 경우, 적당한(Suitable) 파라미터들이 선택되었다는 것이다. 이것은 요구된 파라미터 대로에 정확하게 설정했다고 하는 의미가 아니다. 유저 프로그램은, VIDIOCGWIN를 사용해서 실제로 설정된 파라미터가 정확한지 확인할 필요가 있다. struct video_window 에는 다음과 같은 항목이 있다.

x X윈도우에서의 X 좌표
y X윈도우에서의 Y 좌표
width capture 하는 이미지의 폭
height capture 하는 이미지의 높이
chromakey chroma-key의 값(호스트 순위(Host Order)에서의 RGB32의 값)
flags 추가 capture 플래그
clips 클리핑 하는 직사각형의 리스트(설정만)
clipcount 클리핑 직사각형의 수(설정만)

클리핑 직사각형은 배열로 넘겨준다. 클리핑 직사각형의 각 요소에는 다음의 항목이 있다.

x 스킵(Skip)하는 직사각형의 X좌표
y 스킵(Skip)하는 직사각형의 Y좌표
width 스킵(Skip)하는 직사각형의 폭
height 스킵(Skip)하는 직사각형의 높이

단지 capture 영역을 설정한 것 만으로는, capture하는 것은 유효하지 않는다. VIDIOCCAPTURE ioctl 로 1을 설정해서 건내주는 것으로써, 오버레이 capture 하는 것을 시작한다. 그리고 0을 설정하는 것으로써, 멈출 수가 있다.
몇몇의 capture-장치(Device)에 따라서는, 실제로 보이고 있는 영역의 일부를 capture 할 수 있는 것도 있다. 이 경우, VIDEO_TYPE_SUBCAPTURE가 설정되어 있다. video_capture 구조체는 시간과 Capture할 특별한 부분 영역을 지정한다.
video_capture 구조체에는 다음의 항목이 있다.

x 붙잡는(Grab) 영역의 X좌표
y 붙잡는(Grab) 영역의 Y좌표
width 붙잡는(Grab) 영역의 폭
height 붙잡는(Grab) 영역의 높이
decimation 적용될 스킵할 영역(decimation)
flags 붙잡을(Grab) 때의 플래그

가능한 플래그(flags)에는 다음의 것이 있다.

이름 설명
VIDEO_CAPTURE_ODD 홀수 프레임만을 capture 한다
VIDEO_CAPTURE_EVEN 짝수 프레임만을 capture 한다

비디오 소스(Video Source)
각각의 video4linux의 비디오나 오디오 드라이버는 한개 혹은 여러 소스 채널로부터 capture 한다. 각각의 채널은 VIDIOCGCHAN ioctl호출해서 정보를 얻을 수 있다. 이 함수(VIDIOCGCHAN ioctl)를 사용하기 전에, 호출하는 측은 반드시 channel의 항목에 정보를 얻고 싶은 채널의 번호를 설정해야 한다. 채널 자신에 대한 정보를 struct video_channel 에 저장하여 값을 돌려준다.
VIDIOCSCHAN ioctl 는 정수(integer) 형태의 인수를 취해서, capture하는 입력으로 변환한다. 색의 설정이나 튜닝에 관한 파라미터가 채널 변환을 건너서 유지되는 것은 정의되지 않는다. 호출측에서, 채널마다 이것들을 관리해 다시 설정해 줘야한다.(다른 비디오 입력마다 다른 설정을 보존하는 것이 합리적이다. (reasonable))
struct video_channel 은 다음과 같이 구성되어 있다.

channel
채널 번호(Channel Number) name 입력의 이름 - 카드의 입력 자신의 라벨(Label)이 반영되는 것이 바람직하다.
tuners 이 입력으로 연결되어 있는 튜너(Tuner)의 수
flags 튜너(Tuner)가 가지고 있는 설정(Properties)
type 입력의 타입(만약 알고 있는 경우만)
norm 이 채널의 표준(TV신호의 모드)

flags의 정의는

VIDEO_VC_TUNER 채널에 튜너(Tuner)가 있다.
VIDEO_VC_AUDIO 채널에 오디오가 있다.
VIDEO_VC_NORM 채널은 표준(TV신호의 모드)의 설정을 가지고 있다.

types의 정의는

VIDEO_TYPE_TV 입력은 TV 입력이다
VIDEO_TYPE_CAMERA 입력은 카메라이다

이미지 속성의 설정
화상(Picture)의 이미지 속성은 VIDIOCGPICT ioctl를 사용하면 struct video_picture에서 얻을 수 있다. VIDIOCSPICT ioctl 를 호출하여 이러한 값을 변경할 수 있다. palette의 형(Type)을 제외한 모든 값은 0~65535의 사이에서 조정된다.
struct video_picture 에는 다음의 항목이 있다.

brightness 화상의 밝음
hue 화상의 색조(hue)(칼라의 경우만)
colour 화상의 색(Color)(칼라의 경우만)
contrast 화상의 대조(Contrast)
whiteness 백색도(Whiteness) (그레이 스케일의 경우만)
depth 캡처하는 깊이(Capture Depth)(frame buffer의 깊이(depth)와 대조(match)할 필요가 있겠지요)
palette 이 이미지에서 사용될 팔레트를 알려준다.

팔레트의 값에는 다음의 것이 있다.

VIDEO_PALETTE_GREY 선형적으로 증가하는 gray scale(255가 가장 밝은 흰색)
VIDEO_PALETTE_HI240 BT848의 8 bit 칼라 큐브(cube)
VIDEO_PALETTE_RGB565 RGB565를 16 bit 워드(Word)에 채운다.(Packed)
VIDEO_PALETTE_RGB555 RGB555를 16 bit 워드(Word)에 채운다.(Packed), 맨 위의 비트는 미정의
VIDEO_PALETTE_RGB24 RGB888를 24 bit 워드(Word)에 채운다.(Packed)
VIDEO_PALETTE_RGB32 RGB888를 하위 3바이트에 넣은 32bit. 맨 위의 아르바이트는 미정의
VIDEO_PALETTE_YUV422 YUV422의 비디오의 형태(Style) - 4bits를 Y, 2bits를 U, 2bits를 V에 할당한 8bits
VIDEO_PALETTE_YUYV Describe me
VIDEO_PALETTE_UYVY Describe me
VIDEO_PALETTE_YUV420 YUV420 캡처(capture)
VIDEO_PALETTE_YUV411 YUV411 캡처(capture)
VIDEO_PALETTE_RAW RAW 캡처(capture) (BT848)
VIDEO_PALETTE_YUV422P YUV 4:2:2 Planar
VIDEO_PALETTE_YUV411P YUV 4:1:1 Planar

튜닝(Tuning)
각각의 비디오 입력 채널에는 그것과 관련된 하나 또는 다수 개의 튜너(Tuner)가 연결되어 있다. 많은 장치(Device)는 튜너(Tuner)를 가지고 있지 않는다. TV카드나, 라디오(Radio)카드에는 하나 또는 다수 개의 튜너(Tuner)가 붙어 있다.
튜너(Tuner)에 대한 정보는 VIDIOCGTUNER ioctl를 사용해서 struct video_tuner에서 얻을 수 있다. 튜너(Tuner)의 번호를 설정해 ioctl를 호출하면, 내용을 구조체로 보내준다. 튜너(Tuner)의 변환은 사용하고 싶은 튜너(Tuner)의 정수형의 번호(int)를 인수로 VIDIOCSTUNER를 이용한다.

struct video_tuner은 다음의 항목으로 구성된다.

tuner 튜너(Tuner)의 번호
name 튜너(Tuner)의 규범적인(Canonical) 이름 (예 FM/AM/TV)
rangelow 설정 가능한 최저 주파수
rangehigh 설정 가능한 최고 주파수
flags 튜너(Tuner)의 상태를 알려주는 플래그(Flags)
mode TV신호의 모드(관련하는 경우만)
signal 신호의 강도(아는 경우) - 0~65535의 사이

플래그(flags)에는 다음의 것이 있다.

VIDEO_TUNER_PAL PAL를 수신(tuning)을 지원한다.
VIDEO_TUNER_NTSC NTSC를 수신(tuning)을 지원한다.
VIDEO_TUNER_SECAM SECAM를 수신(tuning)을 지원한다.
VIDEO_TUNER_LOW 주파수가 저역대(Lower range)이다.
VIDEO_TUNER_NORM 튜너(Tuner)의 표준(TV신호의 모드)를 설정할 수 있다
VIDEO_TUNER_STEREO_ON 튜너(Tuner)의 오디오가 스테레오가 되어 있다
VIDEO_TUNER_RDS_ON 튜너(Tuner)는 RDS 데이터스트림(Datastream)을 보인다.
VIDEO_TUNER_MBS_ON 튜너(Tuner)는 MBS 데이터스트림(Datastream)을 보인다.

mode 에는 다음의 것이 있다.

VIDEO_MODE_PAL 튜너(Tuner)는 PAL 모드 이다.
VIDEO_MODE_NTSC 튜너(Tuner)는 NTSC 모드 이다.
VIDEO_MODE_SECAM 튜너(Tuner)는 SECAM 모드 이다.
VIDEO_MODE_AUTO
자동적으로 변환(switches)하는 모드 또는 모드를 설정할 수 없는 경우

튜너(Tuner)로 설정하는 주파수는 1/16 MHz 내에서의 unsigned 의 32bit 의 값이지만 VIDEO_TUNER_LOW 의 플래그가 설정되어 있는 경우에는 1/16 KHz의 값이다. 현재의 주파수는 VIDIOCGFREQ ioctl를 통해서 unsigned long 값으로 없을 수 있고 VIDIOCSFREQ ioctl 로 설정할 수 있다.

오디오(Audio)
TV와 라디오 장치(Device)는 선택할 수 있는 하나 또는 다수 개의 오디오 채널을 가지고 있다. 오디오의 설정은 struct video_audio을 VIDIOCGAUDIO ioctl에 건네주는 것으로 얻을 수 있다. 또 VIDIOCSAUDIO ioctl로 오디오의 특성(Properties)를 설정할 수 있다.
struct video_audio은 다음의 항목으로 구성된다.

audio 채널 번호
volume 볼륨 레벨(Level)
bass 중저음(bass) 레벨(Level)
treble 고음(treble) 레벨(Level)
flags 오디오 채널의 상태를 알려주는 플래그(Flags)
name[16] 오디오 입력을 위한 규범적인(Canonical) 이름
mode 오디오 입력의 모드
balance 좌/우의 밸런스
step 하드웨어로 설정 가능한 단계(Step)

플래그(flags)에는 다음과 같이 정의된다.

VIDEO_AUDIO_MUTE 오디오가 단음(mute)되고 있다
VIDEO_AUDIO_MUTABLE 단음(mute)를 지원한다.
VIDEO_AUDIO_VOLUME 음량(Volume)의 컨트롤을 할 수 있다
VIDEO_AUDIO_BASS 중저음(bass)의 컨트롤을 할 수 있다
VIDEO_AUDIO_TREBLE 고음(treble)의 컨트롤을 할 수 있다
VIDEO_AUDIO_BALANCE 좌우 밸런스의 컨트롤을 할 수 있다

디코딩(Decoding) 모드는 다음과 정의된다.

VIDEO_SOUND_MONO 모노(Mono) 신호
VIDEO_SOUND_STEREO 스테레오(Stereo)의 신호(NICAM for TV)
VIDEO_SOUND_LANG1 언어 1을 바꿀 수 있는 유럽 TV(European TV alternate language 1)
VIDEO_SOUND_LANG2 언어 2을 바꿀 수 있는 유럽 TV(European TV alternate language 2)

이미지 읽어오기(Reading Image)
read의 시스템 콜(System Call)에 대한 각각의 콜(Call)은 장치(Device)로부터 다음의 가능한 이미지를 가져온다. 포맷을 설정하고 함수에 대한 올바른 크기의 버퍼를 준비하는 것은 호출자의 책임이다. 모든 장치(Device)가 read 시스템 콜을 지원하지 않는다.
두번째 방법으로 장치(Device)가 mmap을 지원하면 mmap 인터페이스(interface)를 통해서 이미지 가져오는 것(Capture)을 조정할 수 있다. mmap 인터페이스를 사용하기 위해서 사용자는 우선 첫 번째로 원하는 이미지와 깊이(Depth)의 성질을 결정해야 한다.
그 다음 VIDIOCGMBUF ioctl를 호출한다. 이 ioctl 는, mmap 해야 할 버퍼(Buffer)의 크기와 각각의 프레임(Frame)에 대한 버퍼에서의 오프셋(offset)을 알려준다. 지원되는 프레임의 수는 장치(Device)에 의해서 결정되고 대체적으로 한 프레임이다.
video_mbuf structure은 다음의 항목으로 구성된다.

size 잡으려고(Map) 하는 바이트(Bytes) 수
frames 프레임(Frame)의 수
offsets 각각의 프레임 마다의 오프셋(offset)

mmap를 실시하면, VIDIOCMCAPTURE ioctl로 (최초의 설정과 같거나 작은) 사용하고 싶은 이미지의 사이즈를 설정한다. 설정이 끝나면 메모리 맵(Map)된 버퍼에 capture가 시작된다. 프로그램에 의해 버퍼가 사용(used) 될 때마다, VIDIOCSYNC ioctl를 호출해서 이 프레임을 해체(free)하고 계속(continue) 한다. 추가로 : VIDIOCSYNC는 해체(free)하고 싶은 프레임 번호를 인수로 가지고 있다.
버퍼가 unmapped 되거나, 모든 버퍼가 다 채워지면, capture는 멈춘다. 드라이버에 메모리와 화면의 양쪽 모두에 capture할 수 있게 설정했을 경우, 메모리에 캡처(Capture)하는 동안에 드라이버는 가능한 한 최선의 방법(Best Effort)으로 캡처한 것을 화면에 표시한다. 이것은 일반적으로 메모리 맵으로 Captuer할 수 없었던 모든 프레임(frame)이 화면에 표시될 수 있다.
마지막의 ioctl는, 만약 하나의 드라이버가 여러 개의 부속품(Components)으로 되어 있을 경우, 하나의 장치(Device)가 관련되어 있는 장치(Device)들을 얻게 해준다. (예를 들면, video0는 나쁜 문제를 만드는 intercast 표시 로그램의 원인이 될 수 있는 vbi0와 항상 관련이 있다고는 할 수 없다.)VIDIOCGUNIT ioctl은 관련되어 있는 장치(Device)가 있는 경우에 그 단위 번호들(unit Number)을 알려준다. video_unit 구조체에는 다음의 항목이 있다.


video 비디오 capture 장치(Device)
vbi VBI capture 장치(Device)
radio 라디오 장치(Device)
audio 오디오 믹서
teletext Teletext 장치(Device)

RDS 데이터스트림(Datastream)
RDS를 지원하는 라디오 장치(device)를 위해서, 장치에 read() 시스템 콜을 이용하여 Radio Data System(RDS) 정보를 받아오는 것은 가능하다. 이 데이터들은 다음과 같은 3개의 그룹으로 합쳐있다.

First Octet RDS 블록의 LSB(Least Significant Byte)
Second Octet RDS 블록의 MSB(Most Significant Byte)
Third Octet
Bit 7 : 에러 비트(Error bit). 이 블록을 받는 도중에 복구할 수 없는 에러가 발생했다는 것을 나타낸다.
Bit 6 : Corrected bit. 이 데이터 블록을 위해서 에러가 수정되었다는 것을 나타낸다.
Bit 5~3 : Received Offset. 싱크 시스템(Sync System)에 의해서 오프셋이 받아졌다는 것을 나타낸다.
Bit 2~0 : Offset Name. 이 데이터에 적용되는 오프셋을 나타낸다.

'Programming > Linux' 카테고리의 다른 글

yum을 이용한 rpm 다운로드 방법  (0) 2016.03.25
gcc 컴파일 옵션.  (0) 2008.08.22
Linux find grep 명령사용하기  (0) 2008.06.24
Fedora8사전에서 Microsoft를 검색하면...  (0) 2008.05.26
printf를 잘 쓰자  (0) 2008.05.21
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

1. 문자열 찾기(영어 전용)

# grep -rw "찾는문자열" ./

2. 문자열 찾기

# grep -i -l "찾는문자열" * -r 2> /dev/null

2>/dev/null : 에러출력을 /dev/null 로 보내라는 의미

3. 문자열 찾기(한영 공용)

# find . -exec grep -l "찾는문자열" {} \; 2>/dev/null

4. 문자열 찾기(한영, 대소문자 무시)

# find . -exec grep -i -l "찾는문자열" {} \; 2>/dev/null

옵션 i는 대소문자를 무시하라는 의미

5. 문자열 찾은 후 치환

# find . -exec perl -pi -e 's/찾을문자열/바꿀문자열/g' {} \; 2>/dev/null

6. 파일 찾기

# find / -name 파일명 -type f

7. 파일 찾기(대소문자 무시)

# find / -iname 파일명 -type f

8. 디렉터리 찾기

# find / -name 파일명 -type d

9. 디렉터리 찾기(대소문자 무시)

# find / -iname 파일명 -type d

10. 하위 디렉터리에서 모든 파일 찾기


find . | xargs grep '파일명'

'Programming > Linux' 카테고리의 다른 글

gcc 컴파일 옵션.  (0) 2008.08.22
V4L??  (0) 2008.06.26
Fedora8사전에서 Microsoft를 검색하면...  (0) 2008.05.26
printf를 잘 쓰자  (0) 2008.05.21
리눅스 디렉토리  (0) 2008.05.21
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
사용자 삽입 이미지
 
Evil Empire....

'Programming > Linux' 카테고리의 다른 글

V4L??  (0) 2008.06.26
Linux find grep 명령사용하기  (0) 2008.06.24
printf를 잘 쓰자  (0) 2008.05.21
리눅스 디렉토리  (0) 2008.05.21
Data Types  (0) 2008.04.03
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
4. gcc의 짝꿍들

gcc 는 컴파일러입니다. 당연히 소스를 컴파일 할수 있읍니다.
그런데 gcc만 가지고 있어서는 아무런 일도 못합니다.

왜냐구요?

그이유를 알고 싶으시다면 kelp/임베디드강좌/초보 에
holelee 님이 쓰신 gcc 이야기 시리즈를 읽어 보시기 바랍니다.
( 개인적으로 많은 깨달음을 얻게 해준 내용 입니다 )

그래서 gcc 이외에 필요한 프로그램과 데이타(?)들이 있읍니다.
이런 것을 모두 모은 것을 크로스 컴파일러 툴 체인이라고 합니다.

컴파일러 툴이라면 될 텐데 굳이 체인이라고 붙인 이유는
제 개인적인 생각으로는 각 패케지간에 서로 의존적이기 때문일것으로
추측합니다.

이 툴 체인의 목록은 다음과 같습니다 .

binutils - 어셈블러, 링커 그리고 라이브러리 관련 실행 화일들 모음
kernel - 리눅스 커널 ( 헤더 파일 때문에 필요함 )
gcc - 컴파일러
glibc - 라이브러리 및 헤더화일

추가적으로

gdb - 디버거 ( 이놈은 그냥 옵션으로 생각하시면 됩니다. ^^ )

가 있읍니다.

4.1 gcc의 3.0 대의 속설(?)

많은 분들은 gcc의 3.0 대에 문제가 있다고 알고 있어서
이 버전을 회피하시면서 예전 버전을 고집하시는 경향이 있읍니다.

그런데 이 부분은 오해랍니다.

문제가 되는 버전은 gcc 3.0 입니다.
당연히 문제가 발생했으니 해당 버전을 고쳤겠지요

그래서 3.1 대 이후라면 별 문제는 없읍니다

크로스 컴파일을 하시는 분이라면 최근 프로세스를 쓰기 위해서는
예전 버전으로는 한계가 있읍니다.

최신 버전을 쓰셔야 지원되는 프로세스가 있읍니다.

넘 겁먹지 마시고 3.0대를 쓰시기 바랍니다.

4.2 binutils

바이너리 유틸이라고 합니다.
포함되는 내용은 다음과 같죠...

addr2line - 실행화일의 어드레스에 대한 소스화일명과 라인 넘버를 표현해주는 프로그램입니다.
ar - 라이브러리를 관리하는 프로그램입니다.
as - 어셈블러 입니다.
c++filt - 잘 모르겠읍니다. ^^
gasp - 어셈블러 매크로 해석기 입니다.
ld - 링커 입니다.
nm - 오브젝트안의 심볼릭을 표시해 주는 프로그램입니다.
objcopy - 오브젝트 화일을 컨버팅 해주는 프로그램입니다.
objdump - 오브젝트 화일의 정보를 표시해 줍니다.
ranlib - 라이브러리의 인덱스 화일을 생성합니다.
readelf - elf 포맷의 화일 헤더 정보를 해석해 줍니다.
size - 오브젝트 화일의 섹션 크기와 포함된 오브젝트의 총 크기를 표시해 줍니다.
strings - 프로그램 내부에 사용되는 초기화 문자열들을 골라 표시해 줍니다.
strip - 오브젝트나 실행화일의 정보를 선택적으로 제거해 줍니다.

4.3 kernel

크로스 컴파일러를 만들때 사용되는 데이타 타입이나 시스템 콜을 참조하기 위해서
필요한 헤더화일을 참조하기 때문에 툴체인에 들어 갑니다.

엄밀히 말하면 kernel의 헤더화일만 필요합니다.

4.4 gcc

패케지가 일반적으로 지원하는 것은 각 언어별로 지원합니다.
다음은 크로스 컴파일러로 쓰는 대표적인 것 들입니다.

gcc,cpp,g++,c++,gccbug,gcov

설명을 굳이 달지 않는 이유는 저는 gcc 이외에는 거의 쓰지 않기 때문에
뭐하는 놈들인지 잘 몰라서 입니다. 이해해 주세요...

4.5 glibc

커널을 컴파일하거나 부트로더를 컴파일 할때는 필요 없읍니다.

하지만 응용프로그램을 사용한다면 당연히 이것이 있어야 합니다.

여러분들 중에서 glibc와 newlib 를 혼동하시는 분들이 있읍니다.

glibc 는 GNU 라이브러리 입니다. 크기가 매우 커집니다.
newlib는 glibc가 매우 크기 때문에 꼭 필요한 놈들만 골라서 추려놓은 것이죠
그래서 크기가 매우 작습니다.

특별한 경우가 아니라면 저는 newlib를 별로 추천하지 않습니다.
가끔 리눅스용 프로그램을 임베디드 제품에 포팅하다보면 없는 함수가 있어서
곤란을 겪기 때문입니다.

램이나 플래쉬 시스템이 16M 이상이고 여유가 있다면 가급적 glibc를 쓰시기를
권유합니다.

4.6 gdb

이놈은 디버거죠..

즉 프로그램을 디버깅 할때 유용한 도구 입니다.
하지만 윈도우 디버거를 사용하시던 분이라면 매우 불편함을 느끼실 겁니다.

하지만 없는 것 보다는 있는 것이 좋습니다.
printf 만 가지고 디버깅 하시면 매우 힘들끼 때문입니다.

더구나 익숙해지면 의외로 막강한 기능에 놀라시게 됩니다.

이 놈을 굳이 툴체인에 포함시키지 않는 것은 상호 연관관계가 별로 없어서
입니다.

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
초보자 아닌 분은 보지 마십시오...

1. 글을 시작 하며

이글은 임베디드 리눅스의 초보자를 위한 글입니다.
(이미 알고 계신분은 물러 가십시오... ^^ )

이글의 내용 중 일부는 저의 잘못된 경험에 의해서 오류가 있을 수
있읍니다.

오류를 발견하시면 바로 지적을 부탁 드립니다.

이글은 임베디드 시스템에 리눅스를 사용하기 위해서 사용되는
크로스 컴파일 환경에 대한 간단한 소개 글이지 설치 방법에
대한 글이 아님을 미리 말씀 드립니다.

2. 크로스 컴파일러란?

대부분의 프로그래머들은 PC 라는 동일한 환경에서 프로그램을
작성하실 겁니다.

PC에서 프로그램을 짜고 컴파일 하고, 실행 화일을 PC에서 수행 합니다.

이렇게 동일한 환경에서 동작 되는 컴파일러와 이 컴파일러에서
생성된 실행화일을 동일한 환경에서 수행 한다면 이때의 컴파일러를
네이티브( native ) 컴파일러라고 합니다.

이와 반대로 컴파일러가 동작하는 시스템과 컴파일러에 의해서 생성된
실행화일이 동작하는 시스템이 다를 때 이 컴파일러를 크로스(cross)
컴파일러라고 합니다.

여러분이 임베디드 시스템에 동작하는 프로그램을 작성한다면
당연히 크로스 컴파일러 환경을 구축해야 합니다.

개발 환경은 PC 일것이고 실행 화일이 동작하는 시스템은
다른 CPU 구성을 갖는 임베디드 시스템일 것이기 때문입니다.

그렇다고 모든 임베디드 시스템에 동작하는 프로그램들이 크로스
컴파일 환경을 필요로 하는 것은 아닙니다.

PC와 같은 구조를 갖는 임베디드 리눅스 시스템을 만든다면
PC의 네이티브 컴파일러에서 만들어진 실행화일이 그대로
수행될 수 있기 때문입니다.

하지만 임베디드 시스템 대부분이 저렴한 가격대를 요구하거나,
또는 특수한 기능을 수행하는 구조를 가지기 때문에 이런 경우는
조금 드믄 편입니다.

그래도 개발 프로세스를 빠르게 진행하기 위해서 익숙한 PC 구조를
사용하는 경우도 요즈음은 많아 지는 추세인것 같습니다.

어찌되었든 크로스 컴파일 환경에서의 개발은
윈도우 개발자 입장에서 보면 매우 열악한 개발 환경이 됩니다.

돈이 많은 회사야 좋은 개발 툴을 사서 이런 열악한 환경을
일부 개선하기는 하지만 그래도 열악하기는 마찬가지 입니다.

가장 큰 이유는 컴파일이 끝난후 실행 화일을 즉시 시험하지
못하기 때문입니다.

그외에도 개발하기 위해서 손가락이 무척 바빠지는 것도
한 요인입니다. 단순하게 마우스 클릭 한번으로 수행되는
GUI 컴파일러에 익순한 분들이 타자를 치는 것은 무척 힘든
것입니다.

그래도 리눅스에서 크로스 컴파일러를 사용하는 것에는 이유가
있읍니다.

3. 리눅스와 gcc

지금은 많은 분들이 임베디드 시스템 개발에 리눅스를
사용되고 있다는 것을 알고 있읍니다.

하지만 그 이유가 리눅스 커널을 임베디드 시스템에 탑제하기
때문이라고 알고 계신다면 잘못 알고 계신 겁니다.

임베디드 시스템 개발 환경으로 리눅스를 사용하는 근본적인
이유는 gcc라는 막강한 컴파일러가 있기 때문입니다.

리눅스만 사용하시는 분이라면 리눅스 프로그램 개발을 위해서
당연히 gcc라는 컴파일러를 사용합니다.

그래서 gcc라는 것이 그냥 리눅스용 컴파일러라고 알고 있읍니다.

하지만 gcc는 그렇게 단순한 컴파일러가 아닙니다.

또한 gcc는 그냥 i386 프로세서에서 동작하는 실행화일을 만들어
내는 컴파일러도 아닙니다.

현재 존재 하는 컴파일러 중에서 가장 많은 프로세서를 지원하는 컴파일러가
바로 gcc입니다.

gcc 컴파일러의 패케지는 이미 전세계에 동작되는 대부분의 프로세서를
지원하기 위한 준비를 갖추고 있읍니다.

더구나 공짜입니다. !!!

하지만 여러분은 이런 gcc가 어떻게 다른 CPU를 지원하게 할 수 있는지에
대해서는 모를 겁니다.

그냥 gcc 명령을 치면 i386 코드가 생성되기 때문입니다.


3. 크로스 컴파일러와 gcc 소스 패케지

gcc에서 i386 이외의 실행화일을 만들기 위해서는 리눅스에 이미 설치된
gcc란 컴파일러는 소용이 없읍니다.

몇 가지 옵션만 바꾸어서 gcc 수행한다고 i386 이외의 프로세서를 지원하는
코드가 생성되는 것은 아닙니다.

애초에 다른 프로세서에서 동작 될 수 있는 실행화일을 만들수 있겠금 gcc를
만들어야 하는 것입니다.

그렇다고 기존에 i386에서 동작하는 gcc를 아예 다른 프로세서에서 동작하는
실행화일을 만드는 gcc로 바꾸어 버리면 문제가 됩니다.

그 뒤로는 i386에 동작하는 어떤 프로그램도 만들 수 없기 때문입니다.

그래서 보통은 gcc의 이름을 조금 바꿉니다.

예를 들어 arm 계열의 프로세서에서 동작하는 실행 프로그램을 만들기 위해서
사용하는 gcc는 arm-linux-gcc라는 이름을 가집니다.

이름이 다른 이 두 컴파일러는 전혀 다른 컴파일러가 아닌 똑같은 gcc인 것입니다
단지 gcc는 i386 프로세서에서 수행되는 코드를 만들어 내는 컴파일러이고
arm-linux-gcc라는 것은 arm 프로세서에서 동작되는 코드를 만들어 내는 컴파일러
일 뿐입니다.

관행적으로 네이티브용 컴파일러가 보통 gcc가 되고 크로스 컴파일러는 gcc
앞에 접두사를 붙입니다.

만약 알파 프로세서 동작하는 gcc에서 i386 계열의 실행 코드를 만드는 크로스
컴파일러는 i386-linux-gcc가 될 것입니다. ( 확인하지 않았읍니다. ^^ )

어찌되었든 둘 다 동일하게 gcc란 패케지에서 파생한 컴파일러인 것입니다.

자....

제가 자꾸 gcc 패케지라는 말을 쓰고 있읍니다.
이 gcc 패케지라는 것이 무엇일까요?

윈도우에서 델파이라는 개발 툴을 구매해서 설치하면 단순하게 델파이 컴파일러
만 설치되는 것이 아닙니다. 개발하기 위한 이것저것들이 설치 됩니다.

이와 동일한 개념으로 gcc 패케지란 컴파일을 하기 위한 이런 저런 것을 모두 담은 것을
말 하는 것입니다.

윈도우에서와 달리 리눅스에서는 패케지들이 소스로 구성되어 있읍니다.
그래서 이런 것을 gcc를 예를 들면 gcc 소스 패케지 라고 말합니다.

또 여러분이 착각하는 것중 하나가 gcc가 단순하게 c 컴파일러라고 알고 있는데
정확하게 이야기 하면 c 컴파일러가 아닙니다. c++ 소스를 컴파일
할때도 역시 gcc 를 사용합니다. 어셈블러를 컴파일 할때도 gcc를 사용할수
있읍니다.

그래서 gcc 소스 패케지에는 c 이외의 몇가지 컴파일러들이 더 들어 있읍니다.

어찌되었든 gcc 소스 패케지란 gcc 컴파일러를 만들수 있는 소스로 구성된 것을
말 합니다.

이 gcc 소스 패케지를 이용하여 원하는 프로세스 지원 크로스(또는 네이티브)
컴파일러를 만드는 것입니다.

그런데 아주 모순 된 것 중 하나는 gcc를 만들기 위해서는 gcc가 필요하다는
점입니다. 왜냐하면 gcc 소스 패케지이기 때문입니다.

하지만 이점은 여기에서 문제 삼지 않으려 합니다.
여러분의 리눅스에는 당연히 gcc 컴파일러가 이미 설치되어 있기 때문입니다.

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
APK003 print를 잘 쓰자
==============================================

1. 개요

이 문서는 ESP-NS에서 동작하는 응용 프로그램에서
printf 를 쓰는 방법에 대한 소개 입니다.

작성자 : 유영창
frog@falinux.com
작성일 : 2004년 9월 10일
수정일 :

관련된 ADK( Application Developer Kit ) 디렉토리

adk/sample/printf

2. 최강의 디버거 printf

응용 프로그램을 작성하는 과정에 반드시 수반되는 것이
디버깅입니다. 이 과정은 프로그래머에게는 숙명입니다.
이걸 피해갈 사람은 없읍니다.

윈도우 프로그래머라면 통합 환경에서 제공하는 디버깅기능을
즐겨 사용하게 됩니다.

이런 분들이 임베디드 리눅스에서 동작하는 프로그램을 디버깅
하면 갑갑함을 느낍니다.

왜냐?

임베디드 리눅스에서 사용할만한 통합환경이 없다는 것이
가장 큰 이유입니다

그렇다면 리눅스에는 쓸만한 디버거가 없을까요?

있읍니다 그것도 엄청 막강한 gdb라는 툴이 있읍니다.

그러나

제 주위에서 이 프로그램을 사용하는 사람 본적이
별로 없읍니다.

왜냐하면 준비하는데 엄청난(?) 작업이 필요하기 때문입니다.
특히 저같이 게으른 사람에게는 gdb를 이용해서 작업하는
과정은 무척 어려운 일입니다.

라인 명령을 사용해야하고 디버깅을 위한 준비작업 또한
만만치 않기 때문입니다.

그래서 저는 printf 라는 막강한 디버거를 사용합니다.

사실 임베디드 시스템에서 printf 함수는 목적하는 기능구현을
위해서 사용할 필요가 없는 함수입니다.

뭐 .... PC 리눅스에서도 마찬가지죠..

하지만

이 printf 함수 만큼 즐겨 사용하는 함수가 없읍니다.

주로 디버깅을 위해서 사용합니다.

이 printf 디버거는 무척 강력합니다.

일단 준비할 것이 없읍니다

그냥 printf 만 사용하면 됩니다.

그리고 내가 원하는 모든 변수값들을 찍어 볼수 있읍니다.
내가 원하는 함수의 문장을 통과하는지를 관찰할수 있읍니다.

디버깅이라는 것이 이게 다 아니겠읍니까?

리눅스 프로그램머들은 고수가 될수록 이 printf 함수를
자유자재로 사용합니다.

저 스스로도 고수라고 칭하므로 당근 이 printf 함수를
아주 적절히(?) 절묘하게(?) 사용합니다.
이건 고수들만의 노하우도 됩니다. ( 퍽~~ ㅜㅜ )

그런데 이 printf 를 그냥 사용하는 것은 조금 불편합니다.

그래서 조금 변경해서 사용하는데 이것을 소개할까 합니다.
그리고 더불어 주의점도요...

3. printf함수도 시간을 빼앗아 간다.

printf 를 그냥 사용해도 되지만 디버깅 단계에서는 유용하겠지만
나중에는 수많은 메세지들이 콘솔에 난무하는 엄청난 혼란을
발생합니다. ( 당해본 사람만 압니다.)

그래서 고수(?)들은 이 printf 를 그냥사용하지 않고 매크로 함수로
변형해서 사용합니다.

간단하게 소개 하면 이렇게 어딘가에 선언을 합니다.

//#define NDEBUG

#ifndef NDEBUG
#define dp(fmt,args...) printf( fmt, ## args )
#define dlp(fmt,args...) printf( "[%s %d]" fmt, __FILE__,__LINE__, ## args )
#else
#define dp(fmt,args...)
#define dlp(fmt,args...)
#endif


이것은 NDEBUG 라는 것이 선언되어 있지 않으면
dp 라는 것은 printf 함수로 대치 됩니다.
( dlp 라는 것은 조금 나중에 설명하겠읍니다. )

만약 NDEBUG 라는것이 선언되면 printf 는 아무것도 하지 않고
프로그램 소스에서 제거 됩니다.

예를 들어

printf( "hello world\n" );

이라고 쓰는 것은

dp( "hello world\n" );

라고 쓰면 됩니다.

#define NDEBUG 라는 문장이 없으면
위 문장들은 출력을 발생하게 됩니다.

그러나

#define NDEBUG 를 선언하게 되면

dp( "hello world\n" );

는 아무런 일도 하지 않습니다. 더구나 컴파일러의 최적화에 의해서
실행코드의 크기도 작아 먹지 않습니다.

위에서 소개한 dp 문은 보통 전체 소스 파일들이 사용하는 공통 헤더파일에
정의해 써 놓고 사용하는 것이 좋습니다.

평소에는 dp 문을 이용하여 출력을 하다가

NDEBUG 라는 문자열만 사용하면 싹~ 없어지기 때문에 나중에 한꺼번에
출력이 안될수도 있기 때문에 추척 편리한 함수입니다.

하나의 소스파일에서 메세지 출력을 없애고 싶다면
해당 소스파일에 위 정의문의 바로 위나 위 정의문을 포함한 헤더파일을
선언하는 #include 문 앞에 NDEBUG 라는 문자열을 정의하면 됩니다.

정말 정말 편리한 기능입니다.

만약 프로그램 전체에서 dp를 사용한 문자열의 출력을 제거하고 싶다면
그냥 컴파일 옵션에 -DNDEBUG 라는 것만 추가 하면됩니다.

APK 에 있는 샘플에 소개한 Makefile을 사용한다면
Makefile 에 있는

CFLAGS += -Wall -O2 -g



CFLAGS += -Wall -O2 -g -DNDEBUG

로 바꾸면 됩니다.

4. printf함수를 이용한 위치 추적

혹시 다음과 같은 문장의 의미를 여러분은 아시는 지 모르겠읍니다.

printf( "%s %s %d\n", __FILE__, __FUNCTION__, __LINE__ );

이것은 이 문장이 적혀진 라인을 포함하는 파일명과 함수명 그리고
파일의 라인번호를 출력하게 합니다.

그래서 이것을 이용해서 dlp라는 함수를 선언합니다.

dp는 단순히 어떤 메세지나 값을 표출하는데 사용한다면
dlp는 해당 메세지가 표출된 위치를 함께 표출하기 위해서 사용합니다.

5. \r 을 출력하는 문자열 라인의 앞에 추가 하자!

초기에 보드에 프로그램을 작성 하다 보면 디버깅을 위한 메세지를
출력하면서 동작상태를 관찰하게 됩니다.

그런데 응용 프로그램을 자동으로 실행하게 했다면 로긴이 안된 상태이기
때문에 문자열의 '\n' 문자 때문에 다음과 같은 현상이 발생합니다.

message line 1
message line 2
message line 3

원래는 줄 앞에 나란히 정렬해야 하는데 삐뚤 삐뚤하게 출력되기 때문에
애써 예쁘게 출력하도록 한 내용이 보기 어렵게 됩니다.

그래서 한 라인의 시작 문자열 맨 앞에서는 '\r' 문자를 사용하는 것이 좋습니다.

예를 들어

printf( "message line 1\n" );
printf( "message line 2\n" );
printf( "message line 3\n" );

이라고 한다면 이것을 다음과 같이 고쳐 주어야 합니다.

printf( "\rmessage line 1\n" );
printf( "\rmessage line 2\n" );
printf( "\rmessage line 3\n" );

6. \n을 사용하기 전까지는 화면에 출력되지 않는다.

printf 문장을 사용해서 다음과 같이 특정 변수명값을 추적한다고 합시다.

while(1)
{
:
printf( "%d ", test_v );
:
}

이렇게 하고 출력이 나올걸 기대하면 아마도 전혀 의도하지 않는 현상이
발생할겁니다.

리눅스에서 printf 문은 '\n' 을 만나기 전까지는 출력 처리가 되지 않는
다는 점을 기억합시다.!!!!

왜 이렇게 될까요?

그것은 여러 프로세스들이 서로 출력을 할때 보기 편하라는 의미가 담겨
있읍니다

A 프로그램도 출력도 하고 B 프로그램도 출력을 하고 있다면 아마도
먼저 보낸 순서대로 출력이 되어야 할겁니다. 그러면 서로 짬봉이
되는 바람에 무슨 내용인지 알수가 없죠...

그래서 '\n'을 먼저 출력하는 프로그램의 출력 내용을 표출하는 것입니다.

그래서 출력 결과를 보시고자 한다면 항상 출력하고자 하는 내용의 마지막에는
'\n'을 꼭 추가하시기 바랍니다.

7. printf 는 실제로 시리얼로 출력하는 것이다.

ESP 보드는 printf 가 메인 콘솔에서 본다면 시리얼로 데이터가 전송되는 것입니다.
메인 콘솔의 속도가 115200 으로 되어 있지만 이 속도가 그렇게 빠르지 않다는 점을
명심하시기 바랍니다.

나중에 printf 가 블럭 되기도 하고 아주 빠른 처리를 요구하는 부분에서 printf를
남발하면 큰 코 다치게 됩니다.

특히 printf 는 그 처리가 무척 복작한 함수입니다. 그래서 한번만 호출해도
엄청난 수행시간을 필요로 합니다.

그래서 가끔 아주 간단한 지연이 필요한 경우에는 이 printf 함수를 사용하기도
한다는 점 기억하시기 바랍니다. 그만큼 처리 속도를 잡아 먹는 다는 이야기 입니다.

'Programming > Linux' 카테고리의 다른 글

Linux find grep 명령사용하기  (0) 2008.06.24
Fedora8사전에서 Microsoft를 검색하면...  (0) 2008.05.26
리눅스 디렉토리  (0) 2008.05.21
Data Types  (0) 2008.04.03
유닉스/리눅스 명령어 레퍼런스  (0) 2008.03.26
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
■ 리눅스 디렉토리 구조

□ / (root)
- 마운트 되는 리눅스 파일 시스템이 있는 최상위 디렉토리
- 시스템의 근간을 이루는 가장 중요한 디렉토리
- 파티션 설정 시 반드시 존재하여야 함
- 절대경로의 기준이 되는 디렉토리
    ※ 절대경로 - / 디렉토리 기준   예) /usr/local
       상대경로 - 현재 작업 디렉토리 기준 예) ./local

□ /bin
- 리눅스의 기본 명령어(binary)들이 들어있는 디렉토리
- 시스템을 운영하는데 기본적인 명령어들이 들어 있음.

□ /sbin
- 시스템 관리에 관련된 실행 명령어들이 들어있는 디렉토리
- 시스템 점검 및 복구 명령, 시스템 초기 및 종료 명령 등 시스템 관리에
   관련된 실행파일들 존재.

□ /lib
- 프로그램들이 의존하고 있는 라이브러리 파일들 존재.
- /lib/modules : 커널 모듈 파일들 존재.
- 대부분의 라이브러리들은 링크로 연결되어 있음.

□ /proc
- 시스템에 대한 정보를 제공하는 가상 파일 시스템.
- 커널의 어떤 기능을 제어할 수 있는 역할을 가지고 있음.
- 대부분 읽기 전용이나, 일부 파일중에는 쓰기가 가능한 파일이 존재
   하는데 이러한 파일들에 특정 값을 지정하면 커널 기능이 변하게 됨.
- 이 디렉토리 내에 있는 파일을 cat 명령을 이용하여 보면 시스템 정보를
   확인 할 수 있음.
   예) 인터럽트 정보 확인 ---> cat /proc/interrupts

□ /etc
- 시스템 환경 설정 파일이 있는 디렉토리
- 네트워크 관련 설정파일, 사용자 정보 및 암호정보, 파일 시스템 정보,
   보안파일, 시스템 초기화 파일등 중요 설정 파일들의 위치한 디렉토리
- /etc/CORBA : Common Object Request Broker Architecture (COBRA)에
                관한 파일이 들어있음.
- /etc/X11 : 엑스 윈도우 설정에 관련된 파일들이 있음.
- /etc/cron.d : crontab 명령의 설정파일이 있음.
- /etc/cron.daily : 매일 작동하게 하는 crontab 스크립트 파일이 존재.
- /etc/gnome : GTK+ 정의파일들이 있음.
- /etc/httpd : 아파치 웹 서버의 설정 및 로그파일이 있음.
- /etc/logrotate.d : logrotate 설정 파일들이 있음.
- /etc/mail : 센드메일과 관련된 파일이 있음.
- /etc/ppp : ppp 설정에 관련된 파일들이 있음.
- /etc/profile.d : 쉘 로그인 하여 프로파일의 실행되는 스크립트에
                    대한 정의가 있음.
- /etc/rc.d : 시스템 초기화와 관련된 스크립트가 존재.
- /etc/samba : 삼바에 관련된 파일들이 있음.
- /etc/security : 터미널 보안에 관련된 설정이 있음.
- /etc/skel : 새로운 사용자를 추가할 때 자동적으로 생성되는 디렉토리와
               파일이 있음.
- /etc/squid : squid 프록시 서버에 관련된 파일이 있음.
- /etc/ssh : secure shell 설정 파일이 있음
- /etc/sysconfig : 시스템과 네트워크 설정을 담고 있음.
- /etc/xinetd.d : 슈퍼데몬 xinetd.d의 서비스 영역을 설정하는 디렉토리.

□ /var
- 가변 자료 저장 디렉토리
- 시스템 운영중에 시스템 자료 데이터가 변경될 때 변경된 자료들이
   저장되는 곳.
- 주로 시스템 작동기록(log)들을 저장.
- /var/log : 시스템에 발생된 일들에 대한 기록 파일이 있음
- /var/named : 네임서버 설정 파일들 존재
- /var/spool/mail : 수신 메일을 사용자 명으로 기록하는 디렉토리

□ /usr
- 일반 사용자들을 위한 대부분의 프로그램 라이브러리 파일들이 위치.
- /usr/bin : 응용 프로그램의 실행 파일이 위치
- /usr/sbin : 주로 네트워크 관련 실행 명령어와 실행 데몬들을 많이
   포함하고 있음.
- /usr/X11R6 : X-window 시스템에 관련된 파일 존재.
- /usr/include : 기본 C 라이브러리 헤더 파일과 각종 라이브러리
   헤더파일들이 있음.
- /usr/lib : /usr/bin과 /usr/sbin에 있는 실행 바이너리를 실행하기 위한
   라이브러리 존재.
- /usr/src : 프로그램소스 및 커널 소스들이 보관되어 있는 곳.
- /usr/man : 매뉴얼 페이지가 담겨있는곳.
- /usr/local : 새로운 프로그램들이 설치되는 곳
    (windows의 Program Files 와 유사)

□ /mnt
- 다른 장치들을 마운트 할때 일반적으로 사용하는 디렉토리
- 다른 디렉토리를 사용하여도 됨.

□ /home
- 일반 사용자의 홈 디렉토리가 만들어 지는 디렉토리
- 사용자 계정을 만들면 게정과 같은 이름으로 새로운 사용자 디렉토리가
   /home 디렉토리의 하위 디렉토리로 생성됨.
예) test 사용자 추가 후 홈 디렉토리 확인하기.
root@test />$adduser test
root@test />$cd /home
root@test home>$ls

     test   <-- 디렉토리 생성

□ /boot
- 부팅에 핵심적인 커널 이미지와 부팅 정보 파일을 담고 있는 디렉토리
- /etc/lilo.conf에서 지정한 커널 부팅 이미지 파일이 들어 있으며 부팅시
   매우 중요한 디렉토리

□ /root
- 슈퍼유저(root) 사용자의 홈 디렉토리.
- / 와 /root 디렉토리는 부르는 이름은 같지만 서로 다름.

'Programming > Linux' 카테고리의 다른 글

Fedora8사전에서 Microsoft를 검색하면...  (0) 2008.05.26
printf를 잘 쓰자  (0) 2008.05.21
Data Types  (0) 2008.04.03
유닉스/리눅스 명령어 레퍼런스  (0) 2008.03.26
Man Page/sigaction  (0) 2008.03.26
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
글쓴이 : 임장섭 (2002년 03월 21일 오전 04:34) 읽은수: 2,250 [ 새소식 인쇄용 페이지 ]

Special Report

RISC는 임베디드에 유용한가?

하나의 프로젝트를 시작할 때 그 구성요소를 선택하는 것은 무척 어려운 결정이다. 그 중 중요한 결정 중의 하나는 RISC(Reduced Instruction Set Computer)와 CISC(Complex Instruction Set Computer) 중 하나를 선택하는 것이다. CISC는 요즘 기술이 빠르게 진보한다는 점을 가만하면 비교적 오래된 것이긴 하지만, 아직도 성능이 우수하며 CISC를 선택하는 것이 더 현명할 때도 있다.

새로운 프로젝트를 시작할 시점이라고 가정해보자. 당신은 마이크로프로세서를 선택해야 할 것이다. 32비트 프로세서가 필요하다고 결정하긴 했지만, 그 중 어떤 것인가? 100가지 이상의 다양한 32비트 임베디드 칩 중에 하나를 선택해야 한다. 따라서, 그 중 마음에 드는 몇 가지로 선택의 폭을 좁혀야 한다. 그렇다면 아마도 당신은 RISC 프로세서를 골랐을 것이다.
대부분의 프로그래머와 엔지니어들은 이렇게 말할 것이다. "요즘은 프로세서가 다 RISC 아냐?" RISC는 현대적이고 더 빠르며 더 매력적이다. 한마디로 더 호감이 간다.
그러나 최신 유행에 민감한 대부분의 엔지니어들은 인정하기 힘들지 몰라도, 10년 된 CISC 칩을 선택하는 것이 요즘 나온 RISC 칩을 선택하는 것보다 너 나을 수도 있다. 물론 항상 그런 것은 아니지만, 실제 설계자들이 느끼는 것보다는 더 자주 있는 일이다. CISC 칩은 아직도 건재하며, 대부분의 인기있는 RISC보다도 더 선호되고 있다. 모토로라와 MIPS사는 32비트 프로세서 판매에서 1, 2위를 다투고 있으며, 1998년 기준으로 각각 8,330만 개, 5,000만 개의 판매고를 기록했다. 인텔의 CISC dinosaur(68K인 것으로서)도 1,230만 개의 높은 판매량을 기록한 제품이다. CISC는 RISC라는 용어가 생기고 나서 생긴 용어다. 세계대전(Great War)이 2차 세계대전(World War Ⅱ)이란 말이 생긴 이후 1차 세계대전(World War I)으로 바뀌어 불렸듯이, CISC란 표현은 이와 반대 개념인 RISC란 용어가 생김에 따라 나오게 된 용어다.

RISC란 무엇인가?
우선, RISC란 실제로 무엇인가와 RISC가 무엇을 의미하는 지를 구분해서 알아보자.
RISC는 reduced instruction set computer의 약자로서 컴퓨터(혹은 그 내부의 프로세서)가 축약형 명령 셋을 가지고 있음을 암시한다. 그것은 CPU Lite와 같다. 당신은 RISC가 마이크로프로세서의 분해된 형태일 뿐이라고 냉소적으로 말할 수도 있다. 부분적으로는 맞는 말이다.
RISC의 개발원리는 프로세서를 완전히 분해하는 것이었다. 꼭 필요한 요소가 아니면 다 버렸다. 이것은 프로그래머의 관점에서 볼 때, 때로는 RISC 칩이 간단한 곱셈도 할 수 없다는 것을 의미한다. 그 의견은 곱셈은 단순히 반복되는 덧셈이기 때문에 ADD 명령이 충분히 좋아야 한다는 것이다.
RISC가 처음 부상하기 시작한 1980년대에 UC Berkeley와 Stanford에선 무슨 생각을 하고 있었을까? 무어의 법칙에 의해, 매달 칩 디자이너에게 4%의 하드웨어를 넣는 것은 축소를 위해 바람직하지 않은 것으로 생각했다. RISC의 기초가 되는 아이디어는 복잡한 기능은 하드웨어가 아닌 소프트웨어에서 더 효율적으로 행해진다는 것이다. 소프트웨어는 하드웨어보다 바꾸기 쉽고, 업데이트하기 쉬우며 더 빨리 만들어 낼 수 있다. 새로운 칩을 설계해서 만드는 것보다 새로운 코드를 쓰는 것이 더 빠르다. 따라서 RISC를 기반으로 하는 컴퓨터는 더 빨리 업그레이드될 수 있다. 프로그램과 알고리즘은 기록시간에서 변경되고 향상되어 진다. 무엇보다도 RISC 하드웨어는 단순화되고 능률적으로 되어가기 때문에 칩도 더 빨리 작동할 수 있다. 모두가 다 좋은 것이다.
본래의 RISC 칩은 CISC의 반대 개념으로서의 현재 RISC보다 더 작고 단순했으며 빨랐다.
68020과 80286과 같은 프로세서가 수년간 축적해 온 것들을 버림으로써 SPARC와 MIPS 같은 RISC가 만들어졌다.
클록 주파수의 측면에서 RISC는 완전한 승리자였다. 기술 잡지와 산업간행물들은 RISC의 등장을 컴퓨터의 신기원이라고 환호했다.
주위에서 가장 빠른 프로세서를 찾으라고 한다면 누구나 인텔의 펜티엄을 선택할 것이다. 이것이 당신이 구할 수 있는 가장 빠른 프로세서라는 것이 애통할 만한 일이었다. 그렇다면 SPARC는? 썬사의 워크스테이션은 현재 가장 느린 32비트 칩 중의 하나에 의해 가동되고 있다.
뭐가 잘못된 것인가? 확실히 1990년대에는 RISC를 둘러싼 과장이 많았다. RISC가 PC산업에서의 인텔의 압도적인 우세를 꺾을 마지막 기회로 보여졌기 때문에 어느 정도는 이해가 간다. 만약 RISC가 반값으로 두 배의 성능을 보여주었다면(절대 실현될 수 없는데도 종종 반복되는 주장) 확실히 전세계는 인텔과 그 독점회사들을 포기했을 것이다. RISC는 가진 것 없는 자들의 마지막 희망이었다.
동시에 RISC의 기세는 인텔을 포함한 CISC 벤더들을 자극했다. 모토로라는 68030과 68040으로 68K 제품군을 확장시켰고, x86 아키텍처는 68386과 68486으로 한 단계 나아갔다.
하지만, 하나의 예외로 인해 그들은 그렇게 할 수 없었다. 68K 프로세서는 클록 속도가 대부분의 32비트 칩보다 뒤떨어져 최대치가 남들이 세 자리 숫자일 때 66 MHz 이었다. 요즘도 대부분의 68K 프로세서는 100 MHz 이하의 속도에서만 사용할 수 있다.
이것이 CISC 프로세서의 죽음을 이야기하는가? CISC는 영원히 사장되고 마는 것인가?
그렇지 않다. 클록 속도에서는 종종 뒤쳐지지만 68K와 x86 같은 CISC 칩은 아직도 충분한 능력을 수행하고 오히려 RISC 보다 더 낫다. CISC 칩은 고려해 볼만한 가치 이상의 것이며 때론 임베디드 시스템을 위한 최고의 선택이 되기도 한다.

장점과 단점
RISC 아키텍처로 얻을 수 있는 것은 직교명령집합(orthogonal instruction set)이 있는 비교적 간단한 CPU이다. 모든 명령은 같은 길이를 가지고 있어 RAM에 깔끔하게 정렬된다. 또한 비슷하게 엔코더 되기 때문에 RISC opcode를 해체하고자 한다면 작업이 쉬워진다. 메모리에서 명령을 카운트하는 것도 쉽다. 마지막으로 RISC 명령은 거의 항상 단일 클록 사이클에서 실행되기 때문에 특정 루틴의 사이클 수를 계산할 수 있다.
RISC는 명령이나 혹은 당신이 좋아할 지도 모르는 다른 기능들이 없다. 우선 수학이 있다. 대부분의 RISC 칩에는 원래 곱하거나 나누는 명령이 없다. 그리고 대부분은 아직도 나누기를 못한다. 당신이 어셈블리 언어 프로그래머라면 축하한다. 당신은 정수를 곱하고 나누기 위해 코드 루틴을 소유하게 된다. 부동 소수점 계산은 신경 쓰지 않아도 된다. 대부분의 RISC 칩은 이 기능도 없다. 대부분의 CISC 칩에도 FPU(부동소수점처리장치)가 없지만 새로운 RISC 칩보다는 오래된 CISC 프로세서에서 더 자주 볼 수 있다.
또한 bit twiddling도 없다. 시스템에 레지스터나 다른 주변장치가 많다면 프로세서가 32 bit word보다 적은 것을 처리하지 않을 때 더 곤란해진다. 많은 RISC 설계자들은 단일 비트 구동을 명백하게 이단 시 했다. 예를 들어, 상태 레지스터(status register)에서 단일 비트를 체크하고 고정(toggle)하기 위해 당신은 프로세서로 들어가는 메모리의 전체 레지스터(그리고 그 주위 메모리 32비트 전체 혹은 I/O)를 읽어야만 한다.
정렬되지 않은 메모리 액세스는 RISC의 또 다른 골칫거리다. RISC 칩은 워크스테이션을 위해 설계되었는데, 워크스테이션에선 컴파일러가 항상 워드 경계를 따라 데이터를 정렬해 놓는다(바이트처럼). 더 작은 수는 존재하지 않거나 32비트 단어에 맞추기 위해 zero-pad된다. 임베디드 시스템에서는 좀처럼 그렇게 깔끔하지 않다.
홀수 어드레스에 저장된 32비트처럼 메모리 경계 주위를 둘러싼 숫자는 많은 RISC 칩에 접근하기 어렵다. 그들은 정렬되지 않은 연산 수를 다룰 수가 없다. 마찬가지로 24-bit 값과 같이 odd-sized quantity는 저장될 때 zero-extend 또는 sign-extended 되어야만 하므로 결과적으로 RAM을 낭비한다.
좋은 소식은 컴파일러는 이 중 어떤 것도 감지하지 못한다는 것이다. 당신이 어셈블리 언어 프로그래머라면 RISC가 곤혹스러울 것이다. 만약 당신이 컴파일러를 가지고 C나 다른 고수준(high level) 언어로 프로그램을 쓴다면 이러한 제약을 거의 깨닫지 못하게 될 것이다. 당신이 코드 밀도에 관심이 없다면 말이다.
image_view.jpg
코드 밀도
많은 임베디드 설계자들은 마이크로프로세서보다 시스템 내의 RAM과 ROM에 더 많은 비용을 소비한다. 메모리는 많은 시스템의 특성을 정의(또는 한정)한다. 마케팅은 메모리에 비용을 더 쓰기보다는 기능을 줄이고 싶어한다. 프로그래머는 메모리 예산에 코드를 맞추어야 한다.
이러한 면에서 코드 밀도는 큰 문제가 될 수 있다. 코드 밀도는 실행 가능한 프로그램이 얼마나 꽉 차 있는 지를 보여준다. 그것은 프로그램의 풋프린트이며 하나의 프로세서에서 다른 프로세서로 완전히 변한다. 이것을 경험해 보지 못했다면 당신은 컴파일된 C 프로그램은 모두 다 똑같고 어떤 칩이 실제 코드를 실행시키는 지는 중요하지 않다고 생각할 수도 있을 것이다. 이것은 큰 오산이다.
다른 칩을 위해 컴파일된 아주 똑같은 C 프로그램은 완전히 다른 메모리 풋프린트를 만들어낸다. 이것은 컴파일러의 실수나 오류가 아니다. 그것은 다른 칩보다 더 밀도가 높은 바이너리를 생산하는 몇몇 CPU 칩의 자연스런 특성이다.
그림 1은 많이 사용되고 있는 32비트 마이크로프로세서들의 코드 밀도 비교한 것이다. 그림에서 볼 수 있듯이, 차이는 절반까지 생길 수 있다. 이러한 칩들이 실제 같은 프로그램(같은 소스 코드)을 실행하고 있고 같은 결과를 가져온다고 해도 어떤 칩은 다른 칩 코드 공간의 반만 있으면 된다는 것이다.
CISC 칩의 코드 밀도가 RISC 칩의 코드 밀도보다 더 좋다는 것도 알 수 있다. RISC의 원칙 중의 하나는 모든 복잡한 기능은 다 소프트웨어에서 행해지고 하드웨어는 단순화되어야 한다는 것이다. 이는 RISC 칩이 같은 일을 하기 위해 CISC 칩보다 더 많은 소프트웨어를 필요로 할 것이라는 것을 의미한다. 대부분의 RISC 칩은 나누기 명령이 없다. 만약, 두 숫자를 나누길 원한다면 소프트웨어에서 하면 되는 것이다.
이에 대해 당신이 코드나 컴파일러에서 할 일은 없다. 컴파일러는 주어진 하드웨어 명령과 함께 일해야만 한다. 당신의 프로세서에 축약형 명령어가 있다면 컴파일러는 더 많은 소프트웨어를 만들어냄으로써 그것을 보상해 줄 것이다.

코드 압축
CISC 칩이 더 나은 코드 밀도를 가지고 있는 또 다른 이유는 그 명령이 짧아지는 경향이 있기 때문이다. 정의에 의하면, 32비트 RISC 칩은 32비트 명령을 가지고 있다. 반면 32비트 CISC 칩은 아마도 8비트, 16비트, 32비트 그리고 심지어 더 큰 명령을 갖게 될 것이다. 이것은 CISC 칩을 복잡하게 만드는 기능 중의 하나 이지만 임베디드 시스템 내에서는 더 효율적으로 만들기도 한다.
왜 당신은 명령 비트에 신경을 쓰는가? 예를 들어, 68020은 ADD 명령을 8비트 프로그램 메모리에 맞출 수 있지만 MIPS R4000은 32비트를 필요로 하기 때문에 프로그램이 두 개의 숫자를 같이 더할 때마다 이전 메모리의 3/4를 버리게 된다. 또한 MIPS 칩은 68K보다 빠른 것은 첨가할 수 없다.
최근 몇몇 RISC 벤더는 이 문제에 대한 현명한 해결책을 발견했다. 일반적으로 그 해결책은 코드 압축(code compression)이라 불리지만, 그것은 잘못된 이름이다. 아무도 PKZIP을 이용해서 코드를 압축하지 않는다. 대신에 그들은 칩의 명령 셋을 약간 바꾸어 모든 명령이 32비트 길이가 되지 않도록 한다.
이에 대한 세 가지 예가 ARM, ARC Cores 그리고 MIPS이다. 이들은 각각 Thumb, ARCompact, MIPS-16이라 불리는 비슷한 코드 압축 설계가 있다. 세 경우 모두 칩이 소수의 16비트 명령으로 그들의 32비트 명령 집합을 선택적으로 증대시킬 수 있다. 각각의 C 컴파일러는 이제 바이너리를 더 작게 만들면서 16비트 명령을 코드에 뿌릴 수 있다.
얼마나 더 작아지는 지는 여러 요인에 따라 다르다. 그리고 이미 알고 있는 바와 같이 마케팅 광고만큼은 힘들다. 실제 테스트에서 축소는 대략 20∼30% 정도이고 프로그램에 따라 다르다. 그것은 단지 코드 공간의 압축일 뿐이라는 것을 명심하라. 데이터 스토리지는 압축되지 않는다. 하지만, 코드 압축은 올바른 진보이며 RISC 아키텍처를 더욱 매력적으로 만드는 요인 중의 하나이다.
ARM Thum과 MIPS MIPS-16의 두 경우에, 당신의 코드는 32비트 모드와 16비트 모드 사이에서 확실히 스위치되어야 한다. 두 개의 명령형을 혼합할 수 없기 때문에 당신은 32비트의 명령을 사용하여 구동하는 코드에서 16비트의 동작과 함께 구동하는 코드를 분리해야 한다. 우선, 전적으로 16비트 명령과 함께 구동하는 코드 영역을 찾아야 한다.
더 짧은 명령을 위한 trade-off는 그들의 제한된 레퍼터리(repertoire)이다. 예를 들어, 16비트 코드는 인터럽트, 캐시 관리, 메모리 관리, 제외(exception) 또는 롱 점프(long jump) 등을 처리할 수 없다. 운 좋게도 Thumb와 MIPS-16 컴파일러는 이를 분류한다. ARC의 ARCompact는 두 모드 사이에서 스위치하지 않기 때문에 이 제한을 받지 않으며, 두 사이즈의 명령을 자유롭게 혼합하기 때문에 프로그램을 분리시키려고 애쓰지 않아도 된다.
IBM에서 나온 CodePack system은 임베디드 PowerPC 칩에 또 다른 방식으로 접근한다. 다른 세 개의 압축 RISC 명령어와는 달리, IBM은 PKZIP을 사용하는 것처럼 오브젝트 코드(object code)에서 실제로 실행 바이너리들을 압축한다. 이 때 컴파일되고 어셈블되고 링크된 후에 프로그램을 압축할 수 있다. 그리고 나서 압축된 것을 ROM이나 디스크에 저장한다.
임베디드 PowerPC 칩은 메모리로부터 패치될 때 명령을 푸는 별도의 하드웨어가 있다. 그림 2는 어떻게 각각의 명령이 풀리고 압축되는 지 보여준다.
첫째, 당신의 코드는 보통 오브젝트 코드 형식에서 저장되지 않았기 때문에 완전히 불가사의하다. 그 코드는 압축되었고 그것이 압축 해제를 어렵게 만든다. 코드를 보호해야 할 필요성이 있을 때엔 이것이 장점으로 작용할 것이다. CodePack은 소프트웨어를 압축해줄 뿐만 아니라 효과적으로 엔코드 해준다.
둘째, CodePack은 fly 상에서 소프트웨어를 풀어야 하는데, 그것은 가끔 보통 예상하는 것보다 시간이 오래 걸리기 때문에 재미있는 기능을 수행하기도 한다. CodePack이 장착된 PowerPC 프로세서는 branch와 jump을 처리하기가 까다로운데, 이는 branch target이 ROM에 놓여진 코드의 커다란 블록의 어딘가에 엔코드 되었을 때 위치를 정하기 어렵기 때문이다.
셋째, 각각의 CodePack 프로그램은 자신만의 압축키를 사용하기 때문에 프로그램이 다르면 압축도 다르게 된다. 이는 압축된 바이너리들이 양립할 수 없음을 의미한다. 따라서, 키가 없으면 다른 PowerPC에서 가동되지 않을 것이다.
마지막으로, CodePack은 ARC, ARM, MIPS와 똑같은 30%의 compression factor를 보증한다. 그 모든 복잡성을 감안한다면 두드러지게 좋아진 것은 아니다. 하지만, IBM은 획기적인 일을 해냈다.

RISC POWER
RISC 칩이 가지고 있는 하나의 장점은 전력소모량이다. 대개 RISC 칩은 CISC 칩보다 전력을 덜 소모한다. 이것은 명백하다. 만약 RISC 프로세서의 회로 설계가 더 단순하고 간소화되었다면 그것이 전력을 덜 소모하는 이유가 되었을 것이다. 트랜지스터가 더 적다는 것은 에너지가 덜 확장된다는 것을 의미한다.
ARM 프로세서는 전력을 적게 소모하기로 유명한데, 애석하게도 진실이 아니다. 물론 ARM 프로세서는 인텔의 486보다야 전력을 덜 소모하지만, 그것은 Hoover 댐도 마찬가지이다.
공정하게 말해서 ARM 프로세서는 전력을 덜 소모하는 편이긴 하지만, 같은 시기에 나온 대부분의 RISC 프로세서도 다 마찬가지이다. 1994년의 다른 프로세서와 비교하면 ARM7은 경이로울 만큼 전력효율이 높지만 2002년에는 많은 RISC 프로세서가 있을 것이다. 심지어 어떤 CISC 프로세서는 전력효율이 ARM보다 높다. MIPS, SuperH, ARC Core 그리고 다른 것들도 모두 저전력 코어를 가지고 있다.
RISC의 전력 상의 이점은 자동온도조절기(thermostat)나 휴대전화기, 스마트카드 등을 만들 경우에는 무척 중요하지만, 그 외의 다른 애플리케이션에서는 그다지 중요치 않다. 첫 번째 카테고리를 위해 RISC 프로세서는 좋은 선택이다. 비록 당신이 메모리 전력을 소비해도 좋지만, 당신은 CPU 전력을 절약해야 하는 바 조심해야 한다.
코드 밀도는 전력소모에 관계하기 때문에 코드 밀도가 더 나은 칩은 전체적으로 메모리 액세스를 많이 만들지 않아 시스템 전력을 덜 소모할 것이다.
ROM으로부터의 패치나 RAM으로의 읽기/쓰기 액세스는 전력을 적게 소모한다. 그것을 최소화할수록 더 좋다. 여기에는 확고한 법칙이 없기 때문에 예를 든다면 코드 밀도가 2배 증가하였다고 하여도 전력도 2배 증가한다고 말할 수 없다. 애플리케이션마다 다르지만, 만일 당신이 전력소모에 대한 압박을 받게 된다면 이 관계를 기억해라.

성능
RISC의 주요 이점 중에 하나가 그 탁월한 성능이고 따라서 RISC 칩은 항상 빠르다고 할 수 있을까? 한마디로 대답은 "아니오"이다.
무엇보다도 성능이란 말은 애매 모호한 표현이다. 모든 사람은 각각 다른 종류의 성능에 관심이 있다. 예를 들어 미디어 프로세싱에 좋은 것이 네트워크 프로세싱에는 좋지 않을 수 있다. 모든 것에 뛰어난 프로세서는 없다고 말해두겠다. 모든 CPU 명령 셋은 절충일 뿐이다.
당신은 당신의 특수한 애플리케이션에 맞는 ISA(Instruction Set Architecture)가 있는 CPU를 선택해야 한다. 같은 속도로 가동되는 두 개의 칩(여기선 100 MHz라고 하자)은 ISA의 차이에 의해 완전히 다른 성능을 제공할 수 있다.
대부분의 RISC 명령 셋은 거의 동일하다. 그렇다면 결국 그들은 아주 기본적인 것만을 지원하도록 되어 있었던 것인가? 실제 모든 RISC 아키텍처는 수년간 RISC 원칙을 따르지 않는 변형된 기능에 의해 타락해 왔다. 하지만, RISC 칩은 포괄적이고 호환성이 있다.
CISC 진영에는 시스템에 믿을 수 없을 만큼 유용하거나 시스템과 전혀 관련이 없는 여러 가지 명령들이 있다. 때론 어디서 이렇게 괴상한 명령이 나왔을까 생각되기도 하고 다른 프로그램은 이것을 어디다 쓸까 하고 의아해질 때도 있다.
그 중 내가 가장 좋아하는 것 중의 하나는 모토로라에서 나온 68300 제품군 칩에서 발견된 TBLS 명령이다. TBLS는 table look up이고 interpolate instruction이다. 대부분의 프로그래머는 그것을 절대 사용하지 않겠지만, 이런 명령이 필요할 경우 이것은 그야말로 구세주이다.
TBLS 명령은 데이터 포인트의 스파스 테이블(sparse table)에서 복잡한 기하학 함수(geometric function)를 만들 수 있게 해준다. TBLS는 당신이 만들어 놓은 값의 테이블을 탐색해서 가장 가까운 두 개를 당신이 지정한 숫자에 위치시킨다. 그리고 나서 linear interpolation을 통해 그 두 데이터 포인트 사이의 정확한 값을 계산한다. 본질적으로 TBLS는 그림 3에서 보는 것과 같이 X, Y분산그래프의 점들을 연결시킨다.
이상해 보이는가? 그럴 수도 있다. 하지만, 만약 당신이 동작제어를 하고 있다면, 이것은 무척 긴요하게 쓰일 것이다. 이게 없다면 모든 종류의 exception과 boundary case를 가지고 수백 개의 다른 기하학 함수를 코드해야 한다. TBLS는 약 30 클록 사이클에서 실행되는 단일 명령이란 것을 명심해라.

RISC 대 CISC
한마디로 RISC는 빠른 클록 속도를 얻기 위해 feature와 function을 포기하는 것을 의미한다. 당신이 속도를 숭배하고 클록 속도야말로 당신의 모든 것이라고 생각한다면 RISC가 적격이다. 당신은 200 MHz RISC 프로세서를 이용해 75 MHz clunker를 이용하는 것보다 더 높은 clock rate를 얻을 수 있다.
그러나, 더 나은 성능을 얻을 수 없게 되거나 비용만 많이 들이게 될 수도 있다. 빠른 프로세서는 빠른 RAM, 빠른 ROM, 빠른 I/O를 원한다. 당신의 전체 버스 구조도 더 빨라져야 할 것이다.
RISC에 특별한 명성이 있다는 점을 부인할 수 없다. 그것은 새롭고 흥미로운 것으로 인식되고 있으며, 아직도 CISC 프로세서가 강세라는 의견은 반 직관적으로 보인다. 그럼에도 불구하고, CISC는 많은 장점들을 가지고 있다. 코드 밀도와 집적이 더 좋으며, 비트 조작, 메모리 액세스, looping, decision tree 등을 위한 특수한 명령의 성능이 뛰어나다. RISC는 어떤 추상적인 우아함이 있지만, 이것은 비즈니스에는 소용이 없다. 때로는 느리고 꾸준한 것이 경기에서 승리할 수 있다.

+ Recent posts