리눅스 디버깅 기술 마스터하기

출처 : http://www-128.ibm.com/developerworks/kr/library/l-debug/index.html

리눅스 디버깅 기술 마스터하기 (한글)

리눅스 상에서 버그를 해결하는 핵심 전략들

developerWorks
문서 옵션
이 페이지를 이메일로 보내기

이 페이지를 이메일로 보내기

JavaScript가 필요한 문서 옵션은 디스플레이되지 않습니다.


제안 및 의견
피드백

난이도 : 중급

Steve Best, JFS core team member, IBM

2006 년 6 월 19 일

실행중인 사용자 공간 프로그램을 검사하는 방법은 여러 가지이다. 디버거를 실행하여 프로그램을 직접 관찰하거나, print 문을 추가하거나, 프로그램을 분석하는 툴을 추가할 수 있다. 이 글에서, 리눅스에서 실행되는 프로그램을 디버깅 할 때 사용할 수 있는 방법들을 설명한다. 세그멘테이션 오류, 메모리 오버런 및 누수, 행(hang) 같은 문제들을 디버깅하는 네 가지 시나리오를 검토해 본다. (이 글은 2002년 8월에 IBM developerWorks에 게재되었다.)

이 글에서 네 가지 디버깅 시나리오를 제시한다. 시나리오 1의 경우, 메모리 할당 문제가 있는 두 개의 샘플 프로그램을 사용한다. MEMWATCH와 Yet Another Malloc Debugger (YAMD) 툴을 사용하여 디버깅 한다. 시나리오 2에서는 strace 유틸리티를 사용한다. 시스템 호출과 시그널을 추적하여 프로그램이 어디서 잘못되었는지를 규명한다. 시나리오 3에서는 리눅스 커널의 Oops를 사용하여 세그멘테이션 오류 문제를 해결하고 커널 소스 레벨 디버거(kgdb)를 설정하여 GNU 디버거(gdb)를 사용하여 같은 문제를 해결한다. kgdb 프로그램은 직렬 연결을 통한 리눅스 커널 원격 gdb이다. 시나리오 4는 행을 일으키는 컴포넌트 정보를 디스플레이 한다. 매직 키 시퀀스를 사용한다.

일반적인 디버깅 전략

프로그램에 버그가 포함되어 있다면 대게 코드 어딘가에 있을 것이다. 여러분이 사실이라고 믿는 이러한 상황은 실제로는 잘못되었다. 버그를 찾는다는 것은 무엇인가 잘못되었다는 것을 발견할 때까지 여러분이 사실이라고 믿는 것을 다시 한번 확인하는 과정이다.

다음은 여러분이 사실이라고 믿고 있는 몇 가지 유형이다.

  • 소스 코드의 특정 위치에서, 변수는 특정 값을 가진다.
  • 주어진 위치에서, 구조가 정확히 설정되었다.
  • if-then-else 문에서 if 부분은 실행되었던 경로이다.
  • 서브루틴이 호출될 때 루틴은 매개변수를 정확히 받는다.

버그를 찾는 것에는 이러한 모든 것들을 확인하는 과정이 포함된다. 특정 변수가 특정 값을 갖고 있다고 믿는 다면 서브루틴이 호출될 대 이를 검사해보라. if 구조가 실행된다는 것을 믿는다면 검사해 보라. 여러분이 가정하는 것을 확인해보면 결국 여러분의 신념이 잘못되었다는 것을 발견할 것이다. 결국 여러분은 버그의 위치를 찾게 된다.

디버깅은 피해갈 수 없는 과정이다. 메시지를 스크린에 프린팅 하기, 디버거 사용하기, 프로그램 실행에 대해 생각하기, 문제에 대한 현학적인 고찰하기 같이 디버깅에 대한 많은 방식들이 있다.

버그를 픽스하기 전에 소스의 위치부터 알아야 한다. 예를 들어, 세그멘테이션 오류가 있을 경우, 코드의 어떤 라인에서 seg 오류가 발생했는지를 알아야 한다. 문제의 코드 라인을 찾아내면 그 메소드에서의 변수의 값, 메소드가 호출되었던 방법, 에러가 발생했던 이유 등을 파악하라. 디버거를 사용하면 이 모든 정보를 찾기가 쉬워진다. 디버거를 사용할 수 없다면 다른 툴들도 있다. (제품 환경에서는 디버거를 사용하지 못할 수도 있다. 리눅스 커널에는 디버거가 빌트인 되어있지 않다.)

유용한 메모리 및 커널 디버깅 툴
리눅스에서 디버그 툴을 사용하여 사용자 공간과 커널 문제를 추적하는 방법은 여러 가지이다. 다음 툴과 기술을 사용하여 소스 코드를 디버깅 하라.

사용자 공간 툴:

  • 메모리 툴: MEMWATCH와 YAMD
  • strace
  • GNU debugger (gdb)
  • Magic key sequence

커널 툴:

  • Kernel source level debugger (kgdb)
  • Built-in kernel debugger (kdb)
  • Oops

이 글에서는 코드를 육안으로 검사해서는 찾기 어려운 문제들과, 매우 드문 환경에서 발생하는 문제 유형에 대해 살펴보도록 하겠다. 환경이 결합될 때에만 발생하는 에러가 있고, 프로그램을 전개한 후에만 메모리 버그를 발견할 때가 가끔 있다.




위로


시나리오 1: 메모리 디버깅 툴

리눅스 시스템 상의 표준 프로그래밍 언어로서 C 언어는 동적 메모리 할당에 대한 많은 제어권을 제공한다. 하지만 이러한 자유가 중대한 메모리 관리 문제를 야기시키고 이 문제는 프로그램 충돌 또는 강등으로 이어진다.

메모리 누수(malloc() 메모리가 상응하는 free() 호출로 결코 누출되지 않는다.)와 버퍼 오버런(어레이에 할당되었던 지난 메모리 작성하기)은 공통의 문제들이고 탐지하기 어렵다. 이 섹션에서는 메모리 문제를 탐지하고 고립하는 몇 가지 디버깅 툴에 대해 알아보겠다.




위로


MEMWATCH

Johan Lindh가 작성한 MEMWATCH는 다운로드 가능한 C를 위한 오픈 소스 메모리 에러 탐지 툴이다.(참조자료) 헤더 파일을 코드에 추가하고 gcc 문에 MEMWATCH를 정의하면 프로그램에 메모리 누수와 오염을 탐지할 수 있다. MEMWATCH는 ANSI C를 지원하고, 결과 로그를 제공하고, 중복도 없고 에러도 없는 실행하지 않는 메모리와 오버플로우와 언더플로우를 탐지한다.


Listing 1. 메모리 샘플 (test1.c)
		#include <stdlib.h>#include <stdio.h>#include "memwatch.h"int main(void){  char *ptr1;  char *ptr2;  ptr1 = malloc(512);  ptr2 = malloc(512);  ptr2 = ptr1;  free(ptr2);  free(ptr1);}

Listing 1에 있는 코드는 두 개의 512-바이트 메모리 블록을 할당하고 첫 번째 블록에 대한 포인터가 두 번째 블록에 설정된다. 결과적으로 두 번째 블록의 주소가 소실되고 메모리 누수가 생긴다.

이제 memwatch.c를 컴파일 한다. 다음은 makefile 예제이다.


test1
		gcc -DMEMWATCH -DMW_STDIO test1.c memwatchc -o test1

test1 프로그램을 실행하면 누수 된 메모리 리포트가 만들어 진다. Listing 2는 memwatch.log 아웃풋 파일 예제이다.


Listing 2. test1 memwatch.log 파일
		MEMWATCH 2.67 Copyright (C) 1992-1999 Johan Lindh...double-free: <4> test1.c(15), 0x80517b4 was freed from test1.c(14)...unfreed: <2> test1.c(11), 512 bytes at 0x80519e4{FE FE FE FE FE FE FE FE FE FE FE FE ..............}Memory usage statistics (global):  N)umber of allocations made: 	2  L)argest memory usage : 	1024  T)otal of all alloc() calls: 	1024  U)nfreed bytes totals : 	512

MEMWATCH는 문제가 있는 실제 라인을 제공한다. 이미 제거된 포인터를 제거하면 알려준다. 제거되지 않은 메모리에도 똑 같이 적용된다. 로그의 끝에 있는 섹션은 얼마나 많은 메모리가 누수가 있었는지, 얼마나 많이 사용되었는지, 총 할당량은 어느 정도인지를 디스플레이 한다.




위로


YAMD

Nate Eldredge가 작성한 YAMD 패키지는 C와 C++에서 메모리 할당과 관련 문제들을 찾는다. 이 글을 쓰고 있는 현재 최신 버전의 YAMD는 0.32다. yamd-0.32.tar.gz를 다운로드 하라.(참고자료) make 명령어를 실행하여 프로그램을 구현한 다음 make install 명령어를 사용하여 프로그램을 설치하고 툴을 설정한다.

YAMD를 다운로드 한 후에 test1.c에서 이것을 사용한다. #include memwatch.h를 제거하고 makefile을 다음과 같이 변경한다.


YAMD를 사용한 test1
		gcc -g test1.c -o test1

Listing 3은 test1 상에서의 YAMD의 아웃풋이다.


Listing 3. YAMD를 사용한 test1 결과
		YAMD version 0.32Executable: /usr/src/test/yamd-0.32/test1...INFO: Normal allocation of this blockAddress 0x40025e00, size 512...INFO: Normal allocation of this blockAddress 0x40028e00, size 512...INFO: Normal deallocation of this blockAddress 0x40025e00, size 512...ERROR: Multiple freeing Atfree of pointer already freedAddress 0x40025e00, size 512...WARNING: Memory leakAddress 0x40028e00, size 512WARNING: Total memory leaks:1 unfreed allocations totaling 512 bytes*** Finished at Tue ... 10:07:15 2002Allocated a grand total of 1024 bytes 2 allocationsAverage of 512 bytes per allocationMax bytes allocated at one time: 102424 K alloced internally / 12 K mapped now / 8 K maxVirtual program size is 1416 KEnd.

YAMD는 우리가 이미 메모리를 제거했고 메모리 누수가 있다는 것을 알려준다. 또 다른 샘플 프로그램에서 YAMD를 실행해 보자.


Listing 4. 메모리 코드 (test2.c)
		#include <stdlib.h>#include <stdio.h>int main(void){  char *ptr1;  char *ptr2;  char *chptr;  int i = 1;  ptr1 = malloc(512);  ptr2 = malloc(512);  chptr = (char *)malloc(512);  for (i; i <= 512; i++) {    chptr[i] = 'S';  }	  ptr2 = ptr1;  free(ptr2);  free(ptr1);  free(chptr);}

다음 명령어를 사용하여 YAMD를 시작한다.

./run-yamd /usr/src/test/test2/test2

Listing 5는 샘플 프로그램 test2에서 YAMD를 사용한 결과를 보여준다. YAMD는 for 루프에서 우리가 out of bound 조건을 갖고 있다는 것을 말해준다.


Listing 5. YAMD를 사용한 test2 결과
		Running /usr/src/test/test2/test2Temp output to /tmp/yamd-out.1243*********./run-yamd: line 101: 1248 Segmentation fault (core dumped)YAMD version 0.32Starting run: /usr/src/test/test2/test2Executable: /usr/src/test/test2/test2Virtual program size is 1380 K...INFO: Normal allocation of this blockAddress 0x40025e00, size 512...INFO: Normal allocation of this blockAddress 0x40028e00, size 512...INFO: Normal allocation of this blockAddress 0x4002be00, size 512ERROR: Crash...Tried to write address 0x4002c000Seems to be part of this block:Address 0x4002be00, size 512...Address in question is at offset 512 (out of bounds)Will dump core after checking heap.Done.

MEMWATCH와 YAMD 모두 유용한 디버깅 툴이고 다른 접근 방식이 필요하다. MEMWATCH를 사용해서는 include 파일인 memwatch.h에 추가하고 두 개의 컴파일 타임 플래그를 켜야 한다. YAMD는 link 문에 -g 옵션만 필요했다.




위로


Electric Fence

대부분의 리눅스 배포판에는 Electric Fence용 패키지가 포함되어 있지만 다운로드 할 수도 있다. Electric Fence는 Bruce Perens가 작성한 malloc() 디버깅 라이브러리이다. 여러분이 할당한 메모리 바로 뒤에 보호를 받는 메모리를 할당한다. fencepost 에러가 있다면(어레이 끝에서 실행됨) 프로그램은 프로텍션(protection) 에러를 사용하여 즉시 종료된다. Electric Fence와 gdb를 결합하면 어떤 라인이 보호되는 메모리에 접근했는지 정확히 추적할 수 있다. Electric Fence는 메모리 누수를 탐지할 수 있다.




위로


시나리오 2: strace 사용하기

strace 명령어는 사용자 공간 프로그램에서 실행되는 모든 시스템 호출을 보여주는 강력한 툴이다. strace는 호출에 대한 인자를 디스플레이 하고 상징적인 형태로 값을 리턴한다. strace는 커널에서 정보를 받고 커널이 특별한 방식으로 빌트인 될 필요가 없다. strace 정보는 애플리케이션과 커널 개발자에게 유용하다. Listing 6에서 파티션의 포맷은 실패했고 listing은 make file system(mkfs)에 대한 strace의 시작을 보여준다. strace는 어떤 호출이 문제를 일으키는지 결정한다.


Listing 6. mkfs에서의 strace 시작
		execve("/sbin/mkfs.jfs", ["mkfs.jfs", "-f", "/dev/test1"], & ... open("/dev/test1", O_RDWR|O_LARGEFILE) = 4 stat64("/dev/test1", {st_mode=&, st_rdev=makedev(63, 255), ...}) = 0 ioctl(4, 0x40041271, 0xbfffe128) = -1 EINVAL (Invalid argument) write(2, "mkfs.jfs: warning - cannot setb" ..., 98mkfs.jfs: warning - cannot set blocksize on block device /dev/test1: Invalid argument )  = 98 stat64("/dev/test1", {st_mode=&, st_rdev=makedev(63, 255), ...}) = 0 open("/dev/test1", O_RDONLY|O_LARGEFILE) = 5 ioctl(5, 0x80041272, 0xbfffe124) = -1 EINVAL (Invalid argument) write(2, "mkfs.jfs: can\'t determine device"..., ..._exit(1)  = ?

Listing 6을 보면 ioctl 호출이 파티션을 포맷하는데 사용되었던 mkfs 프로그램이 실패하는데 원인이 된다는 것을 알 수 있다. ioctl BLKGETSIZE64는 실패한다. (BLKGET-SIZE64ioctl을 호출하는 소스 코드에 정의된다.) BLKGETSIZE64 ioctl은 리눅스 상의 모든 장치들에 추가되고 있고, 이 경우, 논리적 볼륨 매니저는 이것을 지원하지 않는다. 따라서 mkfs 코드는 BLKGETSIZE64 ioctl 호출이 실패할 경우 오래된 ioctl을 호출해야 한다. 이것은 mkfs가 논리적 볼륨 매니저와 작동하도록 한다.




위로


Scenario 3: gdb와 Oops 사용하기

Free Software Foundation의 디버거인 gdb 프로그램을 사용할 수 있다. 명령행 또는 Data Display Debugger (DDD) 같은 그래픽 툴에서 사용할 수 있다. gdb를 사용하여 사용자 공간 프로그램이나 리눅스 커널을 디버깅 할 수 있다. 이 섹션에서는 gdb용 명령행에 대해서만 설명하겠다.

gdb program name 명령어를 사용하여 gdb를 시작한다. gdb는 실행 파일의 심볼을 로딩하고 인풋 프롬프트를 디스플레이 하면, 여러분은 디버거를 사용할 수 있다. gdb 프로세스를 볼 수 있는 세 가지 방법이 있다.

  • attach 명령어를 사용하여 이미 실행중인 프로세스를 본다. attach는 프로세스를 중지시킬 것이다.

  • run 명령어를 사용하여 프로그램을 실행하고 시작할 때 프로그램을 디버깅 한다.

  • 기존 코어 파일을 보고 프로세스가 종료되었을 때의 상태를 파악한다. 코어 파일을 보려면 다음 명령어를 사용하여 gdb를 시작한다.

    gdb programname corefilename

    코어 파일을 사용하여 디버깅 하려면 프로그램 실행 파일과 소스 파일 그리고 코어 파일이 필요하다. 코어 파일로 gdb를 시작하려면 -c 옵션을 사용한다.

    gdb -c core programname

    gdb는 어떤 라인의 코드가 문제를 일으켰는지를 코어 덤프에 보여준다.

프로그램을 실행하거나 이미 실행중인 프로그램에 붙기 전에 버그가 있다고 생각하는 소스 코드의 리스트를 만들고, 중단점을 설정하고, 프로그램 디버깅을 시작한다. gdb 온라인 도움말과 help 명령어를 사용하여 상세한 튜토리얼을 참조할 수 있다.




위로


kgdb

kgdb 프로그램(gdb를 통한 원격 호스트 리눅스 커널 디버거)은 gdb를 사용하여 리눅스 커널을 디버깅 하는 메커니즘을 제공한다. kgdb 프로그램은 커널의 확장으로서, 원격 호스트 머신에서 gdb를 실행할 때 kgdb 확장 커널을 실행하는 머신에 연결할 수 있다. 커널로 들어가서 중단점을 설정하고 데이터를 검사할 수 있다. (애플리케이션 프로그램에서 gdb를 사용하는 것과 비슷하다.) 이 패치의 주요 기능들 중 하나는 gdb를 실행하는 원격 호스트가 부팅 프로세스 동안 목표 머신(디버깅 될 커널을 실행하고 있음)으로 연결된다는 점이다. 때문에 디버깅을 최대한 빨리 시작할 수 있다. 이 패치는 리눅스 커널에 이 기능을 추가하여 gdb가 리눅스 커널을 디버깅하는데 사용될 수 있도록 한다.

kgdb를 사용하려면 두 개의 머신이 필요하다. 하나는 개발 머신이고 다른 하나는 테스트 머신이다. 시리얼 라인(null-modem cable)은 시리얼 포트를 통해 머신으로 연결된다. 여러분이 디버깅 하고자 하는 커널은 테스트 머신 상에서 실행된다. gdb는 개발 머신에서 실행된다. gdb는 시리얼 라인을 사용하여 여러분이 디버깅 하고 있는 커널과 통신한다.

다음 단계를 통해서 kgdb 디버그 환경을 설정한다.

  1. 리눅스 커널 버전에 맞는 패치를 다운로드 한다.

  2. 커널에 컴포넌트를 구현한다. 이것은 kgdb를 사용하는 가장 쉬운 방법이다. (커널의 컴포넌트를 구현하는 두 가지 방법이 있다. 모듈로서 구현하거나 직접 커널에 구현하는 방법이 있다. 예를 들어, Journaled File System (JFS)은 모듈로서 구현되거나 커널에 직접 구현될 수 있다. gdb 패치를 사용하면 JFS를 커널에 직접 구현할 수 있다.)

  3. 커널 패치를 적용하고 커널을 재구현 한다.

  4. .gdbinit 라고 하는 파일을 만들고 이것을 커널 소스 하위 디렉토리에 둔다.(/usr/src/linux) .gdbinit 파일에는 다음과 같은 네 가지 라인이 있다.
    • set remotebaud 115200
    • symbol-file vmlinux
    • target remote /dev/ttyS0
    • set output-radix 16

  5. append=gdb 라인을 lilo에 추가한다. 이것은 부트 로드로서 커널을 부팅할 때 사용될 커널을 선택한다.
    • image=/boot/bzImage-2.4.17
    • label=gdb2417
    • read-only
    • root=/dev/sda8
    • append="gdb gdbttyS=1 gdb-baud=115200 nmi_watchdog=0"

Listing 7은 개발 머신에 구현한 커널과 모듈을 테스트 머신으로 가져오는 스크립트 예제이다. 다음 아이템들을 수정해야 한다.

  • best@sfb: Userid와 머신 이름
  • /usr/src/linux-2.4.17: 커널 소스 트리의 디렉토리
  • bzImage-2.4.17: 테스트 머신 상에 부팅 될 커널의 이름
  • rcp and rsync: 커널이 구현된 머신 상에서 실행되어야 함.


Listing 7. 커널과 모듈을 테스트 머신으로 가져오는 스크립트
		set -xrcp best@sfb: /usr/src/linux-2.4.17/arch/i386/boot/bzImage /boot/bzImage-2.4.17rcp best@sfb:/usr/src/linux-2.4.17/System.map /boot/System.map-2.4.17rm -rf /lib/modules/2.4.17rsync -a best@sfb:/lib/modules/2.4.17 /lib/moduleschown -R root /lib/modules/2.4.17lilo

커널 소스 트리가 시작되는 디렉토리를 수정함으로서 개발 머신 상에서 gdb 프로그램을 시작할 준비가 되었다. 이 예제에서, 우리의 커널 소스 트리는 /usr/src/linux-2.4.17에 있다. gdb를 입력하여 프로그램을 시작한다.

모든 것이 작동한다면 테스트 머신은 부팅 프로세스 동안 중지된다. gdb 명령어 cont를 입력하여 부팅 프로세스를 계속 진행한다. 한 가지 문제는 null-modem 케이블이 그릇된 시리얼 포트에 연결될 수도 있다는 점이다. gdb가 시작하지 않으면 포트를 두 번째 시리얼로 전환하여 gdb를 시작한다.




위로


kgdb를 사용하여 커널 문제 디버깅하기

Listing 8은 jfs_mount.c 파일의 소스에서 수정되었던 코드이다. 무효 포인터 예외를 만들어서 109 라인에 세그멘테이션 오류를 만들었다.


Listing 8. 수정된 jfs_mount.c 코드
		int jfs_mount(struct super_block *sb){...int ptr; 			/* line 1 added */jFYI(1, ("\nMount JFS\n"));/ ** read/validate superblock* (initialize mount inode from the superblock)* /if ((rc = chkSuper(sb))) {		goto errout20;	}108 	ptr=0; 			/* line 2 added */109 	printk("%d\n",*ptr); 	/* line 3 added */

Listing 9는 파일 시스템에 대한 mount 명령어가 실행된 후에 gdb 예외를 디스플레이 하고 있다. kgdb에서 사용할 수 있는 여러 명령어들이 있다. 데이터 구조와 변수 값을 디스플레이 하고, 시스템의 모든 태스크들이 어떤 상태에 있는지를 보고, 이들이 수면하는 곳은 어디이며, CPU를 소비하고 있는 곳은 어디인지를 알 수 있다. Listing 9는 백 트레이스가 제공하는 정보를 보여준다. where 명령어는 백 트레이스를 수행하는데 사용된다. 코드에서 중지된 장소로 가기위해 실행되었던 호출을 보여준다.


Listing 9. gdb 예외와 백 트레이스
		mount -t jfs /dev/sdb /jfsProgram received signal SIGSEGV, Segmentation fault.jfs_mount (sb=0xf78a3800) at jfs_mount.c:109109 		printk("%d\n",*ptr);(gdb)where#0 jfs_mount (sb=0xf78a3800) at jfs_mount.c:109#1 0xc01a0dbb in jfs_read_super ... at super.c:280#2 0xc0149ff5 in get_sb_bdev ... at super.c:620#3 0xc014a89f in do_kern_mount ... at super.c:849#4 0xc0160e66 in do_add_mount ... at namespace.c:569#5 0xc01610f4 in do_mount ... at namespace.c:683#6 0xc01611ea in sys_mount ... at namespace.c:716#7 0xc01074a7 in system_call () at af_packet.c:1891#8 0x0 in ?? ()(gdb)

다음 섹션에서는 디버거 설정 없이 같은 JFS 세그멘테이션 오류 문제에 대해 살펴보도록 하겠다. 비-kgdb 환경에서 Listing 8의 코드를 실행할 때 커널이 만들어내는 Oops를 사용한다.




위로


Oops 분석

Oops (또는 panic) 메시지에는 CPU 레지스터 같은 시스템 오류 상세들이 포함되어 있다. 리눅스에서, 시스템 충돌을 디버깅하는 전통적인 방법은 Oops 메시지의 상세를 분석하는 것이었다. 상세를 포착하면 메시지는 ksymoops 유틸리티로 전달된다. 이것은 코드를 명령어로 변환하고 스택 값을 커널 심볼로 변환한다. 많은 경우에, 오류의 원인을 파악할 수 있는 충분한 정보가 된다. Oops 메시지에는 코어 파일이 포함되어 있지 않다.

시스템이 Oops 메시지를 만들어냈다고 가정해보자. 코드의 작성자로서, 문제를 해결하고 무엇이 Oops 메시지의 원인이 되었는지 파악하고 싶을 것이다. 아니면 Oops 메시지를 디스플레이 했던 코드의 개발자에게 문제 정보를 알려주고 문제 해결을 받게 될 것이다. Oops 메시지는 방정식의 한 부분이지만 ksyoops 프로그램을 통해서 실행하지 않는 한 도움이 되지 않는다. 아래 그림은 Oops 메시지를 포맷팅 하는 과정이다.


Oops 메시지 포맷팅하기
Formatting an Oops message

ksymoops가 필요로 하는 여러 가지 아이템들이 있다. Oops 메시지 아웃풋, 실행중인 커널의 System.map 파일, /proc/ksyms, vmlinux, /proc/modules 등이 필요하다. 커널 소스 /usr/src/linux/Documentation/oops-tracing. txt 또는 ksymoops 매뉴얼 페이지에는 ksymoops를 사용하는 방법이 자세히 나와있다. Ksymoops는 코드 섹션을 분해하고, 오류 명령어를 가리키고, 코드가 호출되었던 방법을 보여주는 트레이스 섹션을 디스플레이 한다.

우선, Oops 메시지를 파일에 넣어 ksymoops 유틸리티를 통해 이를 실행한다. Listing 10은 mount에 의해 생성된 JFS 파일 시스템에 대한 Oops를 보여준다. JFS의 mount 코드에 추가되었던 Listing 8의 세 개의 라인에서 야기된 문제가 포함되어 있다.


Listing 10. ksymoops에 의해 처리된 후의 Oops
		ksymoops 2.4.0 on i686 2.4.17. Options used... 15:59:37 sfb1 kernel: Unable to handle kernel NULL pointer dereference atvirtual address 0000000... 15:59:37 sfb1 kernel: c01588fc... 15:59:37 sfb1 kernel: *pde = 0000000... 15:59:37 sfb1 kernel: Oops: 0000... 15:59:37 sfb1 kernel: CPU:    0... 15:59:37 sfb1 kernel: EIP:    0010:[jfs_mount+60/704]... 15:59:37 sfb1 kernel: Call Trace: [jfs_read_super+287/688] [get_sb_bdev+563/736] [do_kern_mount+189/336] [do_add_mount+35/208][do_page_fault+0/1264]... 15:59:37 sfb1 kernel: Call Trace: [<c0155d4f>]...... 15:59:37 sfb1 kernel: [<c0106e04 ...... 15:59:37 sfb1 kernel: Code: 8b 2d 00 00 00 00 55 ...>>EIP; c01588fc <jfs_mount+3c/2c0> <=====...Trace; c0106cf3 <system_call+33/40>Code; c01588fc <jfs_mount+3c/2c0>00000000 <_EIP>:Code; c01588fc <jfs_mount+3c/2c0>  <=====   0: 8b 2d 00 00 00 00 	mov 	0x0,%ebp    <=====Code; c0158902 <jfs_mount+42/2c0>   6:  55 			push 	%ebp

다음에는, jfs_mount에서 문제를 일으킨 라인이 어떤 것인지를 파악해야 한다. Oops 메시지를 보면 문제는 offset 3c 에 있는 명령어에서 비롯되었다는 것을 알 수 있다. 이것을 다루는 한 가지 방법은 jfs_mount.o 파일에 objdump 유틸리티를 사용하여 offset 3c를 보는 것이다. Objdump는 모듈 함수를 분해하고 어떤 어셈블러 명령어가 C 소스 코드에 의해 만들어 졌는지를 보는데 사용된다. Listing 11은 objdump에서 볼 수 있는 것을 보여주고 우리는 jfs_mount 에 대한 C 코드를 보고 109 라인에 의해 무효가 발생했다는 것을 볼 수 있다. Offset 3c는 Oops 메시지가 문제의 원인을 규명했던 위치이기 때문에 중요하다.


Listing 11. jfs_mount의 어셈블러 리스팅
		109	printk("%d\n",*ptr);objdump jfs_mount.ojfs_mount.o: 	file format elf32-i386Disassembly of section .text:00000000 <jfs_mount>:   0:55 			push %ebp  ...  2c:	e8 cf 03 00 00	   call	   400 <chkSuper>  31:	89 c3 	  	    	mov     %eax,%ebx  33:	58		    	pop     %eax  34:	85 db 	  	    	test 	%ebx,%ebx  36:	0f 85 55 02 00 00 jne 	291 <jfs_mount+0x291>  3c:	8b 2d 00 00 00 00 mov 	0x0,%ebp << problem line above  42:	55			push 	%ebp




위로


kdb

Linux kernel debugger (kdb)는 리눅스 커널용 패치이고, 시스템이 실행 중일 때 커널 메모리와 데이터 구조를 검사하는 방식을 제공한다. kdb는 두 개의 머신까지는 요구하지는 않지만 kgdb 처럼 소스 레벨 디버깅을 수행할 수 없다. 추가 명령어를 사용하여 중요한 시스템 데이터 구조를 포맷팅 및 디스플레이 한다. 다음 과 같은 명령어 세트를 사용해서 커널 작동을 제어할 수 있다.

  • Single-stepping a processor
  • Stopping upon execution of a specific instruction
  • Stopping upon access (or modification) of a specific virtual memory location
  • Stopping upon access to a register in the input-output address space
  • Stack back trace for the current active task as well as for all other tasks (by process ID)
  • Instruction disassembly

메모리 오버런 추적하기

수 천 개의 호출 뒤에 발생하는 할당 오버런 같은 상황에 직면하기 원치 않을 것이다.

우리 팀은 이상한 메모리 오염 문제를 파악하느라 오랜 시간을 보냈다. 이 애플리케이션은 우리의 개발 워크스테이션에서는 작동했지만 새로운 워크스테이션에서 malloc()에 2백만 개의 호출을 한 후에 중지되었다. 실제 문제는 백만 호출과 관련한 오버런이였다. 새로운 시스템은 malloc() 영역이 다르게 레이아웃 되었기 때문에 문제가 생긴 것이다. 따라서 문제 메모리를 다른 장소에 배치했고 오버런을 수행했을 때와는 다른 것을 파괴했다.

우리는 이 문제를 다양한 기술들을 적용하여 해결했다. 디버거를 사용하기도 했고 소스 코드에 트레이싱을 추가하기도 했다. 이와 동시에 메모리 디버깅 툴을 찾기 시작했고 이것이 이러한 유형의 문제를 더욱 빠르고 효율적으로 해결한다는 것을 발견했다. 새로운 프로젝트를 시작할 때 내가 가장 먼저 하는 일은 MEMWATCH와 YAMD를 실행하여 이들이 메모리 관리 문제를 지적할 수 있는지를 확인하는 것이다.

메모리 누수는 애플리케이션에서는 일반적인 문제지만 이 글에서 설명한 툴을 사용하여 문제를 해결할 수 있다.




위로


Scenario 4: 키 시퀀스로 추적하기

키보드가 여전히 작동하고 있고 리눅스 상에서 행(hang)이 걸렸다면 다음 방식을 사용하여 행 문제를 해결하라. 다음 단계들을 따라가면 매직 키 시퀀스를 사용하여 현재 실행중인 프로세스와 모든 프로세스들에 대한 역추적 내용을 디스플레이 할 수 있다.

  1. 실행중인 커널에는 CONFIG_MAGIC_SYS-REQ가 빌트인 되어야 한다. 또한 텍스트 모드에 있어야 한다. CLTR+ALT+F1를 사용하면 텍스트 모드가 되고 CLTR+ALT+F7은 X Windows로 돌아간다.
  2. 텍스트 모드에 있을 때, <ALT+ScrollLock>을 누른 다음 <Ctrl+ScrollLock>을 누른다. 이 키스트로크는 각각 현재 실행 중인 프로세스와 모든 프로세스들에 대한 스택 트레이스를 제공한다.
  3. /var/log/messages를 검사해 보라. 모든 것이 올바르게 설정되었다면 시스템은 상징적인 커널 주소로 변환되었을 것이다. 백 트레이스가 /var/log/messages 파일에 작성될 것이다.




위로


결론

리눅스 상에서 프로그램을 디버깅하는데 사용할 수 있는 많은 툴이 있다. 이 툴들은 많은 코딩 문제를 해결하는데 도움이 된다. 메모리 누수 위치, 오버런 등을 보여주는 툴은 메모리 관리 문제도 해결할 수 있고 MEMWATCH와 YAMD도 도움이 된다.

리눅스 커널 패치를 사용하여 gdb를 리눅스 커널 상에 작동시키는 것도 문제 해결에 도움이 된다. 또한 strace 유틸리티는 시스템 호출 동안 파일시스템 유틸리티에 어떤 오류가 생겼는지 파악하는데 도움이 된다. 다음 시간에는 이 글에 소개된 툴을 사용하여 버그를 없애는 방법을 설명하겠다.

기사의 원문보기




위로


참고자료




위로


필자소개

Steve Best는 Linux Technology Center(Austin, Texas)에서 일하고 있다. 현재 Journaled File System (JFS) 작업을 하고 있다. 운영 체계 개발과 파일 시스템, 국제화, 보안 분야에서 많은 작업중이다.

by 성우 | 2007/12/11 20:30 | Linux | 트랙백 | 덧글(0)

[Gentoo] SVN - Subversion 사용하기

[Gentoo] Subversion 사용법 정리

Subversion버전 관리 시스템입니다.

소스 코드는 물론 바이너리 파일 등의

여러가지 형식의 파일을 관리 할 수 있습니다.


버전 관리 시스템을 이용하면 수정, 추가, 삭제등의 기록등의

모든 기록이 남으므로 변경사항을 추적하기 쉽고

잘못 수정했더라도 다시 이전 상태로 되돌리기가 쉽습니다.

CVS의 단점들을 개선한 버전 관리 시스템인 Subversion

사용법을 간단하게 정리해 보았습니다.


Subversion 설치
$ emerge subversion


Editor 설정
SVN_EDITOR=/usr/bin/vimexport SVN_EDITOR
.profile 또는 .bash_profile안에 추가


저장소 생성하기
$ mkdir /home/svn/$ cd /home/svn/$ svnadmin create --fs-type fsfs dirnameor$ svnadmin create --fs-type bdb dirname


trunk, branches, tags 기본 디렉토리 생성하기
$ svn mkdir svn+ssh://user@{IP 또는 도메인}/home/svn/dirname/trunk$ svn mkdir svn+ssh://user@{IP 또는 도메인}/home/svn/dirname/branches$ svn mkdir svn+ssh://user@{IP 또는 도메인}/home/svn/dirname/tags


import
$ mkdir tempdir$ cd tempdir$ touch temp.c$ cd ..$ svn import tempdir svn+ssh://user@{IP 또는 도메인}/home/svn/dirname/trunk


checkout - 저장소의 소스트리를 로컬에 저장.
$ svn checkout svn+ssh://user@{IP 또는 도메인}/home/svn/dirname dirname or$ svn co svn+ssh://user@{IP 또는 도메인}/home/svn/dirname dirname 


commit - 로컬에서 변경한 파일 내역을 저장소에 저장.
$ svn commit or $ svn ci 


update - 로컬의 파일내역을 저장소의 최신 revision으로 업데이트.
$ svn update or $ svn up 


status - 현재 상태 보기
$ svn status or $ svn st 
A : 추가. 추가되었지만 아직 커밋되지 않음.
C : 충돌. 작업본의 변경 내용과 저장소의 변경 내용이 겹친 경우.
D : 삭제. 이 상태에서 커밋하면 저장소의 파일도 삭제됨.
M : 수정. 커밋하면 수정된 내용이 반영됨
! : 유실.


log - 커밋 로그 보기
$ svn log 


add/delete/copy/mkdir/move
$ svn add newfilename$ svn delete filename $ svn mv filename1 filename2$ svn copy filename1 filename2
svn commit 하기 전까지는 변경내역이 저장되지 않음


diff - 변경내역 보기
$ svn diff filename


dump - 저장소 백업
$ cd /home/svn$ svnadmin dump dirname > dirname.dump


load - 저장소 복구
$ cd /home/svn$ svnadmin create newdirname

by 성우 | 2007/12/11 20:29 | Gentoo | 트랙백 | 덧글(0)

논문 주석달기

1. 주석 번호

본문에 붙이는 주석 번호는 설명하려는 용어나 문장의 끝 오른쪽 위에 기입하는 것을 원칙으로 한다. 숫자 표시는 아라비아 숫자로 적는데, 보통 '1' 이나 '1)'의 형식을 많이 사용한다. 워드프로세서에서는 이 형식 가운데 하나를 선택하게 되어 있다.

 

2. 주석란의 위치

옛 논문에서는 논문 전체의 말미나 장의 끝에 몰아서 기록하는 미주 방식을 사용하였지만 근래에 와서는 각 페이지 아래 부분에 몰아서 기입하는 각주 방식을 많이 취하고 있다. 이 때 주의할 점은 주석란이 지나치게 많은 자리를 잡거나 복잡하다는 인상을 주어서는 안된다는 것이다. 그러기 위해서 한가지 사실을 인용하면서 많은 참고 자료를 소개할 필요가 있을 때에 한하여 복식 주석의 방식을 취하는 것이 좋다. 즉 하나의 주석 번호 아래 여러 개의 문헌을 계속 기록하기 때문에 주석란의 자리를 절약하게 되기 때문이다. 이 때에는 문헌과 문헌 사이에 '쌍반점(;)'만 찍어두면 된다.

 

3. 완전주석과 약식주석

완전 주석은 어떤 문헌이 처음 인용되었을 때 그 문헌을 식별하는데 충분한 여러 사항을 빼지 않고 기록하는 방법이다. 약식 주석은 일단 완전 주석으로 소개된 문헌을 반복해서 주석할 때 일정한 부호나 생략된 방식으로 주석하는 것을 말한다.

 

(1) 완전 주석

 

(가) 단행본의 경우

 

1) 저자명

-동양 사람인 경우 성-명의 순서로 적는다. 영문일 경우 이름을 먼저 쓰고 성을 나중에 쓴다. 자기 저서인 경우 '졸저'라고 쓰는 경우도 있다.

-공저인 경우 대표적, 최초 저자명만 쓰고 '외'라고 덧붙인다.(세명 이하일 때에는 저자명을 다 쓰기도 한다.)

-편집자는 성명 뒤에 '편' 혹은 'ed.' 를 붙이고, 번역자는 성명 뒤에 '역' 혹은 'trans.'를 붙인다.

-학술단체, 협회, 정부 기관 등의 법인이 저자인 경우 그 법인명이 저자란에 기입된다.

 

2) 서명

-저자명 다음에 쉼표(,)를 찍고 계속해서 서명을 적되 내제명과 표지명이 다를 때에는 내제명을 적는 것이 원칙이다. 필자명을 알 수 없는 경우, 또는 백과사전류 등은 저자명을 생략하고 바로 서명부터 쓴다.

-국문 서명인 경우에는 『』 표시 를 달고, 영문 서명인 경우에는 이탤릭체를 사용한다.(인쇄시가 아닌 타자시일 경우 밑줄을 친다.)

 

3) 출판 사항

-서명 뒤에 괄호'()'를 치고 그 안에 발행판수, 발행지, 출판사명, 출판연월의 네 항목을 넣는다. 국문의 경우 판수나 발행지를 쓰지 않기 때문에 굳이 괄호를 치지 않아도 된다. 판수 다음에는 ';' 을, 발행지 다음에는 ':' 을, 출판사명 다음에는 ',' 을 기입한다. --ex)  (개정판; 서울 : 을유문화사, 1999) -- 개정판이 아닌 경우에는 판수를 쓰지 않는다. 발행지는 그 서적의 발행 출판사가 있는 도시명을 기재하면 된다. 국문일 경우 생략하는 경우가 많지만, 외국 서적의 경우에는 반드시 넣어야 한다. 외국의 경우는 동일명의 출판사라 하더라도 그 출판사가 소재하는 도시가 다른 경우가 많기 때문이다. 출판연월은 보통 연도만 아라비아 숫자로 기입하며, 필요에 따라 월 단위까지 기입힌다.

 

4) 페이지 명시

-인용, 참고한 내용이 실린 페이지를 명시해야 한다. 페이지 표시에 있어 한 페이지만 표시할 때는 'p.' 라고 쓰고, 두 페이지 이상 걸쳐 인용했을 때는 'pp.' 라고 쓰고 페이지 번호를 숫자로 쓴다. 또 pp. 35ff. 는 35페이지 이하를, pp. 20~30 passim 은 20페이지에서 30페이지 사이의 여기저기에서 인용했음을 뜻한다.(하지만 여기서 passim 같은 경우는 쓰지 않는 편이 좋다. 주석을 다는 목적은 어디서 어느 부분을 인용했는지 정확히 알리기 위함이기 때문이다.)

 

이상의 것을 보기로 보이면 다음과 같다.

1) 조윤제, 『한국시가사강』(정정판; 서울: 을유문화사, 1961). p. 120.

2) 장덕순 외, 『구비문학개설』, 일조각, 1960. pp. 3~5.

3) 졸저, 『신고국어학사』, 학연사, 1983. pp. 6ff.

4) Barry Ulanov, A History of Jazz in America(New York: Viking press, 1952). p. 50.

5) Rene Wellek and Austin Warren, Theory of Literature(New York: Harcourt, 1956). p. 50.

 

 

(나) 논문의 경우

 

1) 저자명

-단행본의 저자명 기입 요령과 같다. 자기 논문을 인용했을 경우 '졸고'라고 쓰는 경우도 있다.

 

2) 논제명

-서명과는 달리 인용 부호("")로 묶여야 한다.

 

3) 잡지명, 논문집명

- 인용된 논문이 실려 있는 잡지명 또는 논문집명을 완전하게 기입한다. 저서와 마찬가지로 국문인 경우 『』안에 잡지명을 넣는다. 영어인 경우 이탤릭체로 표시한다.

 

4) 권수 및 호수

-잡지명, 논문집명 뒤에 제 o권 제 o호로 표시하거나 권수는 로마숫자로, 호수는 아라비아 숫자로 표시한다.

 

5) 출판 연월일

-출판 연월까지만 쓰고 보통 일자는 생략한다. 계간일 경우에는 계절명까지만 표시한다.

이상 잡지명, 논문집명, 권수, 호수, 출판 연월일은 괄호 속에 묶여야 한다.

 

6) 페이지 표시 - 단행본의 경우와 같다.

 

이상의 것을 보기로 보이면 다음과 같다.

1) 김길동, "백운소설연구"(『서강인문논총』8집, 1964. 11.)

2) 박형택, "흥부전의 현실성에 관한 연구"(『문화비평』제1권 제4호, 1969. 겨울). p. 815.

3) Walter Kirchner, "The Life of Catherine I of Russia"(The American Historial Review Ⅱ, January 1946). p. 254.

 

(다) 기타 자료

 

1) 백과사전 및 참고 자료 기사

-필자명이 있는 경우:  남풍현, "이두", 『한국민족문화 대백과사전』(서울: 한국정신문화연구원, 1991).

-필자명이 없는 경우: "샤머니즘", 『동아원색세계대백과사전』(서울: 동아출판사, 1982).

 

2) 신문 기사

-기사:  "몽골 대초원에 뻗어나가는 한국인의 기상",『한겨레신문』, 2002. 3. 15: 5.

-사설:  "정치부터 대개혁을", 사설, 『동아일보』, 1998. 11. 11: 3.

* 맨 뒤의 숫자는 면수를 말한다. 기사와 사설을 작성한 사람의 이름이 있을 경우 앞에 써 넣는다.

 

(2) 약식 주석

 

대표적으로 사용되는 약식 주석들을 제시하면 다음과 같다.

 

Ibid. : 라틴어 ibidem 의 약자로 상게서, 상게논문의 뜻이다. 바로 앞의 주에서 인용한 서적이나 노문을 다시 반복하여 사용할 때 쓴다. Ibid. 대신에 '위 책, 위 글' 등이라 쓰기도 한다.

 

<보기>

1) 양주동, 『여요전주』(서울: 을유문화사, 1959). p. 113.

2) 위의 책, p. 165.

3) Crichton, Michael, The Andromeda Strain(New York: Knopf, 1969). p. 29.

4) Ibid., p. 36.

 

Op. cit. : Opere citato 의 약자로 전게서, 전게논문의 뜻이다. 반복 인용하고자 하는 주석문 다음에 다른 문헌에 관한 주석이 삽입되어 있거나, 한 페이지 또는 몇 페이지 앞에 완전 주석문이 소개되었을 경우 저자명 다음에 이 부호를 쓴다. 곧 바로 위에서가 아니라 그 앞의 어디에선가 일단 인용했던 문헌을 다시 인용하는 경우 주를 완전히 작성하지 않고 저자명 또는 필자명 다음에 이 부호를 적고 해당 페이지를 적는다. 이 부호 대신 '앞 책, 앞 글' 등이라 쓰기도 한다.

 

<보기>

1) 백낙청 역, "리얼리즘과 현대소설"(『창작과 비평』제2권 제3호, 1967. 가을). p. 124.

2) 김동인, 『춘원 연구』(서울: 신구문화사, 1958). p. 21.

3) 백낙청 역, Op. cit., p. 130.

4) 김동인, 앞 책, p. 25.

 

<참고 문헌 쓰기>

 

논문을 쓰는 데 참고했던 모든 문헌은 논문 뒤에 참고 문헌란에서 다시 정리하여 밝혀야 한다. 기재 요령은 다음과 같다.

첫째, 동양서, 서양서로 구분한다.

둘째, 저서나 논문으로 구분한다.

동양서는 다시 국내서적과 외국서적으로 구분하여 국내서적부터 기재하되 저자명의 가나다순으로 배열하고, 서양서는 알파벳 순으로 배열한다.

저서는 다시 자료와 연구서로 구분하여 자료부터 기재하는 것이 좋다.

 

1) 저서의 경우

저자명, 서명, 발행지, 출판사, 출판 연월순으로 기재하는 것은 주석의 경우와 같다. 다만 출판 사항을 묶어 놓은 괄호를 없애고, 쉼표 대신 마침표를 하는 것이 원칙이며, 참고한 페이지의 명시를 하지 않는 점이 다르다. 또한 영문 저자명을 성-이름 순으로 쓰고 그 사이에 쉼표를 찍는다. 참고 문헌에서 저자명을 성-이름 순으로 쓰는 이유는 참고문헌에서는 여러 문헌들을 제시하여야 하는데 이 때 여러 문헌들을 성의 알파벳 순으로 정렬해야 하기 때문이다.

 

<보기>

A형:  이능화. 『조선여속고』. 서울: 학문각. 1968.

B형:  이능화(1968). 『조선여속고』. 서울: 학문각.

 

2) 논문의 경우

<보기>

A형:  김일렬. "홍길동전의 불통일성과 통일성". 『어문학』27. 1972.

B형:  김일렬(1972). "홍길동전의 불통일성과 통일성". 『어문학』27.

 

3) 번역서의 경우

<보기>

A형:  Wellek, Rene and Austin Warren. Theory of Literature. New York: Harcour, 1956(백철, 김병철 공역, 문학의 이론, 서울: 신구문화사, 1959).

B형: Wellek, Rene and Austin Warren(1956). Theory of Literature. New York: Harcour, 1956(백철, 김병철 공역, 문학의 이론, 서울: 신구문화사, 1959).

by 성우 | 2007/12/07 17:07 | ETC | 트랙백 | 덧글(0)

임베디드 공부

임베디드리눅스를 공부하고자 하는분들이 가장 먼저 해야 할일

임베디드 리눅스를 해야 겠다는 생각만 가지고 있다가 이젠 시작해야지 라는 생각을 하셨다면 우선 숨을 크게 들이키시고 내벹는 행동을 반복하신후 임베디드 리눅스를 단번에 점령하겠다는 생각을 버린다. ^^; 정말 임베디드 리눅스는 한번 들어가 보면 끝이 없어서 한두달 만에 끝장을 보겠다는 생각을 가지셨다면 당장 그만 둘것! 당장 그만 두지 않더라도 조만간 그만 두게 될것이다. 왜? 한두달안에는 끝나지 않기 때문이다. 혹시 시작하는 시점의 여러분의 실력이 리눅스의 커널을 이미 분석이 끝난 실력이라면... 더구나 여러 아키텍쳐에 포팅까지 한 실력이라면 정말 한두달 사이에 끝날수 있을 것이다. 굳이 임베디드 리눅스를 따로 할 필요가 없는 실력자이므로...



·리눅스를 설치 해 본적도 없는 초 울트라 초차라면?


당장 리눅스 배포판을 구한다. PC에 리눅스를 설치한다.



·리눅스 명령에 익숙하지 않다면


우선 리눅스에 관련된 책을 한권 산다. 그리고 한번 쭈욱 읽어 본다. http://kldp.org 싸이트에 들락 날락 거리면서 http://man.kldp.org 도 참고 하면서.... 단 주의 할것은 암기력에 자신 있는 분을 제외하고는 명령을 굳이 외우려고 하지 말것 자주 사용하는 명령은 손가락이 외운다. 굳이 사용도 하지 않는 명령을 외우려고 스트레스 쌓이지 말고... 더구나 리눅스 명령어는 정말 정말 너무 많다.



·리눅스 디렉토리 구조를 모른다면

최상위 디렉토리를 외운다. 몇 개 안되므로... 그리고 서점에 간다... 리눅스 관련 책들을 보면서 디렉토리에 관련된 내용을 중점적으로 읽는다. 읽어야 하는 내용은 디렉토리 구현에 대한 것이 아니라.. 각 디렉토리를 어떻게 구분해 놓았는가를 설명한 내용들을 읽는다. 대부분의 책들이 조금씩 만 소개하므로 굳이 책들을 사려고 하지 말 고 서점에서 여러권을 설렵하는 것이 났다. 그리고 이것저것 패케지들을 손수 설치해 본다. 그러면 저절로 깨닫게 될것이다



·쉘 스크립트를 모른다면


리눅스를 하면서 쉘 스크립트를 모르면 고생문이 훤하다 사실 내가 그렇다. 그러나 쉘 스크립트를 아주 잘 할 필요는 없다. 쉘 스크립트를 읽을 정도면 된다. 쉘 스크립트를 작성할 필요가 있다면 스크립트에 대한 강좌를 인터넷에서 보고 하거나 다른 스크립트를 보면서 하면 되니까....



·유닉스 운영 체제를 모른다면

유닉스 운영체제에 대한 최대한 쉽게 설명한 책을 골라서 그냥 소설 읽는 셈 치고 읽어 본다. (참고) 쉽게 설명한 책들의 특징은
1. 그림이 많다.
2. 글씨가 크다.
3. 가격이 싸다.
4. 많은 사람들이 본다.
5. 두께가 얇다



·C 언어를 모른다면

이건 사람 얼굴에 입이 없는 셈이다. 밥 어떻게 먹으려나... 곧 굶어 죽게 될것이다. 바로 C의 기본적인 설명에 대한 책을 독파한다. 이건 정성 들여서 독파해야 한다. 임베디드 리눅스는 거의 C로 시작해서 C로 끝난다. 가끔 C++도 있지만....



·리눅스에서 도는 어플리케이션을 작성한 적이 없다.

http://users.unitel.co.kr/~sangeun5/linux/lpg.html 에 가본다. 정말 도움이 될것이다



·make 사용법을 모른다면

make [강좌- http://kldp.org/KoreanDoc/html/gcc_and_make/gcc_and_make.html] 사용법을 아주 잘 알 필요는 없다 그러나 기본적인 사용법은 알고 있어야 한다. 아주 복잡한 사용법은 이미 기술된것을 이용하는 것으로 충분하다



·리눅스가 동작하기 위한 최소한의 기본 구성에 대해 아는 것이 없다?

부팅 디스크를 만들어 본다. 여기서 주의 할것! 대부분의 분들이 켈프에 있는 부팅 디스크 만들기를 따라만 하시는데 이건 별로 효과가 없다. 부팅 디스크를 만드는 목적은 리눅스가 동작하기 위한 최소한의 기본 구성을 알고자 하는데 목적이 있다. 또한 로더의 필요성 커널과 루트 이미지의 분리와 램디스크에서 동작하는 것에 대해서 또 커널이 동작한 후에 실행되는 최소한의 진행과정을 이해하기 위한 것이다. 이를 알고자 하는데 목적을 두어야지 만드는데에만 열중하면 안된다. 또한 다른 부팅 디스크 이미지를 이용하여 그 내용을 살표보고 공부하여야 한다.



·커널 컴파일을 해 본적이 없다면?

임베디드 리눅스는 커널을 가지고 놀아야 한다. 물론 안하고 하는 방법은 있다. 그러나 대부분의 임베디드 리눅스에서 커널 컴파일과 환경 설정은 거의 필수이다. 임베디드상에서 리눅스의 커널 환경을 설정하고 컴파일하는 방식과 우리가 일반적으로 다루는 PC의 커널을 다루는 방법은 거의 대부분이 같다. PC상에서 커널을 자유자재로 가지고 논다는 것은 "임베디드상에서도 자유롭다"는 것을 의미한다



·커널의 구조를 모른다면

Uinx kernel 완전분석으로 가는길 [http://haninara.xcool.net/forStudy/download.php]이라는 책을 한번 볼것. 약간은 예전의 커널에 대한 이야기가 나오지만 커널이 어떻게 동작하는 지를 알수 있다



·어셈블러를 모른다면?

임베디드 리눅스를 함에 있어서 어셈블러를 몰라도 가능한 영역은 있다. 그러나 많은 부분에서 부딪히게 된다. 고로 어셈블러는 필요 충분 조건이다. 어셈블러라는 것이 너무도 많은 종류가 존재하므로 모두 다 익히기는 어렵지만 자신이 사용하려는 MCU의 어셈블러는 익혀야 한다. 일단 PC를 이용한 임베디드에 대해서 익히려면 PC의 어셈블러는 알아야 한다. 자유 자재로 구사할 정도로 익힐 필요는 없다. 다른 쏘스의 명령을 이해하고 자신이 필요로 하는 기능을 추가하거나 수정 할수 있을 정도면 된다



·윗글에서 제안한 리눅스의 개발과 관련한 기본을 다진후 진행하는 방법

임베디드 리눅스를 할때 많은 분들이 평가 보드를 이용한 학습을 준비한다. 그러나 이런 분들은 대부분 좌절한다. 왜? 기본기가 없는 분들이 평가 보드에 포팅하겠다고 덤비기 때문에 좌절하는 것이다. 포팅이 그리 쉬운 것은 아니다. 일단 PC에서 내공을 쌓은 후 접근하는 것이 수월하다. 임베디드 리눅스라고 PC의 리눅스와 다른 점은 거의 없다. 단지 아키텍쳐만이 다를 뿐이며 이 부분은 전체에 3%도 되지 않는다. PC에서 리눅스의 내부를 자유 자재로 드나드는 분이면 임베디드 리눅스에 접근은 너무도 쉽다. 사실 몇가지 사항을 제외하고는 임베디드 리눅스보다 PC 시스템이 더 복잡하다. 가격도 비교해보면 임베디드 장비가 더 싸다.. ^^; 자 이젠 PC에서 임베디드 리눅스를 하기 위한 접근 방법을 알아 보자. 그리고 공부하기 위하여 평가 보드를 구입하기에는 개인이 구입하는 가격이 너무 고가이다. 컴퓨터를 또하나 사는 셈인데...이게 말처럼 쉽겠는가? 고액 연봉자라면 모를까....



·디바이스 드라이버를 정복하라!!!

임베디드 시스템을 개발하는 과정에서 하드웨어쪽을 제외한 나머지 소프트웨어 측면에서 개발 비중은 로더 및 하드웨어 테스트 프로그램 10% 커널 포팅 10% 디바이스 드라이버 40% 임베디드 어플리케이션 40% 이렇다. 물론 내 개인적인 생각이므로 상황에 따라 다르겠지만 .... 그만큼 디바이스 드라이버는 중요하다. 디바이스 드라이버를 개발 한다고 평가보드를 구매 해야 하는가? 이에 대답은 "아니오" 이다. PC는 매우 복잡한 시스템이다. 임베디드에 사용되는 대부분의 기능이 PC에는 있다. 그러므로 PC에 도는 하드웨어에 관련된 디바이스 드라이버를 스스로 만들 능력이 된다면 임베디드용 디바이스 드라이버를 만들 능력은 충분해 진다. 일단 돈 안드는 PC부터 정복해라. PC가 없다면 모를까 ^^; 자 그럼 디바이스 드라이버는 어떻게 정복하는 것이 좋을까? 한번 알아보자..



·어떤 책이 좋을까?

디바이스 드라이버를 만드는 방법에 대한 책으로 대표적인것에는 오렐리의 책이 있다. 그러나 이책을 초보자가 보기에는 너무 어렵다. 그렇다고 마땅한 다른 책이 있는 것도 아니다. 고로 선택권이 없으므로 이 책을 여러번 읽어 본다. 완벽하게 이해하려고는 하지 말기를 부탁한다. 여러번 읽어 보면 어렴풋이 무슨 내용인지 이해하는 시점이 있을 것이다



·디바이스 드라이버 프로그램을 직접 해본다.

우선 오렐리의 책에 소개된 싸이트에 가서 쏘스를 가져 온다. 그리고 쏘스를 이해하려고 노력한다. 또한 KELP의 내가 쓰고 있는 디바이스 드라이버의 강좌를 계속 지켜 보거나 현재 진행되고 있는 박철님이 진행하고 있는 목요 세미나에 참가한다. 아니면 웹을 뒤지면 의외로 디바이스 드라이버 강좌를 하는 싸이트가 꽤 된다. 싸이트 이름을 내가 일일이 외우기는 힘들지만 ... ^^; ( 천재는 건망증이 심하다고들 한다. )



·프린터 포트를 이용한 캐랙터 디바이스를 만든다

대부분의 임베디드 장비에서 사용되는 디바이스는 캐랙터 디바이스로 충분하다. 고로 캐랙터 디바이스를 안다는 것은 임베디드용 디바이스 드라이버의 절반에 해당하는 내용을 안다는 의미도 된다



·자신이 사용하는 커널 버전이외의 내용은 과감하게 삭제한다.

현재 임베디드용 커널은 2.2대를 근거로 사용한다. 2.4대는 최근에 나왔으므로 아직은 적용중이다. 임베디드용 커널은 버전이 낮다. 또 2.0 대 이전 버전은 약간 적용 방식이 다른 것으로 기억한다. 이를 위해서 오렐리 책에서는 이런 저런 내용을 기술하고 있는데 실전에 사용되는 임베디드 리눅스는 사실 커널을 여러가지로 사용하겠끔 굳이 설계하지 않아도 된다. 즉 커널 버전을 덜 타는 것이다. 범용적인 PC용 디바이스 드라이버를 작성할때나 고려할 내용이다. 그러므로 여러분은 괜히 쏘스를 어지럽히는 커널의 버전 관리 에 대한 내용은 과감하게 제거하고 진행하는 것이 수명 연장에 지름길이 된다



·네트웍크용 디바이스 드라이버는 공부해라

임베디드 장비에 리눅스를 사용하는 가장 큰 목적 중에 하나가 네트워크 스택을 이용하기 위한 것이다. 리눅스 자체가 덩치가 크므로 조그마한 임베디드 장비에는 아예 탑재하지 않는다. 채산성이 전혀 맞지 않기 때문이다. 더구나 리눅스의 대부분의 어플리케이션이 네트워크에 연관되어 있다. 고로 네트워크 디바이스 드라이버는 공부해야 한다.



·기존에 디바이스 드라이버를 한번쯤 스스로 재 작성해 보라.

계속 말하는 것이지만 PC는 매우 복잡한 시스템이다. 고로 PC의 디바이스 드라이버를 구현 할수 있다는 것은 임베디드용 디바이스 드라이버를 구현 할 수 있는 능력이 된다는 것과 동일한 내용이다. 여기서 주의 할것은 PC에서 구현된 디바이스 드라이버들은 매우 안정된 상태이다. 여러분이 이렇게 완벽하게 안정된 디바이스 드라이버를 만들 수는 없다. 왜? 초짜이므로.... 똑같이 안정된 디바이스 드라이버를 작성할수 있다면 바로 리눅스의 개발에 앞장 서 주시길 부탁한다. 보통 많은 분들이 PC용 디바이스 드라이버를 재 작성할때 시리얼 포트용 디바이스 드라이버 부터 하는데 제발 시리얼 포트 부터 하지 말것... PC의 리눅스 상에서 시리얼은 정말 복잡하다. 보통 임베디드의 시리얼과는 상대가 되지 않는다. 터미날을 지원하는 기능과 가상 터미날과 연계 되어 있기 때문이다. 고로 차라리 프린터 포트나 마우스 같은 디바이스 드라이버 부터 만들어 가라... 어쩌면 랜카드용 디바이스 드라이버가 더 쉬울지도 모른다. 다시 당부 드리지만 시리얼 포트 부터 접근하지 말것....



·커널을 이해하라....

디바이스 드라이버를 공부하다보면 많은 부분들이 커널과 연계되어 있음을 알게 된다. 그러므로 디바이스 드라이버에 대해서 공부가 끝났다면 커널의 40%쯤은 이해 했다고 볼 수도 있겠다. 커널을 공부함에 있어서 구분해야 할것이 있다. 하나는 아키텍쳐 의존적인 부분과 아키텍쳐와 독립적인 부분이 있다. 리눅스는 가급적 아키텍쳐 독립적으로 구성되려고 노력한 흔적이 여기저기 보인다. 그래서 리눅스가 다른 아키텍쳐에 포팅 될수 있었던 것이다. 만약 PC의 i386계열에 의존적인 부분이 매우 많았다면 지금처럼 임베디드용으로 사용되지도 못했을 것이다. 자 커널을 이해하는 방법은 어떤게 좋을까? 어디까지 이해해야 할까? 이에 대한 나의 생각을 풀어 보겠다



·커널을 이해하기 위한 방법론 및 어디까지?

커널을 이해하기 위해서 가장 좋은 방법은 쏘스에서 흐름을 쭈욱 쫒아가 보는 것이다. 이를 위한 방법은 켈프에서 제안한 숙제중 부팅 메세지를 시리얼로 보내는 방법을 제안한다. 물론 이때 "Uinx kernel 완전분석으로 가는길이라는 책" 을 옆에 끼고 있는 것이 좋을 것이다. 물론 켈프에 조형기님이 진행하고 있는 강좌란도 무척 도움이 될것이다. 너무 완벽하게 쫒아 가려고 하지 않는 것이 좋을 것이다. 이 놈의 리눅스 커널을 쫒아 가는 것에 맛이 들리면 도통 헤어나질 못하게 된다. 필요한 만큼만 쫓아 다니면 된다. 임베디드 리눅스를 구현함에 있어서 대부분은 기존에 이미 포팅되어 있는 아키텍쳐를 이용하게 되는데 이 방법이 의미하는 것은 커널을 완벽하게 이해하기 보다는 커널 쏘스의 어떤 부분에 어떤 기능이 있는가 정도를 파악하는 선이면 된다는 것이다. 필요할때 좀더 자세하게 쏘스를 쫒아 다니면 된다. 또 내가 권유하는 방식은 당신이 필요로 하는 기능은 대부분 다른 사람이 이미 해 놓았을 가능성이 높다는 것이다. 커널에 집중하기 보다는 웹싸이트를 뒤지는 시간이 더 짧을 수 있다. 요즘은 Know Where!! 아닌가....



·정말 임베디드 리눅스를 하려면

5항까지 진행된 분이라면 6항 이후에 설명하는 과정을 수행해도 문제가 없을 것이다. 여기서 부터는 보통 일반인들이 말하는 임베디드 시스템용 리눅스를 어떻게 하는가를 설명하는 것이다



·평가 보드를 구매하라...

만약 당신이 가난한 개발자라면 이 이후에 진행은 포기해 달라.. 왜? 개인이 하기에는 너무도 벅찬 돈이 든다. 그냥 평가 보드만 사서 될일이 아니다. (이것도 정말 비싸다) 물론 평가 보드만 사도 될수 도 있지만 새로운 하드웨어적인 기능을 추가하고 시험하려면 개발 장비가 보통 고가가 아니다. 그냥 개인이 취미로 하기에는 이미 금전적인 부담이 넘어선다. 단 평가보드상에서 만족한다면 평가보드 살 능력이 되야 한다. 평가보드만으로도 꽤 많은 것을 공부 할수 있다. 단 평가보드를 구매할때 JTAG가 지원되는 평가보드를 구매하라 그나마 JTAG를 사용하는 공부는 돈이 적게 든다



·평가 보드를 구매 했다면....

평가 보드를 보통 구매하면 대부분의 문서가 따라 오게 된다. 물론 사용되는 디바이스의 설명서들이 포함되 있거나 최소한 어디서 구하는지에 대한 설명은 있을 것이다. 이런 자료를 모두 일단 확보할 것.



·MCU를 공부하라..

평가 보드에 사용되고 있는 MCU에 대해서 공부해야 한다. MCU를 모르고 임베디드를 도전하는 것은 시간낭비의 지름길이다. MCU의 구조 MCU의 하드웨어 사양 MCU의 프로그램 방법 ( 어셈블러 ) MCU의 동작 방식 뭐 이런 것이 있겠다.



·평가 보드에 사용되는 디바이스를 공부해라...

평가 보드에 사용되는 디바이스를 모두 공부할 필요는 없다. 자신이 사용하고자 하는 디바이스에 대해서 하드웨어적으로는 어떻게 연결되고 디바이스를 제어하기 위해서는 소프트웨어 적으로 어떻게 해야 하는 가를 이해 해야 한다. 이런 이해를 위해서는 해당 디바이스에 대한 리퍼런스 매뉴얼의 확보는 필수적이다. 항상 나에 가슴을 아프게 하는 것은 기술된 언어가 영어라는 점이다. 빨리 한글이 전세계 공통어로 되어야 하는데.... 나를 세계 대통령으로 밀어 주면 가장 먼저 한글을 공용어로 하고 모든 표기를 한글로 하는 세계법을 제정하겠다.



·크로스 컴파일 환경을 구축하는 것을 공부하라

임베디드 리눅스를 공부하는 것에 가장 큰 관문중에 하나가 크로스 컴파일 환경을 구축하는 것이다. 그나마 다행인것은 요즘은 아예 rpm 패케지로도 나온다는 점이다. 그래도 몇몇 cpu에 필요한 환경은 자신이 스스로 구축해야 한다. 또 평가 보드에 따라 구축하는 방법이 조금씩 다를 수 있다. 물론 평가보드에 따라오는 CD에는 일반적으로 크로스 컴파일에 필요한 화일도 따라오므로 좀 괜찮기는 하지만 아예 공부하지 않으면 조금만 문제가 생겨도 속수 무책일수 있다.



·부트 로더를 공부하라.

임베디드 리눅스를 공부하기 위해서 가장 처음 부딪히는 것이 부트 로더다. PC에서는 그 개념이 별로 중요하지 않으므로 이 문제가 별로 대두되지 않지만 임베디드에서는 바로 대두 된다. 보통은 이미 개발된 오픈된 부트 로더를 자신의 시스템에 맞게 바꾸게 된다. 그러므로 부트로더의 쏘스는 어느정도 분석하고 있어야 한다.
부트로더자료 - [http://haninara.xcool.net/forStudy/download.php]



·NFS 시스템에 대해서 공부하라

임베디드 시스템에는 커다란 보조 기억 장치가 없기 때문에 필히 네트워크를 이용한 다른 시스템의 보조 기억 장치를 마운트 사용해야 편리하다. 이를 위해 사용되는 것이 NFS이다. 고로 이에 대한 공부는 해두는 것이 좋다



·그외 나머지는 어떻게?

커널을 올리고 바꾸고 하는 것은 PC에서 공부했다면 별로 문제가 되지 않는다. 또 대부분 커널은 포팅했다. 단 일반적으로 부딪히는 문제를 늘어 놓는다면 다음과 같다



·MMU가 없다..

보통 PC에서는 MMU가 있으므로 문제가 되지 않지만 임베디드 시스템에서는 MMU가 없는 것이 일반적이다. 왜? 가격이 싸기 때문이다. 그렇다면 어떤 문제가 있을까 바로 이 문제에 대해서 공부해야 한다는 것이다. 50100용을 사용하거나 드래곤볼 을 사용한 임베디드 리눅스의 하우투 문서를 찾아 보고서 공부하는 것이 좋다



·루트 디스크 이미지와 램 디스크

임베디드 리눅스의 거의 대부분이 보조 기억 장치가 없거나 있어도 플래쉬 메모리 이다. 그래서 루트와 마운트 되는 기억 장치로 램 디스크를 많이 사용하게 된다. 문제는 램 디스크용 루트 이미지가 ROM에 있거나 플래쉬 메모리에 저장되기 때문이다. 커널의 루트 이미지 복사는 부분에 대한 공부를 필요로 하는 것이 이 때문이다.



·플래쉬 메모리에 대해서 공부 할것

플래쉬 메모리는 하드 디스크 처럼 쓰고 읽을 수 있는 저장 장치이다. 더구나 읽는 속도가 매우 빠르다. 그러나 플래쉬 메모리는 쓰는 횟수에 한계가 있다. 이에 대한 공부를 미리 하지 않으면 당신이 납품한 임베디드 장비에 대해서 고생 할 가능성이 농후하다. 이에 대하여 다른 사람은 어떤 방법론이 있는가에 대하여 미리 공부해 두는 것도 좋을 것이다. 가끔 배신감 느끼게 플래쉬에 대한 몇가지 소프트웨어가 특허에 걸려 있다.



·계속 늘어 놓으면 한도 끝도 없을 것 같으므로

정말이다.. 임베디드 리눅스라는 분야는 PC이외에 모두 다 라고 할 정도로 다양하다. 이 모든 것을 미리 공부할수는 없다. 역시 실전에 부딪히면서 배우는 수밖에



·빨리 개발하는 방법....

아마도 이 글을 읽고서 벌써 임베디드 리눅스를 공부하고 싶은 마음이 없어지는 사람들의 목소리가 들린다. 음.... 아마도 이글을 읽고 있는 분들 중에는 당장 1달안에 개발을 완료 해야 하는 분들도 있을 것이다. 이에 대한 해답은 아니지만 속성 코스에 대해서 이야기 하려고 한다. 단 이 방법은 엔지니어로써 어느정도 구력이 있는 분에 해당하는 것이지 완전 엔지니어 초짜에 해당되는 것은 아님을 미리 밝힌다.



·이미 개발된 평가 보드를 이용할 것...

자 임베디드 리눅스를 이용한 시스템을 만든다는 것은 자신이 목적으로 하는 동작이 정확하게 수행되면 된다. 그러므로 구현하고자 하는 장비와 최대한 같은 기능을 담고 있는 평가보드(개발보드) 를 구한다. 이 평가 보드에는 리눅스가 모두 설치 되어 있어야 한다. 그리고 캐랙터 디바이스의 가장 최소한에 대한 공부만 한다. 이것 마저도 안한다면 어쩔수 없다. 그리고 평가보드의 회로를 최대한 그대로 수용한 목적 시스템을 만든다. 이런 상태라면 다음과 같은 할일만 남는다.

1. 부트로더에서 초기화와 커널 부팅을 수행하는 부분만 남겨 놓고 제거한다.
2. 커널을 그대로 사용한다.
3. 대부분의 디바이스 드라이버도 그냥 사용한다.
4. 추가된 디바이스의 드라이버만 작성한다.
5. 어플리케이션을 작성한다.

by 성우 | 2007/12/07 17:06 | Linux | 트랙백(1) | 덧글(0)

리눅스 메뉴얼 4 (커널,X윈도,클러스터링)

커널

일반

리눅스가 사용하는 근본 원리와 작동 방식에 대한 설명-kldp

커널에 관한 설명과 커널 컴파일- kldp
유닉스/리눅스 커널 시스템 작동 원리- kldp
커널 분석- 리눅스 공동체 세미나
Kernel Analysis HOWTO- kldp
리눅스 커널 해커들을 위한 입문서- kldp
임베디드 시스템 개발자를 위한 리눅스 커널- kldp

컴파일

커널 소스 설치, 세부 환경설정, 컴파일 및 설치- kldp

Linux Kernel Compile Guide- kldp
Linux Kernel 컴파일하기- kldp
Linux Kernel 패치하기- kldp
커널 2.6 으로 업그레이드 하기- kldp
Linux Kernel 컴파일 팁 1- kldp
Linux Kernel 컴파일 팁 2- kldp

커널 내부구조

리눅스 커널 2.4 소개- kldp

리눅스 2.6의 멋진 세상- http://youlsa.i-on.net/
Kernel 2.6 Intro- kldp
커널 2.6.x 디바이스 드라이버 작성에 관한 안내- http://pain.mizi.com
proc 파일 시스템 다루기- kldp
devfs에 대한 질문/답변 - kldp
캡처 카드나 TV튜너를 사용하는 방법- kldp
시스템 설치시 모듈식의 커널 설정을 가능하게 하는 initrd- kldp
시각적 벨을 사용하는 방법 - kldp
iBCS 리눅스 이외의 다른 x86기반 유닉스의 실행 파일을 실행- kldp
리눅스에서 램디스크 블럭 디바이스 사용하기- kldp
커널 모듈을 사용하는 방법과 커널 컴파일에 관한 팁(linux modules install)- kldp
리눅스 커널 모듈을 자동으로 처리해 주는 커널 데몬 - kldp

X윈도

일반

X 윈도우의 구성 요소들과 아키텍처에 관한 개괄- kldp

X 윈도 시스템 환경 설정 및 여러 정보들- kldp
XFree86 4.3 설치하기- kldp
XFree86 바이너리 패키지로 설치하는 방법- kldp

설정

비디오 카드와 모니터에 알맞는 모드라인(mode line)을 설정- kldp

XFree86 4.x 버전에서 다중 모니터 및 Xinerama 확장 기능을 사용하는 방법- kldp
인텔 810, 810E 칩셋에서 엑스 윈도우를 설정하는 방법- kldp
노트북에서 프레임버퍼를 이용하여 엑스 윈도우를 설정하고 사용하는 방법- kldp
i740에서 엑스 윈도우를 사용하기 위한 엑스 서버 설정- kldp
엑스 윈도우를 설정하기 위한 모드라인 설정 방법- kldp

사용

엑스 윈도우의 KDE에 관한 가이드- kldp

KDE 제어 센터 도움말 메시지 한글 번역- kldp
KDE 패널 도움말 메시지 한글 번역- kldp
KDE 윈도우 매니저 도움말 메시지 한글 번역- kldp
KDE 파일 관리자 도움말 메시지 한글 번역- kldp
GNOME 사용자 가이드- kldp
GNOME과 KDE 소개- http://www.linux.co.kr
GNOME과 KDE 커스터마이즈- http://www.linux.co.kr
Enlightenment Theme (엔라이튼먼트 테마)- http://www.linux.co.kr
KDE Theme (KDE 테마)- http://www.linux.co.kr
WindowMaker Theme (윈도우 메이커 테마)- http://www.linux.co.kr
단순한 엑스 윈도우 매니저 블랙박스 가이드- kldp
E(enlightenment)에 대한 빈번한 질문(FAQ)- kldp
윈도우 매니저 중 하나인 윈도우메이커 설정에 관한 설명- kldp

터미널

자동 로긴과 리눅스를 엑스 터미널로 설정하는 방법- kldp

리눅스를 디스크 없는 터미널 서버로 설정하는 방법- kldp
엑스 윈도우에서 원격지의 프로그램을 실행하는 방법- kldp

기타

엑스 윈도우에서 트루타입 글꼴을 사용하는 방법- kldp

리눅스에서 사용되는 글꼴에 관한 안내- kldp
엑스 터미널 타이틀바를 마음대로 설정하는 방법- kldp
엑스 윈도우에서 커다란 커서를 사용하는 방법- kldp

주변기기

멀티미디어
그래픽 렌더링과 모델링 개발 환경을 위한 소프트웨어 안내- kldp
MPlayer를 소스로 직접 설치하는 방법- kldp
리눅스에서 사운드카드를 인식하도록 하는 방법- kldp
미디를 사용하기 위한 소프트웨어, 하드웨어 및 설정 방법- kldp
MP3 파일로 오디오 CD를 만드는 방법- kldp
MP3 파일을 인코딩, 재생하는데 필요한 하드웨어, 소프트웨어 및 준비과정- kldp
리눅스에서 다양한 포맷의 사운드 파일을 연주하는 방법- kldp
리눅스 비디오 서버-인터넷 방송 및 웹캠 설치 [1][2]- kldp

클러스터링강좌
클러스터(Cluster) 소개- superuser.co.kr
리눅스 클러스터링 [1][2]- 리눅스 공동체 세미나
HPC(High Performance Cluster Computing)- superuser.co.kr
하드를 장착한 클러스터- superuser.co.kr
Diskless 클러스터 설정- superuser.co.kr
부하분산 클러스터- superuser.co.kr
부하분산 서버 설정- superuser.co.kr
Linux 클러스터링- IBM
Beowulf 클러스터 (다중 병렬 CPU 측정 및 구현 )- IBM
Red Hat 클러스터 관리자 설치와 관리 가이드 (한글)- redhat
redhat cluster manager [영문]- redhat

by 성우 | 2007/12/07 17:05 | Linux | 트랙백 | 덧글(0)

<< 이전 페이지     다음 페이지 >>