BLOG main image
LoofBackER's Blog
Jun - Sik , Yang Blog

저자: 서민우
출처: 임베디드월드

다음은 memsetup.S 파일의 내용이다.

memsetup.S
#define BWSCON 0x48000000

.globl memsetup
memsetup:
   ldr      r0,=SMRDATA
   ldr      r1,=_start
   sub    r0,r0,r1
   ldr      r1,=BWSCON
   add    r2,r0,#13*4
0:
   ldr      r3,[r0],#4
   str      r3,[r1],#4
   cmp   r2,r0
   bne    0b

   mov    pc,lr

   .ltorg
SMRDATA:
   .word 0x221d4d20
   .word 0x00000700
   .word 0x00000700
   .word 0x00003f4c
   .word 0x00001f4c
   .word 0x00003f4c
   .word 0x00000700
   .word 0x00018009
   .word 0x00018009
   .word 0x008e0459
   .word 0x00000031
   .word 0x00000030
   .word 0x00000030

S3C2440A SOC는 총 8 개의 메모리 뱅크를 지원하며, 각각의 뱅크는 최대 128 MB의 크기를 가질 수 있다. 이 중 앞의 6 개의 뱅크에는 ROM이나 SRAM을 붙일 수 있으며, 마지막 2 개의 뱅크에는 ROM, SRAM, 또는 SDRAM을 붙일 수 있다. 본인이 사용하는 보드에는 첫 번째 뱅크에 1MB 크기의 NOR flash 롬, 7 번째 뱅크와 8 번째 뱅크에 각각 32MB 크기의 SDRAM이 있다.

S3C2440A SOC의 메모리 뱅크는 다음의 13개의 레지스터를 이용하여 설정할 수 있다.

BWSCON        (0x48000000)
BANKCON0     (0x48000004)
BANKCON1     (0x48000008)
BANKCON2     (0x4800000c)
BANKCON3     (0x48000010)
BANKCON4     (0x48000014)
BANKCON5     (0x48000018)
BANKCON6     (0x4800001c)
BANKCON7     (0x48000020)
REFRESH        (0x48000024)
BANKSIZE      (0x48000028)
MRSRB6         (0x4800002c)
MRSRB7         (0x48000030)

그럼 각각의 레지스터의 역할을 간략하게 살펴 보기로 하자.

BWSCON 레지스터는 각각의 뱅크에 대한 데이터 버스 폭에 대한 설정(예를 들어, 8 비트로 접근할지, 16 비트로 접근할지, 32 비트로 접근할지), 데이터를 각각의 뱅크로부터 읽는 경우 그 시간이 길 경우에 WAIT 신호를 고려할 지 등을 결정한다.

BANKCONn(n = 0,1,2,3,4,5) 레지스터를 이용하여 n에 해당하는 뱅크에 대한 메모리 접근 타이밍을 설정할 수 있다. 예를 들어 ROM이나 SRAM등을 접근할 때는 Address, Chip Selection, Data 등의 순서로 신호를 내 보낸다. 이 경우 각각의 신호간 적당한 시간 간격을 주어야 하며, 이러한 시간에 대한 설정을 이 레지스터를 이용하여 설정한다.

BANKCONn(n = 6, 7) 레지스터는 n에 해당하는 뱅크에 ROM이나 SRAM이 있을 경우는 앞에 설명한 내용과 같은 역할을 하며, SDRAM이 있을 경우는 tRCD(RAS to CAS delay)나 컬럼 어드레스의 크기가 얼만지를 설정한다.

SDRAM의 경우 데이터를 유지하기 위해 주기적으로 데이터를 새롭게 해 주어야 하는데, 이와 관련된 기능을 REFRESH 레지스터를 이용하여 설정한다.

BANKSIZE 레지스터는 SDRAM을 접근할 때 하나 이상의 데이터를 읽어오는 burst operation이나, 뱅크6, 7에 대한 메모리 맵 등을 설정하기 위해 사용한다.

MRSRBn(n = 6, 7) 레지스터는 burst length, CAS latency, burst type 등 SDRAM과 관련된 기능을 설정한다.

이상에서 메모리 컨트롤러와 관련한 13개 레지스터의 내용을 살펴 보았다. 이 중 SDRAM과 관련한 구체적인 설명은 여기서 다루지 않기로 한다. 삼성전자에서 나온 다음의 문서를 참고하기 바란다.

• SDRAM Device Operations
• SDRAM Timing Diagram
• 256Mb E-die SDRAM Specification
• S3C2440A 32-BIT CMOS MICROCONTROLLER USER'S MANUAL Revision 1

memsetup.S 파일에서는 BWSCON 레지스터부터 시작해서 13개의 레지스터에 SMRDATA 번지에 있는 13개의 32 비트 데이터를 써넣는 역할을 한다.

다음은 head.S 파일의 내용을 살펴 보기로 하자.

head.S
.globl _start
_start:
stack_setup:
   ldr       r0,=_start
   sub     sp,r0,#4

   ldr       pc,=kmain

여기서는 sp의 값을 (0x30100000-4)의 값으로 설정한다. 그리고 kmain 루틴으로 뛴다. kmain 루틴은 main.c 파일에 정의되어 있다.

다음은 main.c 파일의 내용을 살펴보자.

main.c
#define rGPFDAT (*(volatile unsigned long *)0x56000054)

void kmain(void)
{
   int i;

   while(1) {
       rGPFDAT = rGPFDAT|0x000000f0;
       for(i=0;i<0x10000;i++);
       rGPFDAT = rGPFDAT&~0x000000f0;
       for(i=0;i<0x10000;i++);
   }
}

여기서는 led를 껐다가 켰다가 하는 동작을 무한히 반복한다.

일단은 cute-boot 부트로더에서 cuteOS로 뛰는 과정을 보이기 위해 cuteOS 부분을 최대한 간단히 작성하였다. 다음 기사부터 cuteOS 부분을 본격적으로 작성해 나갈 것이다.

이상에서 부트로더의 나머지 부분과 cuteOS의 시작 부분을 작성해 보았다. 다음 기사에서는 head.S 파일에 MMU와 cache 설정 부분을 작성해 보고, exception 벡터 테이블, software interrupt 처리 루틴, 하드웨어 인터럽트 처리 루틴 등을 작성해 보기로 하자.
신고
저자: 서민우
출처: 임베디드월드

* 설계와 구현을 통한 임베디드 OS의 이해와 응용(1) - Overview
* 설계와 구현을 통한 임베디드 OS의 이해와 응용(2) - 개발환경 구성 및 부트로더 작성(1)
* 설계와 구현을 통한 임베디드 OS의 이해와 응용(2) - 개발환경 구성 및 부트로더 작성(2)
* 설계와 구현을 통한 임베디드 OS의 이해와 응용(3) - cuteOS의 시작 부분(1)


다음은 Makefile의 내용을 들여다보기로 하자. 먼저 Makefile의 내용은 다음과 같다.

Makefile
# BOOTLOADER
OBJ = start.o led.o clksetup.o memsetup.o cuteOS.bin.o

cute-boot: $(OBJ)
   arm-linux-ld $(OBJ) -o cute-boot -Ttext 0x00000000 -N -T cute-boot.lds
   arm-linux-objcopy cute-boot cute-boot.bin -O binary

start.o: start.S
   arm-linux-gcc start.S -c -DOS_RAM_BASE=0x30100000

led.o: led.S
   arm-linux-gcc led.S -c

clksetup.o: clksetup.S
   arm-linux-gcc clksetup.S -c

memsetup.o: memsetup.S
   arm-linux-gcc memsetup.S -c

# KERNEL
cuteOS.bin.o: cuteOS
   arm-linux-ld -r -o cuteOS.bin.o -b binary cuteOS.bin

cuteOS: head.o main.o
   arm-linux-ld head.o main.o -o cuteOS -Ttext 0x30100000 -N
   arm-linux-objcopy cuteOS cuteOS.bin -O binary

head.o: head.S
   arm-linux-gcc head.S -c

main.o: main.c
   arm-linux-gcc main.c -c

clean:
   rm -f *.o
   rm -f cute-boot
   rm -f cute-boot.bin
   rm -f cuteOS
   rm -f cuteOS.bin

Makefile에 대한 기본적인 내용은 이전 기사에서 언급하였다. 여기서는 새로이 추가 되거나 변경된 부분 위주로 설명하기로 하겠다. Makefile은 크게 두 부분으로 나뉘어져 있다. 하나는 부트로더를 만들어내는 부분이고, 또 하나는 커널을 만들어내는 부분이다. 위의 Makefile을 이용하여 make 명령어를 수행할 경우 다음과 같이 나타난다.

$ make
arm-linux-gcc start.S -c -DOS_RAM_BASE=0x30100000
arm-linux-gcc led.S -c
arm-linux-gcc clksetup.S -c
arm-linux-gcc memsetup.S -c
arm-linux-gcc head.S -c
arm-linux-gcc main.c -c
arm-linux-ld head.o main.o -o cuteOS -Ttext 0x30100000 -N
arm-linux-objcopy cuteOS cuteOS.bin -O binary
arm-linux-ld -r -o cuteOS.bin.o -b binary cuteOS.bin
arm-linux-ld start.o led.o clksetup.o memsetup.o cuteOS.bin.o -o cute-boot -Ttext 0x00000000 -N -T cute-boot.lds
arm-linux-objcopy cute-boot cute-boot.bin -O binary

여기서는 arm-linux-gcc를 이용하여 start.S, led.S, clksetup.S, memsetup.S, head.S, main.c 파일을 각각 start.o, led.o, clksetup.o, memsetup.o, head.o, main.o 파일로 만든다.

그리고 arm-linux-ld 명령어를 이용하여 head.o, main.o 파일로 cuteOS 결과 파일을 만들어낸다(head.S 파일과 main.c 파일은 뒤에서 살펴 보기로 하자). cuteOS가 동작할 메모리 위치는 0x30100000 번지가 된다. –N 옵션은 .data 섹션을 page 경계에 놓지 말고 .text 섹션의 바로 뒤에 붙이는 역할을 한다. 파일의 크기를 줄이기 위해 이 옵션을 사용하였다.

그리고 arm-linux-objcopy 명령어를 이용하여 cuteOS 파일로 순수 바이너리 이미지인 cuteOS.bin 파일을 만들어낸다. 이 파일이 실제 RAM 상에서 동작할 커널의 이미지이다.

다음은 cuteOS.bin 입력 파일을 cuteOS.bin.o 결과 파일로 만드는 과정이다. 여기서 <–b binary> 옵션은 입력 파일 cuteOS.bin 파일이 바이너리 파일이란 의미이며, -o 는 output을 의미한다. 또한 –r 옵션은 arm-linux-ld의 입력 파일로 다시 사용할 수 있도록 결과 파일을 만들라는 의미이며, relocateable의 약자이다. 이 파일은 다음에 오는 arm-linux-ld 명령어를 이용하여 cute-boot 결과 파일을 만드는 과정에서 입력 파일로 사용하게 된다. 즉, arm-linux-ld 명령어를 이용하여 start.o led.o clksetup.o memsetup.o cuteOS.bin.o 입력 파일로 cute-boot 결과 파일을 만든다. <-T cute-boot.lds> 옵션은 arm-linux-ld 가 사용할 링커 스크립트 파일로 cute-boot.lds 파일을 사용하라는 의미이다.

마지막으로 arm-linux-objcopy 명령어를 이용하여 cute-boot.bin 파일을 만든다. 이 파일을 JTAG를 이용하여 ROM 상에 다운 받아 실행하면 된다.

다음은 clksetup.S 파일의 내용이다.

clksetup.S
#define LOCKTIME 0x4c000000
#define UPLLCON 0x4c000008
#define MPLLCON 0x4c000004
#define CLKDIVN 0x4c000014
#define CAMDIVN 0x4c000018

#define UPLLVAL ((60<<12)|(4<<4)|1)
#define MPLLVAL ((0x6e<<12)|(3<<4)|1)

.globl clksetup
clksetup:
   ldr r0,=LOCKTIME
   mov r1,#0xffffffff
   str r1,[r0]

   ldr r0,=CAMDIVN
   mov r1,#0
   str r1,[r0]

   ldr r0,=CLKDIVN
   mov r1,#0xd
   str r1,[r0]

   mrc p15,0,r1,c1,c0,0
   orr r1,r1,#0xc0000000
   mcr p15,0,r1,c1,c0,0

   ldr r0,=UPLLCON
   ldr r1,=UPLLVAL
   str r1,[r0]

   ldr r0,=MPLLCON
   ldr r1,=MPLLVAL
   str r1,[r0]

   mov pc,lr

파일의 내용을 살펴보기 전에 먼저 S3C2440A SOC의 clock과 관련된 기능을 이해해 보자.

S3C2440A SOC에는 CPU, AHB 버스, APB 버스, USB 버스로 clock을 공급하는 clock 생성기가 있다. 이 clock 생성기는 MPLL과 UPLL을 포함하고 있으며 MPLL에서는 CPU, AHB 버스, APB 버스로 공급하는 clock을 생성하며, UPLL에서는 USB 버스로 공급하는 clock을 생성해 낸다.

MPLL로부터 CPU로 공급하는 clock을 FCLK, FCLK을 1,2,3,4, 또는 6으로 나누어 AHB 버스로 공급하는 clock을 HCLK, HCLK를 1 또는 2로 나누어 APB 버스로 공급하는 clock을 PCLK이라 한다. 또 UPLL의 값을 1 또는 2로 나누어 USB 버스로 공급하는 clock을 UCLK이라 한다.

S3C2440A SOC의 clock 생성기는 외부 크리스털(XTIpll)로부터 16.9344MHz의 값을 입력 받아 MPLL과 UPLL로 공급을 한다. 그러면 이 두 PLL은 PLL에 대한 설정에 따라 CPU와 버스에서 사용할 적절한 속도의 높은 주파수의 clock을 생성해 낸다. 참고로 필자는 MPLL로부터 나오는 clock의 속도가 399.65MHz가 되도록 MPLL을 설정하였으며, UPLL로부터 나오는 clock의 속도는 95.96MHz가 되도록 UPLL을 설정하였다.

Power-On Reset시, 즉, S3C2440A SOC에 전원을 넣을 때, PLL이 일시적으로 불안정하기 때문에 외부 크리스털(XTIpll)로부터 오는 clock(16.9344MHz)을 직접 FCLK으로 공급하며, 부팅 초기 루틴에서 PLLCON 레지스터를 이용하여 PLL의 clock 속도를 설정한 후에야 MPLL로부터 나오는 clock을 FCLK으로 공급할 수 있다. 그런데 PLL을 설정할 경우 PLL에서 나오는 clock이 일시적으로 불안정하게 되며, 따라서 일정기간 clock의 공급을 차단하게 되는데 그 차단되는 시간을 LOCKTIME 레지스터를 이용하여 조절한다. 즉, PLL을 설정한 후, LOCKTIME 레지스터에 설정된 값에 해당하는 시간동안 MPLL로부터 나오는 clock이 FCLK으로 전달되지 않으며, LOCKTIME 레지스터에 설정된 값에 해당하는 시간이 흐른 이후에야 MPLL로부터 FCLK으로 clock이 공급된다. 이 경우 LOCKTIME 레지스터의 시간 기준은 외부 크리스털(XTIpll)로부터 오는 clock에 의해 결정된다.

또한 PLL로부터 CPU나 각각의 버스로 clock이 공급되는 도중이라도 그 설정 내용을 변경할 경우 LOCKTIME 레지스터에 설정된 값에 해당하는 시간이 흐른 이후에야 CPU나 각각의 버스로 clock이 공급된다.

그러면 clksetup.S 의 내용을 자세히 들여다보기로 하자.

ldr r0,=LOCKTIME
mov r1,#0xffffffff
str r1,[r0]

이 부분은 LOCKTIME 레지스터의 내용을 설정하는 부분이다. LOCKTIME 레지스터는 0x4c000000 번지에 있으며, 다음과 같은 구조로 되어 있다.




ldr r0,=CAMDIVN
mov r1,#0
str r1,[r0]

ldr r0,=CLKDIVN
mov r1,#0xd
str r1,[r0]

이 부분은 FCLK, HCLK, PCLK의 속도 비율을 1 대 4 대 8로 맞추는 부분이다. CAMDIVN 레지스터와 CLKDIVN 레지스터는 각각 0x4c000018, 0x4c000014 번지에 있다.

먼저 CAMDIVN 레지스터는 다음과 같은 구조로 되어 있다.



또한 CAMDIVN 레지스터의 속도 비율과 관련된 9 번 비트는 다음과 같은 의미를 갖는다.



다음으로 CLKDIVN 레지스터는 다음과 같은 구조로 되어 있다. (258P 참조)




mrc p15,0,r1,c1,c0,0
orr r1,r1,#0xc0000000
mcr p15,0,r1,c1,c0,0

이 부분은 CPU의 버스 모드를 fast 버스 모드로부터 asynchronous 버스 모드로 변경하는 부분이다. CLKDIVN 레지스터의 HDIVN 부분이 0 이 아니고, CPU 버스 모드가 fast 버스 모드일 경우, CPU는 HCLK에 동기해서 동작을 하기 때문에 위의 코드가 필요하다. 코드의 내용을 좀 더 살펴 보자.

mrc p15,0,r1,c1,c0,0

이 명령어는 15 번 코프로세서의 c1 레지스터의 값을 r1 레지스터로 가져오는 역할을 한다. 15 번 코프로세서는 cache나 MMU에 대한 설정 등을 할 때도 사용한다. c1 레지스터는 컨트롤 레지스터이다.

orr r1,r1,#0xc0000000
mcr p15,0,r1,c1,c0,0

c1 레지스터의 최상위 두 비트를 이진수 11로 설정함으로써 CPU의 버스 모드를 asynchronous 버스 모드로 변경한다.

ldr r0,=UPLLCON
ldr r1,=UPLLVAL
str r1,[r0]

이 부분은 USB 버스로 공급하는 clock의 속도를 (95.96/2)MHz로 설정하는 부분이다.

ldr r0,=MPLLCON
ldr r1,=MPLLVAL
str r1,[r0]

이 부분은 CPU로 공급하는 clock의 속도를 399.65MHz로 설정하는 부분이다.

MPLLCON 레지스터와 UPLLCON 레지스터는 다음과 같은 구조로 되어 있다.



MPLL과 UPLL로부터 생성되는 clock의 속도는 다음의 공식을 따른다.

Mpll = (2*m*Fin)/(p*2^s), m = (MDIV+8), p = (PDIV+2), s = SDIV
Upll = (m*Fin)/(p*2^s), m = (MDIV+8), p = (PDIV+2), s = SDIV

참고로 S3C2440A SOC에서 Fin은 16.9344MHz이다.

이상에서 clksetup.S 파일의 내용을 살펴 보았다.
신고
저자: 서민우
출처: 임베디드월드


이번 기사에서는 부트로더의 나머지 부분과 cuteOS의 시작 부분을 작성해 보기로 하자.

먼저 다음과 같은 순서로 부트로더의 나머지 부분을 작성해 나갈 것이다.

1. FCLK, HCLK, PCLK, UCLK 등 CPU와 주변 버스로 공급되는 clock의 속도를 설정한다.
2. SDRAM 등을 접근하기 위해 메모리 컨트롤러를 초기화 한다.
3. cuteOS 이미지를 RAM 상으로 복사한 후 cuteOS의 시작 위치로 뛴다.

다음으로 cuteOS는 최소한의 어셈블리 파일과 C 파일로 구성한다. 다음과 같은 순서로 cuteOS의 시작 부분을 작성해 나가겠다.

1. C 루틴으로 뛰기 위해 SVC32 mode의 스택을 초기화 한다.
2. C 루틴으로 뛴다.

cuteOS의 본격적인 작성은 다음 호부터 진행하기로 하겠다. 그리고, cache와 MMU 설정 부분도 다음 기사에서 다루기로 하겠다.

먼저 start.S 파일의 나머지 부분은 다음과 같다.

start.S
             …
             mov          r0,#0x00000010
             bl           led_on

             bl           clksetup

             bl           led_off

             mov          r0,#0x00000020
             bl           led_on

             bl           memsetup

             bl           led_off

             mov          r0,#0x00000040
             bl           led_on

osload:
             ldr          r0,_OS_ROM_BASE
             ldr          r1,_OS_RAM_BASE
             ldr          r2,_OS_END

copy_loop:
             ldr          r3,[r0],#4
             str          r3,[r1],#4
             cmp          r0,r2
             blt          copy_loop

             ldr          pc,_OS_RAM_BASE

             .balign      4

_OS_ROM_BASE:
             .word _os_start

_OS_RAM_BASE:
             .word OS_RAM_BASE

_OS_END:
             .word _os_end

그럼 구체적으로 start.S 파일의 나머지 부분을 살펴 보자.

               …
               mov               r0,#0x00000010
               bl                led_on

이 부분은 이전 기사에서 작성했던 start.S 파일의 마지막 부분이다. <1: b 1b> 명령어가 빠졌으니 주의하기 바란다.

               bl                clksetup

여기서는 FCLK, HCLK, PCLK, UCLK 등 CPU와 주변 버스로 공급되는 clock의 속도를 설정하기 위해 clksetup 함수를 호출한다. 이 함수는 clksetup.S 파일에 정의되어 있으며 뒤에서 구체적으로 살펴 보기로 하자.

               bl                 led_off

               mov                r0,#0x00000020
               bl                 led_on

이 부분은 디버깅을 위해 led를 껐다가 두 번째 led를 켜는 부분이다.

               bl                 memsetup

이 부분은 메모리 컨트롤러를 초기화 하기 위해 memsetup 함수를 호출하는 부분이다. 이 함수는 memsetup.S 파일에 정의되어 있으며 역시 뒤에서 구체적으로 살펴 보기로 한다.

               bl                 led_off

               mov                r0,#0x00000040
               bl                 led_on

이 부분은 디버깅을 위해 led를 껐다가 세 번째 led를 켜는 부분이다.

다음은 편의상 파일의 마지막 부분을 먼저 살펴 보겠다.

               .balign                4

이 부분은 이후에 올 코드를 4 바이트 경계에 놓겠다는 어셈블러 지시어이다.

_OS_ROM_BASE:
           .word _os_start

여기서 <.word>는 32 비트 숫자를 정의하는 어셈블러 지시어이다. _os_start는 부트 롬상에서의 cuteOS 이미지의 시작 위치를 나타내며, 뒤에서 보게 될 cute-boot.lds 라는 링커 스크립트 파일에 정의 되어있다.

_OS_RAM_BASE:
           .word OS_RAM_BASE

OS_RAM_BASE는 매크로로써 Makefile에서 0x30100000 번지로 정의해 놓았으며, RAM 상에서 cuteOS가 놓일 시작 위치를 나타낸다. 즉, cuteOS는 물리적으로 0x30100000 번지에 놓이게 된다. Makefile의 내용은 뒤에서 살펴 보기로 하자.

_OS_END:
           .word _os_end

_os_end는 부트 롬상에서의 cuteOS 이미지의 마지막 위치를 나타내며, 역시 cute-boot.lds 링커 스크립트 파일에 정의 되어 있다.

그럼 다시 파일의 앞 부분으로 가 보자.

osload:
           ldr            r0,_OS_ROM_BASE
           ldr            r1,_OS_RAM_BASE
           ldr            r2,_OS_END

이 부분은 r0 레지스터에 부트 롬상에 있는 cuteOS 이미지의 시작주소를, r1 레지스터에 0x30100000 값을, r2 레지스터에 부트 롬상에 있는 cuteOS 이미지의 마지막 주소를 넣는 부분이다.

copy_loop:
           ldr            r3,[r0],#4
           str            r3,[r1],#4
           cmp            r0,r2
           blt            copy_loop

이 부분은 롬상에 있는 cuteOS 이미지를 4 바이트씩 읽어서 램상으로 복사하는 부분이다. cuteOS 이미지의 마지막 부분까지 복사하면 루프를 빠져 나간다.

               ldr                pc,_OS_RAM_BASE

여기서는 램상에 있는 cuteOS로 뛴다. 이로써 부트로더의 역할은 끝나게 된다. cuteOS는 head.S 파일과 main.c 파일로 구성되며 뒤에서 살펴 보기로 한다.

그러면 cute-boot.lds 파일의 내용을 살펴 보기로 하자.

먼저 파일의 내용은 다음과 같다.

cute-boot.lds
OUTPUT_FORMAT("elf32-littlearm","elf32-bigarm","elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
               . = 0x00000000;

               . = ALIGN(4);
               .text : {start.o(.text) *(.text)}

               . = ALIGN(4);
               .rodata : {*(.rodata)}

               . = ALIGN(4);
               .data : {*(EXCLUDE_FILE(cuteOS.bin.o).data)}

               . = ALIGN(4);
               __bss_start = .;
               .bss : {*(.bss)}
               _end = .;

               . = ALIGN(4);
               _os_start = .;
               .cuteOS : {cuteOS.bin.o}
               . = ALIGN(4);
               _os_end = .;
}

cute-boot.lds 파일은 링커 스크립트로써 arm-linux-ld가 최종 결과 파일을 만들어 내는 과정에서 설계도 역할을 한다. 그러면 파일의 내용을 좀 더 자세히 살펴 보자.

OUTPUT_FORMAT("elf32-littlearm","elf32-bigarm","elf32-littlearm")

이 부분은 arm-linux-ld가 만들어 낼 최종 결과 파일의 포맷을 나타낸다. 즉, little endian 포맷의 파일을 생성할 것인지, big endian 포맷의 파일을 생성할 것인지를 결정하는 역할을 한다. 링커 스크립트 내의 키워드는 arm-linux-ld 명령어의 <-EB> 또는 <-EL> 옵션과 같이 사용할 수 있다. 만약 arm-linux-ld 명령어를 <-EB> 옵션과 함께 사용하였다면, 두 번째 항목에 해당하는 포맷의 파일을 생성해 내며(elf32-bigarm), arm-linux-ld 명령어를 <-EL> 옵션과 함께 사용하였다면, 세 번째 항목에 해당하는 파일 포맷을 생성해 낸다(elf32-littlearm). 이 두 옵션을 모두 사용하지 않을 경우 디폴트로 첫 번째 항목에 해당하는 파일 포맷을 생성해 낸다(elf32-littlearm). 여기서는 elf32-littlearm 포맷의 파일을 생성하기로 한다.

OUTPUT_ARCH(arm)

이 부분은 최종 결과 파일이 동작할 CPU의 architecture를 나타낸다. 즉, 이 파일은 ARM CPU 상에서 동작한다는 의미이다.

ENTRY(_start)

최종 결과 파일의 시작 지점을 나타낸다. 즉, 여기서 파일의 시작 지점은 _start가 된다. _start는 start.S 파일에 정의되어 있다.

SECTIONS
{
               …
}

이 부분은 링커(arm-linux-ld)가 입력 파일들의 섹션들을 결과 파일의 어떤 섹션들로 위치시킬지를 결정하는 역할을 한다. 다음의 예를 보자.

.text : {start.o(.text) *(.text)}

이 문장은 start.o 입력 파일의 .text 섹션과 그 외의 입력 파일들(*)의 .text 섹션을 결과 파일의 .text 섹션에 위치 시키는 역할을 한다. 참고로 C 파일을 컴파일하여 오브젝트 파일을 생성할 경우, 기본적으로 함수는 .text 섹션에, 전역 변수는 .data 섹션에, 초기화 되지 않은 전역 변수는 .bss 섹션에 놓인다. 그 외에도 여러 가지 섹션들이 있으며, 또한 새로운 섹션을 정의해서 쓸 수도 있다.

. = 0x00000000;

이 부분은 현재의 위치는 0x00000000 번지라는 의미이다.

. = ALIGN(4);

이 부분은 현재의 위치를 4 바이트 경계에 놓겠다는 의미이다.

.rodata : {*(.rodata)}

이 부분은 모든 입력 파일의 .rodata 섹션을 결과 파일의 .rodata 섹션에 놓겠다는 의미이다.

.data : {*(EXCLUDE_FILE(cuteOS.bin.o).data)}

이 부분은 cuteOS.bin.o 파일을 제외한 모든 입력 파일의 .data 섹션을 결과 파일의 .data 섹션에 놓겠다는 의미이다. cuteOS.bin.o 파일은 cuteOS의 순수 바이너리 이미지이다. cuteOS.bin.o 파일을 만들어 내는 과정은 뒤에서 살펴 보기로 하자.

__bss_start = .;

이 부분은 __bss_start 심벌의 주소 값은 현재 위치와 같다라는 의미이다. arm-linux-nm 명령어를 이용하여 이 부분을 확인해 보기 바란다.

.bss : {*(.bss)}

이 부분은 모든 입력 파일의 .bss 섹션을 결과 파일의 .bss 섹션에 놓겠다는 의미이다.

_os_start = .;
.cuteOS : {cuteOS.bin.o}
. = ALIGN(4);
_os_end = .;

이 부분은 결과 파일의 .cuteOS 섹션에 cuteOS.bin.o 파일을 놓는 역할을 한다. _os_start와 _os_end 심벌이 .cuteOS 섹션의 앞뒤에 오는걸 확인해 볼 수 있다. 즉, _os_start 심벌은 cuteOS 이미지의 시작위치를 나타내며, _os_end 심벌은 cuteOS 이미지의 끝 위치를 나타낸다.
이상에서 링커 스크립트의 내용을 알아 보았다.
신고
저자: 서민우
출처: 임베디드월드



다음으로 led.S 파일의 내용은 다음과 같다.

led.S
#define rGPFCON 0x56000050
#define rGPFDAT 0x56000054
#define rGPFUP  0x56000058

#define dGPFCON 0x000055aa

.globl led_init
led_init:
   ldr r0,=rGPFCON
   ldr r1,=dGPFCON
   str r1,[r0]

   ldr r0,=rGPFUP
   mov r1,#0x000000ff
   str r1,[r0]

   mov pc,lr

.globl led_off
led_off:
   ldr r0,=rGPFDAT
   ldr r1,[r0]
   orr r1,r1,#0x000000f0
   str r1,[r0]

   b   delay

.globl led_on
led_on:
   ldr r1,=rGPFDAT
   ldr r2,[r1]
   bic r2,r2,r0
   str r2,[r1]

delay:
   mov r0,#0x8000
1:
   subs r0,r0,#1
   bne 1b

   mov pc,lr

led.S 파일에는 세 가지 함수가 있다. led_init, led_off, led_on의 세 함수가 그것들이며, 각각 led를 초기화하고, 끄고, 켜는 역할을 한다.

그럼 led.S 파일의 내용을 자세히 들여다보자.

led_init:
   ldr r0,=rGPFCON
   ldr r1,=dGPFCON
   str r1,[r0]

   ldr r0,=rGPFUP
   mov r1,#0x000000ff
   str r1,[r0]

   mov pc,lr

이 부분은 led를 초기화 하는 함수이다. 필자가 사용하는 보드에는 led가 GPF(F port)의 4,5,6,7 번 비트에 물려있다. GPF는 총 8 개의 외부 핀으로 연결되며, 각각의 핀을 input, output 또는 외부 인터럽트를 받을 수 있는 용도 중 하나로 사용할 수 있다. 이 중 필자가 사용하는 보드에서는 GPF의 4,5,6,7 번 비트에 led를 연결하고 output 용으로 사용한다. GPF를 제어하기 위해서는 GPFCON, GPFDAT, GPFUP의 세 레지스터를 사용한다. 각각의 레지스터는 다음에서 정의하는 것처럼 0x56000050, 0x56000054, 0x56000058 번지에 있다.

#define rGPFCON 0x56000050
#define rGPFDAT 0x56000054
#define rGPFUP 0x56000058

위의 코드에서는 GPFCON 레지스터를 이용하여 GPF의 4,5,6,7 번 비트를 output 용으로 설정하고, GPFUP 레지스터를 이용하여 풀업 저항을 비활성화 시키고 있다. 풀업 저항은 GPIO 핀을 input 용으로 사용할 경우, input 값이 불안정하게 들어오는 것을 막는 역할을 한다. 즉, input 값이 0 과 1 사이의 어중간한 값으로 들어올 때 0 또는 1로 고정시켜 주는 역할을 한다. 따라서 GPIO 핀을 output 용으로 사용할 경우에는 풀업 저항을 사용할 필요가 없다. 그래서 여기서는 풀업 저항을 비활성화 시키고 있다.

led_off 함수는 GPFDAT 레지스터의 4,5,6,7 번 비트에 이진수 1111을 써 줌으로써 led를 끄는 역할을 한다.

led_on 함수는 r0 레지스터로 넘어온 값에 해당하는 led를 켜 주는 역할을 한다. 즉, r0의 값이 0x00000010일 경우 GPF의 4 번 비트에 해당하는 led를 켜주고, r0의 값이 0x00000020일 경우 GPF의 5 번 비트에 해당하는 led를 켜 주는 역할을 한다. delay 루틴은 led가 꺼져있거나 켜져 있는 시간을 일정하게 유지시켜 주는 역할을 한다.

마지막으로 Makefile의 내용을 들여다보자.

Makefile
cute-boot: start.o  led.o
   arm-linux-ld  start.o  led.o  -o  cute-boot  -Ttext  0x00000000
   arm-linux-objcopy  cute-boot  cute-boot.bin  -O  binary

start.o: start.S
   arm-linux-gcc  start.S  -c

led.o: led.S
   arm-linux-gcc  led.S  -c

clean:
   rm  -f  *.o
   rm  -f  cute-boot.elf
   rm  -f  cute-boot.bin

먼저 Makefile의 작성 요령을 다음 예를 통해서 간단하게 알아보자.

start.o: start.S
   arm-linux-gcc  start.S  –c

여기서 <start.o: start.S>와 같이 콜론 ”:”을 포함하고 있는 부분을 dependency line이라 한다. 콜론을 중심으로 왼쪽 부분을 타겟이라 하고, 오른쪽 부분을 타겟을 만들기 위한 소스라고 한다. dependency line은 다음과 같은 의미를 갖는다.

target 부분은 source에 의존한다.

즉, 위에서 start.o는 start.S에 의존한다. make 명령어를 이용하여 Makefile의 내용을 수행할 경우 make 명령어는 start.o 파일이 바뀐 시간을 start.S 파일이 바뀐 시간과 비교한다. 만약 start.S 파일이 start.o 파일보다 더 최근에 바뀌었다면, make는 <arm-linux-gcc start.S –c> 부분을 수행한다. 즉, start.o 파일을 start.S 파일의 내용에 맞게 새롭게 컴파일을 수행한다. 주의할 점은 <arm-linux-gcc start.S –c>와 같은 명령어 부분은 반드시 탭키로 한 칸 띄어 주어야 한다. 즉, 다음과 같이 명령어 부분을 작성해야 한다.

<탭>arm-linux-gcc start.S –c

탭이 아닌 스페이스 키 등으로 띄어 줄 땐 에러가 발생하니 주의하기 바란다.

위의 Makefile을 이용하여 make 명령어를 수행할 경우 다음과 같이 나타난다.

$ make
arm-linux-gcc start.S -c
arm-linux-gcc led.S -c
arm-linux-ld start.o led.o -o cute-boot -Ttext 0x00000000
arm-linux-objcopy cute-boot cute-boot.bin -O binary

여기서는 arm-linux-gcc를 이용하여 start.S와 led.S 파일을 각각 start.o와 led.o 파일로 만든다.

다음으로 arm-linux-ld를 이용하여 이 두개의 목적 파일로 cute-boot 결과 파일을 만든다. arm-linux-ld 명령어의 –o 옵션은 outupt의 약자이다. 결과 파일의 맨 앞 부분이 놓일 메모리 위치는 0x00000000 번지가 된다. -Ttext 옵션은 “text” 세그먼트의 시작위치를 링커에게 알려주는 옵션이다. cute-boot 파일은 elf 포맷의 파일이며, 다음과 같이 file이란 명령어를 이용하여 cute-boot 파일의 형식을 알 수 있다.

$ file cute-boot
cute-boot: ELF 32-bit LSB executable, ARM, version 1 (ARM), statically linked, not stripped

여기서 cute-boot 파일이 elf 포맷의 32-bit ARM 용 실행 파일임을 알 수 있다.

마지막으로 arm-linux-objcopy 명령어는 파일의 포맷을 바꾸는 역할을 하며, 여기서는 elf 포맷의 cute-boot 파일을 순수 바이너리 이미지로 바꾸는 역할을 한다. 왜냐하면, 우리가 작성한 프로그램을 타겟 보드상에서 수행하기 위해서는 elf 포맷의 파일을 순수 바이너리 이미지 파일로 만들어야 한다. 즉, arm-linux-objcopy 명령어는 입력파일로 cute-boot를 받아 출력 파일로 cute-boot.bin 을 만들어 내는데 그 포맷은 <-O binary> 옵션에 의해 순수 바이너리 이미지 파일이 된다.

참고로 다음과 같이 명령어를 수행해 보자.

$ make clean
rm -f *.o
rm -f cute-boot
rm -f cute-boot.bin

이렇게 명령어를 사용할 경우 make는 Makefile에서 clean에 해당하는 target을 찾는다. 여기서는 *.o , cute-boot, cute-boot.bin 등 make를 수행하는 과정에서 생성된 파일을 모두 제거하는 역할을 한다.

이상에서 Makefile의 내용을 알아보았다.

최종적으로 생성된 cute-boot.bin 이미지 파일을 JTAG를 이용하여 보드상에 다운로드 받아 실행해 보고 의도된 대로 동작하는지 확인해 본다.

다음은 arm-linux-nm 명령어와 arm-linux-objdump 명령어를 이용하여 cute-boot 파일의 내용을 좀 더 자세히 살펴보자. 이러한 명령어들은 실제 개발하는 과정에서 디버깅용으로 유용하게 사용할 수 있는 명령어들이며, 이 후 기사에서도 종종 사용할 것이다.

먼저 arm-linux-nm 명령어는 실행 파일로부터 심벌에 대한 정보를 보여 주는 역할을 한다. 참고로 순수 바이너리 이미지에는 심벌에 대한 정보가 존재하지 않는다. 따라서 여기서는 elf 포맷의 cute-boot 파일을 이용하여 심벌의 정보를 본다.

다음과 같이 arm-linux-nm 명령어를 수행해 본다.

$ arm-linux-nm cute-boot -n
00000000 T _start
00000010 t reset
00000070 T led_init
0000008c T led_off
000000a0 T led_on
000000b0 t delay
000080d0 A __bss_end__
000080d0 A __bss_start
000080d0 A __bss_start__
000080d0 D __data_start
000080d0 A __end__
000080d0 A _bss_end__
000080d0 A _edata
000080d0 A _end

여기서 우리는 _start가 0x00000000 번지에 놓여 있는걸 알 수 있다. 또한 reset이 0x00000010 번지에 놓여 있는걸 볼 수 있다. 참고로 __bss_end__, __bss_start, __bss_start__, __data_start, __end__, _bss_end__, _edata, _end 등의 심벌들은 ld가 자체적으로 정의해서 사용하는 심벌들이다. 궁금하면 다음과 같이 명령어를 수행해 보고 나온 결과를 자세히 살펴 보기 바란다.

$ arm-linux-ld --verbose

다음은 arm-linux-objdump 명령어에 –D 옵션을 이용하여 cute-boot 파일을 역어셈블해 보기로 하자. 다음과 같이 명령어를 수행한다.

$ arm-linux-objdump  cute-boot  -D

cute-boot:     file format elf32-littlearm

Disassembly of section .text:

00000000 <_start>:
  0:   ea000002        b       10
  4:   deadbeef        cdple   14, 10, cr11, cr13, cr15, {7}
  8:   deadbeef        cdple   14, 10, cr11, cr13, cr15, {7}
  c:   deadbeef        cdple   14, 10, cr11, cr13, cr15, {7}
00000010 :
 10:   e10f0000        mrs     r0, CPSR
 14:   e3c0001f        bic     r0, r0, #31     ; 0x1f
 18:   e38000d3        orr     r0, r0, #211    ; 0xd3
 …

그러면 역어셈블한 내용을 좀 더 자세히 들여다보자.

cute-boot: file format elf32-littlearm

이 부분에서 우리는 cute-boot 파일이 little endian 방식의 ARM 용 32 비트 elf 포맷이라는 정보를 얻을 수 있다.

Disassembly of section .text:

이 부분은 .text 섹션에 대한 역어셈블을 의미하며 아래에 실제 역어셈블한 내용이 나온다. .text 섹션은 일반적으로 함수 부분이 컴파일 되어 위치하게 되는 부분이다.

00000000 <_start>:

이 부분은 0x00000000 번지에 _start가 위치한다는 의미이다.

0: ea000002 b 10

역어셈블한 결과는 세 부분으로 나뉜다. 먼저 맨 왼쪽에 주소부분, 중간에 기계어, 맨 오른쪽에 기계어에 대응하는 어셈블리어로 나타난다. 이 부분은 0 번지에 ea000002 이라는 기계어가 있으며, 이 기계어를 역어셈블한 결과가 다음과 같다는 의미이다.

b       10

  4:   deadbeef        cdple   14, 10, cr11, cr13, cr15, {7}
  8:   deadbeef        cdple   14, 10, cr11, cr13, cr15, {7}
c:   deadbeef        cdple   14, 10, cr11, cr13, cr15, {7}

이 부분은 다음 부분을 컴파일하고 링크하여 나온 결과이다.

.balignl 16,0xdeadbeef

앞에서 이 부분에 대한 설명을 하였으니 다시 한 번 확인하기 바란다.

00000010 :

이와 같이 0x00000010 번지에 reset이 위치하는 점도 참고하기 바란다.

이상에서 개발 환경을 구성하는 방법과, 부트로더의 앞 부분을 작성해 보았다. 다음 번 기사에서는 cache와 MMU 설정을 포함하여 부트로더의 나머지 부분을 완성해 보기로 하겠다.

[참고 자료]

http://sourceforge.net/projects/u-boot
u-boot-1.1.2.tar.bz2

http://emlinux.co.kr/index.php' target='_blank
u-boot-1.0.0-emlinux.tgz

S3C2440A 32-BIT CMOS MICROCONTROLLER USER'S MANUAL Revision 1
신고
저자: 서민우
출처: 임베디드월드


이번 기사에서는 개발 환경을 구성하는 방법을 알아보고, 부트로더의 앞 부분을 작성해 보기로 하자. 먼저 cuteOS를 개발해 나갈 환경은 다음과 같다.

호스트 시스템은 다음과 같다.

• i386 PC
• 와우리눅스 7.3 Paran R2
• cross-2.95.3.tar.bz2(크로스 컴파일러)

다음으로 타겟 시스템은 다음과 같다.

• s3c2440A SOC가 장착된 보드(ARM920T)
• 1M NOR flash ROM (0x00000000에 위치)
• 64M SDRAM(32M x 2) (0x30000000에 위치)

이외에 실행 이미지를 타겟 시스템으로 다운로드하기 위한 JTAG와 디버깅을 위해서 시리얼을 사용한다.

앞으로 작성할 소스 코드는 C와 ARM 어셈블리어를 사용하며, 이 두 가지 언어는 이미 숙지하고 있다고 가정하고 기사를 진행하기로 하겠다. 또한 ARM 프로세서내의 레지스터의 구조와 용도, 인터럽트의 처리 방식 등, ARM 프로세서의 programmer’s model에 대해 잘 이해하고 있다고 가정한다. 또한 리눅스 사용법에 대해서도 어느 정도 익숙하다고 가정한다.

그러면 먼저 i386 PC에 와우리눅스 7.3 Paran R2 OS가 설치되어 있는 환경에서 ARM 용 크로스 툴체인을 설치하는 과정을 살펴보기로 하자. 우리가 사용할 ARM 용 크로스 툴체인 cross-2.95.3.tar.bz2 파일은 다음 사이트에서 구할 수 있다.

http://ftp.arm.linux.org.uk/pub/armlinux/toolchain/

참고로 리눅스를 기반으로 한 ARM과 관련된 개발을 할 경우 다음 사이트를 추천한다.

http://www.arm.linux.org.uk/

cross-2.95.3.tar.bz2 파일을 설치하기 위해 리눅스 상에서 먼저 다음과 같은 작업을 한다. 파일의 설치는 반드시 root 사용자 권한으로 해야 한다.

# cd /usr/local/
# mkdir arm
# cd arm/

즉 /usr/local/ 디렉토리로 들어가 arm 디렉토리를 생성한 후, arm/ 디렉토리로 들어간다. 그리고 cross-2.95.3.tar.bz2 파일을 위의 사이트에서 다운로드 받아 /usr/local/arm/ 디렉토리로 가져온다. 그리고 /usr/local/arm/ 디렉토리에서 tar 명령어를 이용하여 다음과 같이 파일을 설치한다.

# tar xvjf cross-2.95.3.tar.bz2

이와 같이 하면 /usr/local/arm/2.95.3/ 디렉토리에 크로스 툴체인이 설치된다. 설치한 툴체인을 사용하기 위해 홈 디렉토리 밑에 있는 .bash_profile 파일의 마지막 부분에 다음과 같이 두 문장을 추가해 준다.

PATH=/usr/local/arm/2.95.3/bin:$PATH
export PATH

참고로 cuteOS의 개발은 일반 사용자의 권한으로도 할 수 있으니, 일반 사용자 계정을 추가한 후 일반 사용자의 홈 디렉토리 밑에 있는 .bash_profile 파일에 위와 같은 내용을 추가하고 개발을 진행해도 되겠다. 참고로 필자는 일반 사용자의 계정으로 cuteOS를 개발해 나갈 것이다.

이렇게 .bash_profile 파일을 수정해 준 후 수정한 내용을 적용하기 위해서는 다시 로그인을 하거나 또는 다음과 같은 리눅스 명령어를 이용하여 .bash_profile 파일의 내용을 현재 쉘에 적용 시켜야 한다.

# source ~/.bash_profile

앞으로 우리가 사용할 명령어들은 /usr/local/arm/2.95.3/bin/ 디렉토리 밑에 존재하며 다음과 같은 명령어들을 주로 사용한다.

arm-linux-gcc
arm-linux-ld
arm-linux-objcopy
arm-linux-nm
arm-linux-objdump

이러한 툴들에 대한 설명은 실제 개발을 진행해 가면서 적절한 부분에서 설명하기로 하겠다.

이상에서 ARM용 크로스 툴체인을 설치하는 과정을 살펴보았다.

다음은 부트로더의 앞 부분을 어떻게 작성하는지, 최종적으로 실행 이미지를 어떻게 만드는지 보기로 하자. 먼저 지금 우리가 작성할 부트로더는 물리적으로 0x00000000 번지에 위치하며, 다음에 작성할 cuteOS는 물리적으로 0x30000000 번지에 위치하게 된다.

이번 글에서 작성할 예제는 세 파일로 구성된다. 즉, 부트로더의 최초 시작 지점인 start.S, 부팅시 디버깅용으로 사용할 led를 제어하기 위한 led.S, 그리고 Makefile로 구성된다.

먼저 start.S의 내용은 다음과 같다.

start.S
#define pWTCON  0x53000000
#define INTMSK  0x4a000008
#define INTSUBMSK   0x4a00001c

.globl _start
_start:
   b   reset

   .balignl 16,0xdeadbeef

reset:
   mrs r0,cpsr
   bic r0,r0,#0x1f
   orr r0,r0,#0xd3
   msr cpsr,r0
   
   ldr r0,=pWTCON
   mov r1,#0x0
   str r1,[r0]
   
   mov r1,#0xffffffff
   ldr r0,=INTMSK
   str r1,[r0]

   ldr r1,=0x7fff
   ldr r0,=INTSUBMSK
   str r1,[r0]

   bl  led_init

   bl  led_off

   mov r0,#0x00000010
   bl  led_on

1:  b   1b  

start.S 파일에서 하는 일은 다음과 같다.

1. CPU를 SVC32 mode로 전환한다.
2. watchdog timer를 끈다.
3. 인터럽트 컨트롤러의 모든 인터럽트를 소스를 mask 처리한다.

그럼 구체적으로 start.S 파일의 내용을 들여다보자.

.globl _start
_start:
   b   reset

이 부분은 파일의 시작 지점으로 물리적으로 0x00000000 번지에 놓이게 된다. 0x00000000 번지에는 1MB 크기의 flash 롬이 놓여 있다. 즉, _start 지점이 0x00000000 번지에 놓이게 되며, <b reset> 명령어는 0x00000000 번지에 놓이는 최초의 명령어가 된다. 이 명령어에 의해 CPU는 reset 위치로 뛴다. <.globl _start>에서 .globl은 전체 목적 파일을 링크할 때 _start 심벌을 링커 ld가 볼 수 있도록 하는 역할을 한다. _start 지점이 0x00000000 번지에 놓이는지는 뒤에서 arm-linux-nm 이라는 명령어를 이용하여 확인해 보기로 한다.

.balignl 16,0xdeadbeef

이 부분은 다음에 올 코드를 16 바이트 경계에 놓고 중간에 비게 되는 부분을 4 바이트 크기의 0xdeadbeef 값으로 채우라는 어셈블러 지시어이다. 즉, reset의 위치는 0x00000010 번지가 되며, <b reset> 명령어와 reset 번지의 사이는 0xdeadbeef로 채워진다. 이 부분 역시 뒤에서 arm-linux-objdump 라는 명령어를 이용하여 확인하기로 한다.

reset:
   mrs r0,cpsr
   bic r0,r0,#0x1f
   orr r0,r0,#0xd3
   msr cpsr,r0

여기는 cpsr 레지스터의 값을 r0 레지스터로 읽어온 후, r0 레지스터의 하위 다섯 비트를 이진수 00000으로 채우고, 다시 하위 5 비트와 5,6,7 번 비트를 이진수 11010011 값으로 채운 후, 수정한 r0 레지스터의 값을 cpsr 레지스터로 쓰는 부분이다. 이 부분은 CPU를 SVC32 mode로 전환을 하며, IRQ와 FIQ를 끄는 역할을 한다. 참고로 CPSR의 포맷은 다음 그림과 같다.



[그림 1] CPSR 포맷


ldr r0,=pWTCON
mov r1,#0x0
str r1,[r0]

이 부분은 watchdog timer를 끄는 역할을 한다. watchdog timer의 위치는 다음 문장에서 나타내는 것처럼 0x53000000 번지에 있다.

#define pWTCON 0x53000000

watchdog timer의 주된 역할은, 예를 들어 OS가 deadlock 등에 의해 정상적으로 동작하지 않을 경우 CPU에 reset 신호를 보내주어, 시스템을 재 부팅하는 역할을 한다. 좀 더 자세히 살펴보면, 여기서는 WTCON 레지스터의 0 번 비트와 2 번 비트를 0으로 만들어 줌으로써 watchdog timer의 reset 신호를 발생시키는 기능과 인터럽트 발생시키는 기능을 비활성화 시킨다. watchdog timer의 블록 다이어그램은 다음과 같다.



[그림 2] watchdog timer 블록 다이어그램

[그림 2]에서 WTCON[0]과 WTCON[2]에 해당하는 부분을 0으로 만듦으로써 앞에서 설명한 것과 같은 동작을 수행한다.

mov r1,#0xffffffff
ldr r0,=INTMSK
str r1,[r0]

ldr r1,=0x7fff
ldr r0,=INTSUBMSK
str r1,[r0]

이 부분은 인터럽트 컨트롤러에 연결되어 있는 모든 인터럽트 소스를 mask 처리하는 부분이다. S3C2440A SOC에는 60 개의 인터럽트 소스가 존재한다. S3C2440A SOC의 인터럽트 컨트롤러 블록 다이어그램은 다음과 같다.



[그림 3] s3c2440A 인터럽트 컨트롤러 블록 다이어그램

[그림 3]에서 인터럽트 컨트롤러의 SUBMASK 레지스터와 MASK 레지스터를 위의 소스와 같이 처리함으로써 SOC 내부 모듈과 외부에서 오는 모든 인터럽트 소스를 mask 처리한다.

bl led_init

bl led_off

mov r0,#0x00000010
bl led_on

이 예제를 수행하는 타겟 보드에는 네 개의 led가 있으며, 부팅시에 디버깅용으로 사용한다. 여기서는 각각 led를 초기화하고 led를 끈 후에 첫번째 led를 켠다. <mov r0,#0x00000010> 명령어는 켜고자 하는 해당 led의 번호를 r0 레지스터로 넘겨주는 부분이다. led에 대한 구체적인 설명은 led.S 파일에서 다루겠다.

1: b 1b

이 부분을 C로 표현하면 논리적으로 다음과 같다.

while(1);

위의 명령어의 1b에서 b는 backward의 약자로 명령어 앞에 있는 숫자 1의 위치를 의미한다. 즉, 무한히 1의 위치로 뛰는 동작을 수행한다.

이상에서 start.S 파일의 내용을 알아보았다.
신고
저자: 서민우
출처: 임베디드월드

본 기사는 임베디드 시스템을 구성하는데 있어 가장 중요한 운영체제(OS)의 흐름을 이해하는데 있다. 실제로 임베디드 OS인 RTOS를 구현해 봄으로써 독자들의 이해를 돕고자 한다. 앞으로 많은 관심을 바라며, 이번 호에서는 앞으로 어떤 내용들이 연재되는지 살펴보자.

임베디드 시스템은 알게 모르게 우리 주변에 널리 퍼져 있다. 유비쿼터스, 홈네트워킹과 같은 용어들은 모두 임베디드 시스템을 기본 전제로 한다. 우리가 가지고 다니는 휴대전화나 MP3 플레이어, 휴대용 게임기 등도 모두 임베디드 시스템이다. 이러한 임베디드 시스템은 CPU, 메인 메모리, I/O와 같은 하드웨어, RTOS와 같은 소프트웨어로 구성된다.

임베디드 시스템 개발자들은 특정한 목적에 맞게 임베디드 시스템을 구성하며, 그러한 임베디드 시스템의 특징은 표면적으로 I/O 디바이스에 의해 나타난다.

임베디드 시스템 개발자들이 해야 할 일들 중에는 이러한 I/O 디바이스를 제어하는 디바이스 드라이버를 작성하는 일도 있다. 디바이스 드라이버는 OS의 큰 흐름 내에서 동작한다. 따라서 OS의 동작을 정확히 이해하고 있어야만 디바이스 드라이버의 정확한 작성이 가능하다. 디바이스 드라이버를 작성하여 구동 시킬 경우 동기화의 문제가 발생할 수 있는데, 이러한 문제는 OS의 흐름을 정확히 모르고 디바이스를 작성할 때 발생한다.

본 기사는 궁극적으로 정확한 디바이스 드라이버의 작성을 위해 OS의 흐름을 이해하는데 그 목적을 둔다. OS의 흐름을 이해하는데 OS를 직접 구현해보는 것만큼 좋은 방법은 없다. 따라서 본 기사에서는 OS를 구현해 나가는 과정에 대해 구체적으로 소개하고자 한다.

Overview

OS는 보통 프로세스 관리, 메모리 관리, 파일 시스템, 네트워크, 디바이스 드라이버로 구성된다. 이 중 OS의 흐름은 프로세스 관리와 밀접하게 관련되어 있다. 따라서 프로세스 관리를 중심으로 OS를 구현해 보고자 한다.

OS는 ARM core를 기본으로 구현한다. 따라서 ARM 명령어와 ARM 아키텍처의 programer's model에 대해서는 어느 정도 익숙해야 본 기사를 이해할 수 있을 것이다.

Host 개발 환경은 i386 PC, 리눅스 파란 7.3 OS, ARM 용 GNU toolchain을 사용하기로 한다. 보다 구체적인 내용은 다음 기사에서 OS를 본격적으로 구현해 나가면서 언급하기로 하겠다.

본 기사를 쓰는 동안에는 OS, RTOS, kernel 이라는 용어가 차이점이 없다라는 가정 하에 혼용해서 사용하기로 한다. 또한 프로세스와 태스크라는 용어도 혼용해서 사용하기로 한다.

OS의 구현은 다음과 같은 순서로 진행한다.

1. 개발 환경 구성 방법 및 부트로더
2. 기본 커널의 설계와 구현
3. 하드웨어 인터럽트 루틴의 설계와 구현
4. multitasking의 설계와 구현
5. 동기화 문제의 발생 원인 - 코드간 간섭
6. 동기화 문제의 해결 방법 설계 및 구현
7. IPC의 설계 및 구현

그럼 어떤 내용을 구현해 나갈 지 좀 더 구체적으로 알아보자.

1. 개발 환경 구성 방법 및 부트로더

a) 리눅스의 설치 구성 요소를 알아보고 toolchain의 설치 방법을 알아본다.

여기서는 OS를 개발하기 위해 리눅스를 설치하고, GNU ARM toolchain의 설치 방법을 알아본다. toolchain이란 하나의 프로그램을 개발하기 위해 프로그램을 작성하여 컴파일하고 디버깅하고 최종 이미지를 만드는 과정에서 순서대로 사용하는 프로그램들을 말한다. 간단히 말해서 컴파일러, 디버거 등을 생각하면 되겠다. 이러한 toolchain에 대해서도 구체적으로 언급을 하고자 한다.

b) 부트로더를 작성해 보고 이해해 본다.

부트로더의 역할은 커널이 정상적으로 부팅을 수행하고 최종적으로 부팅을 완료하여 시스템을 관리할 수 있는 상태가 될 수 있도록 최소한의 환경을 구성해 주는 역할을 한다. 임베디드 시스템에서의 부트로더는 PC에서의 BIOS와 부트로더(예를 들어 lilo와 같은)의 합으로 볼 수 있다. 이러한 임베디드 시스템에서의 부트로더가 하는 역할을 알아보고 구현하여 테스트 해 보기로 하자.

c) 부트로더를 작성하는 과정에서 cache, mmu 등의 특성을 이해해 보고, 구현은 어떻게 이루어지는 지, 어떻게 나타나는지를 살펴보기로 한다.

소프트웨어가 동작하는 환경에서 cache와 mmu가 하는 기능은 중요하다. cache의 경우 시스템의 성능을 높이기 위해 사용하는 하드웨어 장치이다. 가상주소를 관리하는 mmu의 역할은 여러 프로세스간에 주소영역을 분리해 냄으로써 프로세스간에 상호 간섭을 막는 역할을 한다. 그런데 mmu의 경우, 역할은 중요하긴 하지만 그 동작 원리를 제대로 이해하지 못하고 쓰는 경우가 많다. 그러다 보니 프로그램을 이해하는 데에도 뭔가 명확하지 않은 요소를 제공한다. 따라서 여기서는 mmu의 특성을 명확하게 이해하고 가상주소가 갖는 의미를 생각해 보기로 한다.

2. 기본 커널의 설계와 구현

a) 어셈블리 루틴에서 C로 진입하는 루틴을 작성해 본다.

일반적으로 OS의 앞 부분은 어셈블리어로 작성한다. 이유는 CPU architecture 의존적인 부분의 경우 C로 표현할 수 없으며, 따라서 필수적으로 어셈블리어로 시작할 수 밖에 없다. 예를 들어 CPU의 인터럽트를 막는 동작은 C로 표현할 수 없다. 이러한 이유로 부팅 초기에 약간의 어셈블리 루틴을 작성해야 한다. 이후에는 대부분 C로 구현을 해 나간다. 이러한 과정에서 어셈블리 루틴에서 어떻게 C 루틴으로 진입하는지 구현을 통해 알아보자.

b) C 루틴상에서 커널 메시지를 출력해 본다.

OS를 개발해 나가는 과정에서 디버깅 메시지를 찍어보는 건 필수적이다. 그렇지 않을 경우 우리는 눈을 감고 개발을 해 나가야 하는 상황을 맞게 된다. OS의 개발은 무척 정밀한 작업이며, 따라서 개발해 나가는 순간순간 디버깅 메시지를 출력해 볼 수 있어야 한다.

c) interrupt vector table을 작성해 본다.

interrupt vector table이란 용어는 많이 들어봤을 것이다. 그래서 그 개념이 어떤지는 알지만 뭔가 명확치 않은 부분도 있었으리라 생각한다. 여기서는 interrupt vector table의 역할이 무언지 구체적으로 구현을 통해 이해해 본다.
d) system call handler를 설계 및 구현해 본다.

사용자 영역에서 커널 영역으로 진입하는 방법을 시스템 콜이라 한다. 시스템 콜은 프로세스가 커널에 작업을 요청할 경우에 사용하는 인터페이스로 커널의 반 정도를 차지한다. 따라서 시스템 콜을 이해한다는 건 적어도 커널의 반 정도를 이해한다는 것과 같다. 여기서는 그러한 시스템 콜을 처리하기 위한 커널 루틴이 구체적으로 어떻게 구현되는지 자세히 살펴보기로 하자.

3. 하드웨어 인터럽트 루틴의 설계와 구현

하드웨어의 요청에 의해 임의의 사용자 영역에서 커널 영역으로 진입하는 방법을 하드웨어 인터럽트라고 한다. 하드웨어 인터럽트는 I/O등의 디바이스가 커널에 작업을 요청할 경우에 사용하는 인터페이스로 커널의 나머지 반 정도를 차지한다. 따라서 하드웨어 인터럽트를 이해한다는 건 커널의 나머지 반을 이해하는 것과 같다. 시스템 콜의 콜이라는 용어와 하드웨어 인터럽트의 인터럽트라는 용어의 차이점은 무언지도 생각해 보기로 하자.

a) interrupt controller를 초기화하는 루틴을 작성해 본다.

interrupt controller는 I/O 디바이스에서 요청하는 하드웨어 인터럽트를 CPU로 연결시켜 주는 역할을 하며, 하드웨어 인터럽트를 이용하기 위해서 interrupt controller를 초기화 시켜 주어야 한다. 여기서는 interrupt controller의 구체적인 역할이 무언지, 그에 따라 초기화 루틴의 구현은 어떻게 이루어 지는지 알아 보기로 하자.

b) timer controller를 초기화하는 루틴을 작성해 본다.

OS의 심장과 같은 역할을 하는 timer controller는 주기적으로 하드웨어 인터럽트를 발생시키는 역할을 한다. 보통 RTOS의 경우는 초당 1000번 정도의 하드웨어 인터럽트를 발생시킨다. OS에서 중요한 역할을 하는 timer 디바이스를 사용할 수 있도록 초기화 하는 루틴을 작성해 본다.

c) timer interrupt handler를 설계 및 구현해 본다.

일반적인 하드웨어 인터럽트 처리루틴을 이해하고 구현하기 위해 구체적으로 timer 인터럽트를 처리하는 루틴을 작성해 본다. timer 인터럽트는 OS 내에서 여러 가지 중요한 역할을 한다. 예를 들어, round robin 방식의 스케쥴링은 time slice라는 개념이 필요하며, 이러한 time slice는 timer 인터럽트 처리 루틴에서 관리하는 요소 중에 하나이다. 또, 시간과 관련한 여러 가지 OS의 기능 역시 timer interrupt handler에서 제공한다. 예를 들어, 리눅스 시스템 프로그래밍에서 alarm() 과 같은 시스템 콜 함수 등은 OS 내부에서 timer interrupt handler가 제공하는 기능을 이용한다.

4. multitasking의 설계와 구현

OS가 일반적으로 펌웨어와 다른 점은 multitasking을 수행한다는 점이다. 즉, 일반적인 펌웨어는 하나의 태스크를 수행하는 반면에, OS는 여러 태스크를 관리한다. 따라서 multitasking은 OS가 수행해야 할 필수적인 기능이다.

a) 커널 태스크를 생성해 본다.

OS 역시 부팅 초기에는 하나의 논리적인 루틴으로 수행을 시작한다. 부팅이 완료될 즈음에는 multitasking을 수행하기 위한 여러 가지 데이터를 초기화하여 multitasking의 수행을 시작한다. 이 과정에서 부팅 초기에 수행하던 루틴 자체도 하나의 태스크로 관리해야 하며, 이를 여기서는 커널 태스크라 하였다. 이 커널 태스크를 위한 데이터를 초기화한다.

b) 문맥 전환 루틴을 설계 및 구현해 본다.

태스크간에 전환을 문맥 전환이라 한다. 문맥이란 어느 시점에서의 태스크의 수행 상태를 말한다. 문맥 전환은 현재 수행하고 있는 태스크의 문맥을 저장하는 문맥 저장 부분과 바로 다음에 수행할 태스크의 문맥을 복구하는 문맥 복구 부분으로 구성된다. 문맥 전환 루틴을 기준으로 태스크간의 논리적인 흐름이 바뀌게 된다. multitasking을 수행하기 위해 OS의 가장 안쪽에는 이러한 문맥전환 루틴이 자리하고 있다. 따라서 OS를 이해하기 위해서는 문맥전환의 원리를 반드시 이해해야 한다.

c) 스케줄링 루틴을 설계 및 구현해 본다.

태스크간 전환하는 시점에서 새로운 태스크를 선택하는 동작을 스케줄링이라 한다. 이 부분을 어떻게 설계하고 구현하느냐에 따라 우선순위 기반의 스케줄링, 라운드 로빈 방식의 스케줄링 등이 결정된다. 구현의 관점에서 보면 스케줄링 루틴 자체는 어렵지 않다. 여기서는 RTOS에서 필수적인 우선순위 기반의 스케줄링 루틴을 구현해 보기로 한다. 일반적으로 스케줄링 루틴은 문맥전환 루틴을 포함하고 있다.

d) 시스템 콜 처리 루틴에 태스크 스케줄링 루틴을 추가해 본다.
e) 하드웨어 인터럽트 처리 루틴에 태스크 스케줄링 루틴을 추가해 본다.

보통 우리가 응용프로그램을 작성할 때, 다른 프로세스로의 전환이 어떻게 이루어지는지 잘 모르는데, 그 이유는 프로세스간 전환을 수행하는 프로세스 스케줄링 루틴이 커널 루틴의 한 가운데 있기 때문이다. 이러한 프로세스 스케줄링 루틴을 시스템 콜 처리 루틴과 하드웨어 인터럽트 처리 루틴에 넣어 보고 시험해 본다.

5. 동기화 문제의 발생 원인 - 코드간 간섭

a) 공유 영역과 critical section의 개념을 명확히 이해한다.

하나 이상의 태스크 등에서 공통으로 접근하는 데이터 영역을 공유 영역이라 하며, 이 공유 영역을 접근하는 루틴을 critical section이라고 한다. 일반적으로 OS내에서 동기화의 문제가 이 공유 영역을 중심으로 발생한다. OS 내의 디바이스 드라이버에서 관리하는 I/O 디바이스 내부의 레지스터도 공유 영역이며, 따라서 디바이스 드라이버는 critical section을 포함하게 된다. 보통은 공유 영역을 하나 이상의 태스크가 접근할 때는 순서대로 접근해야 하는데 OS 내에서는 그 순서가 겹치는 문제가 발생할 수 있다.

b) 하드웨어 인터럽트 처리 루틴과 태스크 루틴간의 간섭 원인을 정확히 이해한다.

하드웨어 인터럽트는 비동기적으로 발생한다. 즉, 하드웨어 인터럽트란 언제 발생할지 알 수 없다. 태스크를 수행하던 도중에 하드웨어 인터럽트가 발생할 경우 마치 태스크가 함수를 호출하는 모양으로 하드웨어 인터럽트 처리 루틴으로 뛰어 들어가게 되는데, 이 때 태스크 루틴과 하드웨어 인터럽트 루틴이 겹칠 수 있다. 보통은 문제가 없는데, 겹치는 루틴이 같은 공유 영역을 접근할 경우 논리적인 문제가 발생할 수 있다.

c) 태스크 루틴간의 간섭 원인을 정확히 이해한다.

하드웨어 인터럽트 루틴에서 태스크 스케줄링을 수행할 수 있다. 즉, 하드웨어 인터럽트가 발생할 경우 비동기적으로 스케줄링이 발생할 수 있다. 하드웨어 인터럽트 루틴에서 수행하는 스케줄링 루틴으로 인해 태스크 루틴과 태스크 루틴간에 간섭이 있을 수 있다. 이 경우도 두 태스크가 공유 영역을 접근하는 부분에서 태스크 루틴간 간섭이 있을 경우 논리적인 문제가 발생할 수 있다. 태스크 루틴간에 어떻게 간섭이 있게 되는지는 OS를 구현해 나가며 구체적으로 알아 보기로 하자.

6. 동기화 문제의 해결 방법 설계 및 구현

a) cli, sti 명령어를 이용하여 인터럽트 처리 루틴과 태스크 루틴간에 발생하는 코드간 간섭을 해결해 본다.

하드웨어 인터럽트 처리 루틴과 태스크 루틴간의 간섭을 해결하는 방법이다. 즉, 하드웨어 인터럽트가 발생하면 문제가 발생할 수 있는 지점에서 하드웨어 인터럽트를 막는 방법이다. 그렇게 함으로써 문제가 되는 지점을 태스크 루틴과 하드웨어 인터럽트 루틴이 순서대로 접근하게 하는 방법이다. 이 방법이 구체적으로 어떻게 사용되는지 구현을 통해 알아보기로 하자.

b) key와 flag의 개념을 이용하여 태스크 루틴간 발생하는 코드간 간섭을 해결해 본다.

태스크 루틴과 태스크 루틴간의 간섭을 해결하는 방법이다. 즉, key나 flag 역할을 하는 변수를 두어 문제가 발생할 수 있는 지점을 태스크간에 순차적으로 접근하게 하는 방법이다. 세마포어나 뮤택스 변수 역시 이러한 key나 flag의 개념을 가지고 있다.

c) 세마포어와 뮤텍스의 구현 원리를 알아보고 구현해 본다.

디바이스 드라이버를 작성하는 과정에서는 세마포어와 뮤택스를 사용해야 할 경우가 많다. 세마포어나 뮤택스의 개념을 정확히 알지 못하고는 디바이스 드라이버를 구현하는 과정에서 이러한 객체들을 적절히 쓸 수 없으며, 결론적으로 버그를 내포하고 있는 코드를 구성하게 된다. 여기서는 세마포어와 뮤텍스를 직접 구현해 봄으로써 그것들의 동작 특성을 정확히 이해해 보고자 한다.

d) sleep_on 함수와 wake_up 함수를 설계 및 구현해 본다.

디바이스 드라이버를 구현하는 과정에서 흔히 사용하는 개념의 함수들이다. sleep_on 함수의 경우 현재 수행하던 태스크를 논리적으로 더 이상 진행할 수 없을 경우, 예를 들어 I/O 디바이스에서 도착하는 데이터를 기다려야 할 경우, 현재 태스크를 wait queue에 넣고 스케줄링을 수행하는 루틴으로 구성된다. wake_up 함수의 경우는 sleep_on 함수를 이용해 wait queue에서 대기하고 있는 태스크를 꺼내는 역할을 한다. 즉, sleep_on 함수는 wait queue에서 조건을 기다리던 태스크를 꺼내서 ready queue로 넣고, 필요할 경우 스케줄링을 수행하는 루틴으로 구성된다. sleep_on 함수의 경우는 그 특성상 시스템 콜 루틴에서만 사용할 수 있다. wake_up 함수의 경우는 일반적으로 하드웨어 인터럽트 루틴과 시스템 콜 루틴 모두에서 사용할 수 있다.


7. IPC의 설계 및 구현

a) 생산자 소비자 문제를 이해한다.

일반적으로 하드웨어 인터럽트 루틴과 태스크 루틴간, 태스크 루틴과 태스크 루틴간에 데이터를 주고 받게 된다. 예를 들어 네트워크 패킷을 기다리던 태스크에게 하드웨어 인터럽트 루틴에서 그 패킷을 전달해 줄 수가 있다. 또 파이프를 이용하여 태스크간 통신을 하는 경우도 데이터를 주고 받게 된다. 이 때, 데이터를 주는 루틴이 데이터에 대한 생산자, 받는 루틴이 데이터에 대한 소비자 역할을 한다. 즉, OS 내부의 많은 루틴이 이 생산자 소비자 관계에 있다. 이렇게 데이터를 주고 받는 과정에서 발생할 수 있는 동기화 문제를 생각해 보고, 앞에서 구현한 동기화 함수를 이용하여 해결해 보기로 한다. 실제로 OS 수업 중에 배운 잠자는 이발사 등의 문제도 OS 내부에서 디바이스 드라이버등을 작성하는 과정에서 발생할 수 있는 문제에 대해 인간 세상에서 그 모델을 찾은 것이다.

b) 하드웨어 인터럽트 처리 루틴과 태스크간 통신을 설계 및 구현해 본다.

네트워크 패킷을 기다리는 태스크와 그 패킷을 전달하는 네트워크 인터럽트 루틴, 하드디스크에 있는 파일을 기다리는 태스크와 그 패킷을 전달하는 하드디스크 인터럽트 루틴, 키보드의 문자를 기다리는 태스크와 그 문자를 전달하는 키보드 인터럽트 루틴은 모두 데이터 통신을 한다. 이러한 루틴간에 데이터 통신을 어떻게 구현할 지 생각해 보자.

c) 태스크간 통신을 설계 및 구현해 본다.

파이프나 시그널 등은 태스크간 통신을 수행하기 위해 OS 내부에서 제공하는 기능이다. 따라서 OS 내에는 태스크간 통신을 위한 기능도 구현되어야 한다.

이상에서 앞으로 구현하고자 하는 OS의 내용을 간략하게 알아보았다.

다음 호에는 개발 환경을 구성하고 부트로더를 작성해 보기로 한다. 구체적으로는 GNU toolchain을 설치하고, 부트로더를 작성해 보기로 하자. 그 과정에서 mmu의 정확한 특성도 이해해 보기로 하겠다. 참고로 이후에 구현할 OS의 이름은 ‘cuteOS’라 하겠다.
신고

vi Editor 정리

분류없음 2006.10.27 19:32 by LoofBackER
   

VI 에디터 사용법

이 문서는 프리(free)입니다. 자유 소프트웨어 재단(FSF)에 의해 제출된 GNU GPL(일반 공개 라이선스) 제2판 또는 그 이후 버전이 정하는 바에 따라 자유롭게 재배포하고 수정할 수 있습니다.
이 문서는 유용하게 쓰이기를 바라는 마음으로 배포합니다. 그러나 아무런 보증도 하지 않습니다. 심지어 상업성이나 특정 목적에 적합하다는 보증도 하지 않습니다. 자세한 사항은 GNU GPL을 참조하십시오.

1. vi란?

리눅스나 유닉스를 처음 접하는 사람에게 vi는 매우 골치아픈 존재이다. 도스나 윈도우에서문서 편집기를 써 본 사람에게는 vi는 매우 불편한 편집기로 생각될 것이다. 그러나 내가 아는 한 vi만큼 가볍고 편하게 쓸 수있는 편집기는 지구상에는 없다! `가볍고'라는 단어를 붙인 이유는 이맥스(emacs)라는 편집기를 쓰는 사람이 항의할 것이걱정되기 때문이다. 이맥스는 호랑이 담배피던 시절부터 가장 똑똑한 에디터로 군림해 왔다. 그러나 프로그램 크기만도 수십메가에달하고 설치되어 있지 않은 경우도 많다. 하지만 대부분의 유닉스 계열 시스템이라면 vi는 십중팔구 설치되어 있을 것이다. 따라서한번 익혀두면 여러모로 편리하게 쓸 수 있다.

vi라는 이름은 `VIsual display editor'를 의미한다. vi는 버클리의 어느 천재가만들었다고 한다. vi를 만들던 시절에는 ed와 같은 라인 에디터가 일반적이었다. 그 옛날 옛적 도스의 `edlin' 이라는라인 에디터를 써 본 사람이라면 라인 에디터가 얼마나 불편한지 알 것이다. 유닉스처럼 텍스트 에디터와 포매터가 분리된 환경에서는텍스트 에디터의 비중이 크기 때문에 기능 면에서도 많은 요구가 있게 마련이다. 때문에 텍스트 에디터가 워드 프로세서의 기능의상당 부분을 가지게 되었다. 유닉스에 여러가지 종류가 있듯이 vi도 여러가지 클론이 만들어졌다. 요즘 대부분의 배포판에는vim이라는 vi의 클론이 포함되어 있다. vim은 완벽하게 한글을 지원하고 원래의 vi의 기능을 충실하게 갖고 있을 뿐만아니라 여러가지 좀더 편리한 툴들을 제공한다.

2. vi 입문

2-1. 실행과 종료, 파일 저장

우선 vi를 실행해 보자. 쉘 프롬프트에서 vi<CR>를 입력하면 다음과 같은 화면이 보일 것이다. <CR>< C R >을 차례대로 타이프하라는 뜻이 아니라 엔터를 치라는 뜻이다. 만약 이미 존재하는 어떤 파일을 편집하고 싶다면 `vi [file]<CR>'을 입력한다.
~
~
~
~ VIM = Vi IMproved
~
~ version 5.6.70
~ by Bram Moolenaar et al.
~
~ Vim is freely distributable
~ type :help uganda<Enter> if you like vim
~
~ type :q<Enter> to exit
~ type :help<Enter> or <F1> for on-line help
~ type :help version5<Enter> for version info
~
~
~

[영어][완성][세벌식]

`~'는 빈 줄, 즉 아무것도 없는 줄이라는 뜻이다. 친절하게도 vim은 실행하자마자 가장 중요한 명령을 알려준다. 바로 `:q<CR>'이다. 한번 실행해 보자. 쉘 프롬프트로 돌아갈 것이다. 이미 `quit'의 약자라는걸 짐작하고 있을 것이다. vi를 종료하는명령 못지 않게 중요한 명령이 있다. 바로 파일을 저장하는 명령이다. 파일을 저장하기 위해서는 명령 모드에서 `:w [file]<CR>'을 타이프하면 된다. 만약 이미 파일 이름이 지정되어 있다면 그냥 간단히 `:w'만 타이프해도 된다. w는 `write'의 첫 글자이다. 또, 파일을 저장한 후 vi를 종료하려면 명령 모드에서 `:wq<CR>' 혹은 `ZZ'를 차례로 타이프하면 된다.

2-2. 글 입력

이제 뭔가를 써 넣을 차례다. 그 전에 우선 한 가지를 알아둘 것이 있다. vi가 다른`평범한' 편집기와 비교할 때 가장 특이한 점은 프로그램의 상태가 `명령 모드'와 `입력 모드'로 구분된다는 점이다. 보통의편집기는 키보드에서 입력되는 문자가 그대로 문서에 포함될 것이다. 즉, 기본적으로 입력 모드에 있다. 이에 반해 vi는기본적으로 명령 모드에 있다. 이 상태에서 키보드에서 입력하는 문자 하나하나는 vi에 대한 명령어가 된다. 입력 모드로 들어가는문자를 입력하면 비로소 그때부터 입력 모드가 되는 것이다. 입력 모드에서 명령 모드로 복귀하려면 `<ESC>'키를 누른다. 입력 모드로 들어가는 명령을 요약하면 다음 표와 같다.

a 커서 위치의 다음 칸부터부터 끼워넣기(append)
A 커서가 있는 줄의 끝에서부터 끼워넣기
i 커서 위치부터 끼워넣기(insert)
I 커서가 있는 줄의 맨 앞에서부터 끼워넣기
o 커서 바로 아래에 줄을 만들고 끼워넣기(open line)
O 커서 바로 위에 줄을 만들고 끼워넣기

다음과 같이 적어 보자.

iI am a member of KULS!<CR>Are you a member of KULS?<CR>나는 018이다.

화면에 다음과 같이 입력될 것이다.

I am a member of KULS!
Are you a member of KULS?
나는 018이다.
~
~

입력을 마쳤으면 `<ESC>'를 눌러 다시 명령 모드로 돌아오자. 만약 현재 상태가 입력 모드인지 명령 모드인지 잘 모른다면 무조건 `<ESC>'키를 눌러 일단 명령모드로 돌아온 후 다시 시작하도록 한다.

2-3. 커서 이동

이제 커서를 이동시켜 보자. 커서 이동에 사용하는 키는 다음과 같다.

h 한칸 왼쪽으로 이동 l 한칸 오른쪽으로 이동
j 한줄 아래로 이동 k 한줄 위로 이동
w 다음 단어의 첫 글자로 이동 W 다음 단어의 첫 글자로 이동
b 이전 단어의 첫 글자로 이동 B 이전 단어의 첫 글자로 이동
e 단어의 마지막 글자로 이동 E 단어의 마지막 글자로 이동
^ 그 줄의 첫 글자로 이동 $ 그 줄의 마지막 글자로 이동
0 그 줄의 처음으로 이동 <CR> 다음 줄의 첫 글자로 이동
+ 다음 줄의 첫 글자로 이동 - 윗줄의 첫 글자로 이동
( 이전 문장의 첫 글자로 이동 ) 다음 문장의 첫 글자로 이동
{ 이전 문단으로 이동 } 다음 문단으로 이동

단어 단위 이동 명령에서 대문자 명령은 소문자 명령과 약간 차이가 있다. 대문자 명령은 무조건 띄어쓰기 전까지를 한 단어로 취급한다. 다시 말해 I'm a member of "KULS"에서 w, b, eI / ` / m / a / member / of / " / KULS / " 를 각각 한 단어로 취급하는 데 반해 W, B, EI'm / a / member / of / "KULS" 를 한 단어로 취급한다. 또, vi는 빈 줄이 나오기 전까지를 한 문단으로 취급한다. 즉, {를 누르면 이전 빈 줄로, }를 누르면 다음 빈 줄로 이동한다.

2-4. 글 수정

작성되어 있는 글을 수정하는 명령은 보통 c와 커서 이동 명령이 결합된 형태이다. 정리하면 다음과 같다.

r 커서 위치의 한 글자 교체
R 커서 위치부터 <ESC>를 누를때까지 다른 글자로 교체
s, cl 커서 위치의 글자를 한개를 여러 글자로 교체
ch 커서 바로 앞의 글자를 한개를 여러 글자로 교체
cw 커서 위치의 한 단어를 교체
c0 커서 위치부터 줄의 처음까지 교체
C, c$ 커서 위치부터 줄의 끝까지 교체
cc 커서가 있는 줄을 교체
cj 커서가 있는 줄과 그 다음 줄을 교체
ck 커서가 있는 줄과 그 앞줄을 교체

이제 실습을 해보자. 다음과 같이 타이프 해 보자.

jjjr1kwwwwcwKorea University Linux Study<ESC>

아래와같이 바뀌었을 것이다. 세 글자 왼쪽으로 이동한 후(jjj) 커서 위치의 글자를 1로 교체하라(r1)는 뜻이다. r 명령의 경우 한 글자만 교체하는 명령이므로 교체 후 자동으로 명령모드로 전환된다. 그 다음은 한줄 위로 이동한 후(k) 네 단어 오른쪽으로 이동하고(wwww) 커서 위치의 단어를 Korea University Linux Study로 교체하고(cw) 명령모드로 전환하라(<ESC>)는 뜻이다.

I am a member of KULS!
Are you a member of Korea University Linux Study?
나는 011이다.
~
~

다시 다음과 같이 타이프해 보자.

O고려대학교 리눅스 동아리 KULS! Since 1999.<ESC>jkkksthe<ESC>

이제 아래와 같이 바뀌었을 것이다. 먼저 커서가 있는 줄의 위쪽에 한 줄을 삽입하고(O) (고려대학교 리눅스 동아리 KULS! Since 1999.)를 적은 다음 아래줄로 가서 오른쪽으로 세 글자 이동한 후(jkkk) 커서 위치의 한 글자를(s) the로 교체하라고 명령한 것이다.

I am a member of KULS!
고려대학교 리눅스 동아리 KULS! Since 1999.
Are you the member of Korea University Linux Study?
나는 011이다.
~
~

2-5. 글 삭제

글을 삭제하는 명령도 수정하는 명령과 거의 비슷하다. 글을 수정하는 명령이 c와 커서 이동 명령이 결합된 형태인것처럼 글을 삭제하는 명령은 d와 커서 이동 명령이 결합된 형태이다. 정리하면 다음과 같다.

x, dl 커서 위치의 글자 삭제
X, dh 커서 바로 앞의 글자 삭제
dw 한 단어를 삭제
d0 커서 위치부터 줄의 처음까지 삭제
D, d$ 커서 위치부터 줄의 끝까지 삭제
dd 커서가 있는 줄을 삭제
dj 커서가 있는 줄과 그 다음 줄을 삭제
dk 커서가 있는 줄과 그 앞줄을 삭제

이제 글을 삭제해보자. 다음과 같이 타이프한다.

j0wd0wxxxxwwXXXjwwDjdd

다음 줄의 처음으로 이동해(j0) 한 단어 오른쪽으로 이동한 후(w) 커서 위치에서부터 줄의 처음까지 지우고(d0) 다시 한 단어 이동한 뒤(w) 커서 위치의 네 글자를 지우고(xxxx) 다시 두 단어 이동한 뒤(ww) 커서 바로 앞의 글자 세개를 지우고(XXX) 다음 줄로 내려가 두 단어 오른쪽으로 이동한 후 거기에서부터 줄의 끝까지 지우고(jwwD) 다음 줄을 모두 지우라(jdd)는 뜻이다. 이제 아래와 같이 바뀌었을 것이다.

I am a member of KULS!
고려대학교 리눅스 동아리 KULS! Since 1999.
you member Korea University
~
~

2-6. 복사 & 붙이기

글을 복사하는 명령을 이미 두 가지를 배웠다. 위에서 글 교체와 글 삭제 명령으로 지워진 글은 버퍼에 저장된다. 버퍼에 저장된 글을 끼워넣는 명령은 두 가지가 있다. p 를 누르면 현재 커서 위치의 바로 다음에 끼워넣고, P를 누르면 현재 커서 위치의 바로 앞에 끼워넣는다.

현재 작성되어 있는 글에 영향을 미치지 않고 글을 복사하는 방법은 cd 대신 y를 사용한다는 점을 제외하면 위에서 살펴본 교체나 삭제 방법과 동일하다. y는 잡아당기다 라는 뜻의 영어 단어 yank의 첫 글자이다. 정리하면 다음과 같다.

yw 커서 위치부터 단어의 끝까지 복사
y0 커서 위치부터 줄의 처음까지 복사
y$ 커서 위치부터 줄의 끝까지 복사
yy 커서가 있는 줄을 복사
yj 커서가 있는 줄과 그 다음 줄을 복사
yk 커서가 있는 줄과 그 앞줄을 복사
p 커서의 다음 위치에 붙여넣기
P 커서가 있는 위치에 붙여넣기

다음과 같이 입력해보자.

kkPjyyjpjdw$pdw$p0dw$p

먼저 두 줄 위로 올라가 커서가 앞쪽(위쪽)에 조금 전에 삭제한 내용을 끼워넣고(kkP) 다음 줄을 복사해서(jyy) 한 줄 아래로 이동한 후 커서 뒤쪽(아래쪽)에 끼워넣은 후(jp) 한 줄 아래로 내려가 한 단어를 삭제한 후 그 단어를 그 줄의 맨 끝에 붙여넣고(jdw$p) 다시 맨 앞의 한 단어를 삭제한 후 맨 뒤에 붙여넣으라(0dw$p)는 뜻이다. 이제 다음과 같이 바뀌었을 것이다.

나는 011이다.
I am a member of KULS!
고려대학교 리눅스 동아리 KULS! Since 1999.
I am a member of KULS!
Korea University you member
~

2-7. 기타

다음은 위에는 해당되지 않지만 많이 사용되는 명령들이다.

u 작업 취소(undo)
U 그 줄에 행해진 작업 모두 취소
Ctrl+r 작업 재실행(redo)
. 조금 전에 했던 명령을 반복
J 현재 줄과 아래 줄을 연결
~ 대문자를 소문자로, 소문자를 대문자로 바꿈
% 괄호의 반대쪽 짝으로 이동
Ctrl+l 현재 화면을 지우고 다시 그림
Ctrl+g 파일에 관한 정보를 표시

다음과 같이 입력해 보자.

kkk0bbbxxxuuujdw.UkkJ

먼저 세 줄 위로 이동해 그 줄의 맨 앞으로 이동한 후 세 단어 오른쪽으로 이동하고(kkk0bbb) 글자 세개를 지웠다가 이를 취소한 후(xxxuuu) 한줄 아래로 내려가 한 단어를 삭제하고(jdw) 다시 한번 한 단어를 삭제하고(.) 그 줄에서 행해진 작업을 모두 취소한 뒤(U) 두 줄 올라가 그 줄과 그 다음 줄을 연결하라(kkJ)는 명령이다. 이제 다음과 같이 바뀌었다.

나는 011이다. I am a member of KULS!
고려대리눅스 동아리 KULS! Since 1999.
I am a member of KULS!
Korea University you member
~

Ctrl+l 명령은 화면을 다시 나타내는 명령이다. 문서 작성중에 talk 요청이 오거나 혹은 다른 메시지에 의해 화면이 지저분해질 경우 사용하면 편리하다.

지금까지 배운 대부분의 명령 앞에는 숫자 인수를 줄 수 있다. 다음과 같이 타이프해 보자.

3j0w2dw2k2yy3P

세 줄 아래로 내려간 후 첫 번째 칸으로 이동했다가 한 단어 오른쪽으로 이동하고(3j0w) 두 단어를 지운 후(2dw) 두줄 위로 올라가서(2k) 두 줄을 복사해서(2yy) 세번 붙여넣기 하라(3P)는 뜻이다. 이제 다음과 같이 바뀌었을 것이다.

나는 011이다. I am a member of KULS!
고려대리눅스 동아리 KULS! Since 1999.
I am a member of KULS!
고려대리눅스 동아리 KULS! Since 1999.
I am a member of KULS!
고려대리눅스 동아리 KULS! Since 1999.
I am a member of KULS!
고려대리눅스 동아리 KULS! Since 1999.
I am a member of KULS!
Korea member
~

이제 기본적인 내용은 다 익혔다. 지금까지 배운 내용만으로도 간단한 문서를 작성하고 편집하는 데에는 문제가 없을 것이다. 이제 vi를 빠져나가자.

:q<CR>

엇, 그런데 vi가 말을 듣지 않는다. 화면 맨 아래를 보면 다음과 같이 나와 있을 것이다.

~
~
No write since last change (use ! to override)

음. 파일을 저장하지 않았기 때문에 그냥은 나갈 수 없다는 뜻이다. 강제로 빠져나가려면 !를 사용해야 한다.

:q!<CR>

이제 별 탈 없이 vi를 빠져나올 수 있을 것이다.

3. vi 중급 사용자로

일단 vi를 실행한 후 /usr/doc/HOWTO/Installation-HOWTO 라는 파일을 한번 열어보자. 애써 실행한 vi를 빠져나온 다음 다음과 같이
lhs0@libretto$ vi /usr/doc/HOWTO/Installation-HOWTO

vi를 다시 실행해줘도 되겠지만, 장차 vi의 고수가 될 사람이 이런 구차한 방법을 쓸 수는 없다. 명령 모드에서 다음과 같이 입력하자.

:e /usr/doc/HOWTO/Installation-HOWTO<CR>

bash에서처럼 파일 이름을 전부 다 타이프하지 않고 일부만 타이프한 후 <TAB> 키를 누르면 자동으로 완성된다. 다음과 같은 화면이 나올 것이다. 꼭 이 파일이 아니라도 상관없다. 만약 이 파일이 없다면 다른 아무 파일이나 큼지막한 파일을 열어보자.

The Linux Installation HOWTO
by Eric S. Raymond
v4.15, 20 November 1998

This document describes how to obtain and install Linux software. It
is the first document which a new Linux user should read to get
started.
______________________________________________________________________

Table of Contents

...

"/usr/doc/HOWTO/Installation-HOWTO" [readonly] 1518 lines, 59961 characters
[영어][완성][세벌식]

전체 1518줄이다. j키를 눌러 한 줄씩 내려가며 한번 세보자. 농담이다. 설마 정말 이렇게 하는 사람이 있다면 필자는 아주 슬프다.(-;) 화면 맨 아래에 보면 1518 lines 라고 나와 있다. 만약 나오지 않는다면 Ctrl+g를 눌러보자.

3-1. 화면 이동

앞 장에서 이미 커서 이동 명령을 배웠다. 그러나 커다란 문서에서 j, k 키만 가지고 돌아다니는 것은 너무 시간이 오래 걸린다. 커다란 문서를 편집할 때 화면 이동에 쓰이는 키는 다음과 같다.

H 커서를 화면의 맨 위로 z<CR> 현재 줄을 화면의 맨 위로
M 커서를 화면의 중앙으로 z. 현재 줄을 화면의 중앙으로
L 커서를 화면의 맨 아래로 z- 현재 줄을 화면의 맨 아래로
[n]H 커서를 위에서 [n]번째 줄로 [n]L 커서를 아래에서 [n]번째 줄로
Ctrl+u 반 화면 위로 스크롤 Ctrl+b 한 화면 위로 스크롤
Ctrl+d 반 화면 아래로 스크롤 Ctrl+f 한 화면 아래로 스크롤
gg, 1G 문서의 맨 처음 줄로 G 문서의 맨 마지막 줄로
[n]G [n]번째 줄로 이동

이제 또 실습을 해 볼 차례다. 먼저 G를 눌러보자. 화면의 맨 마지막 줄로 커서가 이동할 것이다. 이번에는 gg를 입력해 보자. 다시 맨 처음 화면으로 돌아올 것이다. 극과 극으로만 움직이니 별로 재미가 없다. 100G를한번 입력해 보자. 100번째 줄로 커서가 이동할 것이다. 정말 100번째 줄인지 궁금하면 k키를 한번씩 누르며 몇 번 눌러야첫 번째 줄 까지 가는지 한번 세보자. 정말 따라하는 사람이 있다면 정말 이 글을 더 이상 쓰기가 싫어질 것 같다.

:set number<CR> 또는 :set nu<CR>

를 입력해 보자. 화면 왼쪽에 줄 번호가 표시될 것이다.

:set nonumber<CR> 또는 :set nonu<CR>

를 입력하면 다시 사라질 것이다.

이제 Ctrl+f를 눌러 한 페이지씩 아래로 내려가 보자. 다시 Ctrl+b를 눌러 원래 위치로 돌아와 보자. 이번에는 H를 눌러 보자. 커서가 화면의 맨 첫 번째 줄로 이동할 것이다. M, L도 한번씩 눌러보자. 이번에는 z<CR>을 눌러보자. H를 눌렀을 때와는 약간 다를 것이다. H를 누르면 화면은 정지된 채 커서만 이동하는 데 반해 z<CR>을 누르면 커서의 위치가 문서에 고정된 채 문서가 스크롤되어 커서가 있는 줄이 첫 번째 줄에 위치하게 된다. z., z-도 한번씩 눌러보자.

3-2. 마킹

이제 커다란 문서에서도 마음대로 커서를 움직일 수 있게 되었다. 그런데 만약 어떤 위치에서 작업하다가 잠깐 다른 위치로 가서 뭔가 복사해서 원래의 위치에 붙여넣을 경우를 생각해 보자. 줄 번호를 기억해 두었다가 [n]G명령으로 그 줄로 가도 되겠지만 똑똑한 컴퓨터를 놔두고 머리를 혹사시킬(?) 필요는 없다. vi는 26개의 마킹을 제공한다.즉, 어떤 위치에 마크를 해 둔 후 다른 위치로 이동했다가 다시 돌아갈 때 그 마크를 이용할 수 있다. 마킹에 관계된 명령들을정리하면 다음과 같다.

ma 현재 위치를 `a'로 마크
`a 마크된 `a'로 이동 'a 마크된 `a'가 있는 줄의 처음으로 이동
`` 직전의 커서 위치로 이동 '' 직전에 커서가 위치하던 줄의 처음으로

3-3. 여러개의 버퍼 사용

앞에서 버퍼를 사용하는 방법에 대해서 이미 배웠다. 그런데 앞에서 배운내용으로는 마지막으로 버퍼에 저장된 내용밖에는 사용할 수 없다. vi는 이전 9개까지 버퍼에 저장되었던 내용을 기억한다. 먼저삭제, 복사, 교체한 글은 1번 버퍼에 저장된다. 그 상태에서 또 다른 글을 삭제, 복사, 교체하면 그 내용이 1번 버퍼에저장되고 1번 버퍼에 내용은 2번 버퍼로 옮겨진다. 그 상태에서 다시 글을 삭제하거나 복사하거나 교체하면 그 내용이 다시 1번버퍼에 옮겨지고 1번 버퍼에 있던 글은 2번 버퍼에, 2번 버퍼에 있던 글은 3번 버퍼로 옮겨진다. 이런식으로 총 9개의 버퍼에내용이 저장된다. [n]번째 버퍼에 있는 내용을 붙여넣기 위해서는 다음과 같이 입력하면 된다.

"[n]p 혹은 "[n]P

즉, 붙여넣기 전에 "[n]을 붙여주면 된다. 만약 어떤 버퍼에 저장된 내용을 붙여넣어야 할지 잘 모르겠으면 다음과 같이 해보면 자동적으로 버퍼의 번호를 증가시킬 수 있다.

"1pu.u.u.u.

위에서 이야기한 9개의 버퍼 외에도 vi에서는 a부터 z까지 이름이 붙은 26개의 버퍼를 더 사용할 수 있다. 만약 현재 줄부터 3줄을 버퍼 `a'에 복사 싶다면 "a3yy를 입력한다. 현재 커서의 위치에서 줄의 끝까지 지우면서 그 내용을 버퍼 `b'에 저장하고 싶다면 "bD를 입력하면 된다. 버퍼에 있는 내용을 붙여넣는 방법은 앞에서 설명한 9개의 버퍼와 같다. 만약 버퍼 `a'에 있는 내용을 붙여넣고 싶다면 "ap를 입력하면 된다.

3-3. 패턴 검색 및 교체

패턴을 검색하는 방법은 크게 두 가지가 있다. 먼저 그 줄에서 일치하는 글자를 찾는 방법이다. 만약 현재 줄에서 `a'라는 문자를 찾고 싶다면 fa를 입력한다. 다음 `a'를 검색하려면 ;를 입력하고 다시 이전의 `a'를 검색하려면 ,를 입력한다. 사실 위에서 배운 한 줄 안에서의 검색은 별로 쓸 일이 없을 것 같다. 대부분의 경우 그냥 눈으로 보고 h, l 키나 w, b 키로 찾아가는 것이 속편하다는 사람이 많을 것 같다.

보다 많이 쓰이는 검색 방법은 문서 전체에서 특정 패턴을 찾는 방법이다. 문서 전체에서 특정 패턴을 찾는 방법을 정리하면 다음과 같다.

/[pattern]<CR> 현재 위치에서부터 아래 방향으로 패턴 검색
?[pattern]<CR> 현재 위치에서부터 위쪽 방향으로 패턴 검색
n 검색하던 방향으로 계속 패턴 검색
N 검색하던 반대 방향으로 계속 패턴 검색

만약 `linux'라는 단어를 검색하고 싶다면 다음과 같이 입력한다.

/linux<CR>

계속하여 일치하는 패턴을 검색하고 싶다면 n을 입력한다. 문서의 맨 마지막 패턴에서 다시 n을 누르면 다시 문서의 처음부터 검색을 시작할 것이다. 이 기능을 끄고 싶다면 다음과 같이 입력한다.

:set nowrapscan<CR> 또는 :set nows<CR>

이제 문서의 끝에 도달하면 다시 처음으로 돌아가지 않을 것이다. 다시 켜고 싶다면 다음과 같이 입력한다.

:set wrapscan<CR> 또는 :set ws<CR>

검색만 하니 별로 재미가 없다. 이제 특정 패턴을 다른 패턴으로 바꾸어 보자. 어떤 패턴을 다른 패턴으로 바꾸는 방법을 정리하면 다음과 같다.

:s/old/new<CR> 현재 줄의 처음 old를 new로 교체
:s/old/new/g<CR> 현재 줄의 모든 old를 new로 교체
:1,20s/old/new/g<CR> 1부터 20번째 줄까지 모든 old를 new로 교체
:-2,+4s/old/new/g<CR> 커서 2줄 위부터 4줄 아래까지 old를 new로 교체
:%s/old/new/g<CR> 문서 전체에서 old를 new로 교체
:%s/old/new/gc<CR> 문서 전체에서 old를 new로 확인하며 교체
:g/pattern/s/old/new/g<CR> pattern이 있는 모든 줄의 old를 new로 교체
:g/pattern/s//new/g<CR> :%s/old/new/g<CR>과 동일

3-4. vi에서 UNIX 명령 실행

다음과 같이 입력해보자.

:!bash<CR>

앗, 이건...친숙한 쉘 프롬프트이다. 만약 vi를 사용하다가 잠깐 쉘 프롬프트로 빠져나와야 할 경우 사용한다. 다시 vi로 돌아가고 싶으면 exit<CR>를 입력한다. :q<CR>로vi를 빠져나온것과는 달리 현재 커서의 위치나 버퍼의 내용이 그대로 보존되므로 잠깐 동안 쉘 프롬프트로 빠져나왔다가 금방 다시vi로 돌아가야 할 경우 편리하게 사용할 수 있다. 그런데 주의할 점이 하나 있다. 이렇게 vi를 빠져나온 후 다시 vi를실행해서는 안된다. 별 문제야 없겠지만 같은 파일을 다시 연다면 문제가 생길 수 있다.

만약 한 개의 명령어만 실행할 경우 좀더 편리한 방법이 있다.

:![command]<CR>

필자는 현재 latex과 vi로 이 문서를 작성하고 있는데 문서를 미리보기 할 때마다 vi를 빠져나가서 봐야 한다면 무척 불편할 것이다. 다행히 다음 명령어로 vi를 빠져나가지 않고 미리보기를 할 수 있다.

:!latex %; xdvi %<.dvi<CR>

`latex' 이라는 명령으로 현재 편집중인 파일인 vi-seminar.tex 파일을 컴파일한 다음 생성된 vi-seminar.dvi 파일을 `xdvi'라는 프로그램으로 열어보라는 명령이다. 매번 이렇게 타이프 할 필요는 없다. :을 누른 후 위쪽 화살표 키 혹은 Ctrl+p 키를 누르면 이전에 사용했던 명령이 나올 것이다. 이전에 사용했던 명령을 찾아 단순히 엔터 키만 쳐 주면 된다.

3-5. 끝줄 모드의 사용

이미 끝줄 모드에서 사용하는 명령어를 몇 가지 배웠다. 명령 모드에서 `:'를 입력하면 아래와 같이 화면 맨 아래에서 입력하는 글자들이 보일 것이다.
~
~
~
:wq
[영어][완성][세벌식]

이와 같은 모드를 `끝줄 모드' 혹은 `ex 모드'로 따로 구분해서 부르기도 한다. 끝줄 모드에서 많이 사용하는 명령어를정리하면 다음과 같다. 특정 패턴을 다른 패턴으로 교체하는 방법은 이미 위에서 정리하였으므로 다시 하지 않겠다.

:q<CR> vi를 종료함
:w<CR> 편집중인 문서를 저장
:w [file]<CR> 편집중인 문서를 [file]로 저장
:w >> [file]<CR> 편집중인 문서를 [file]에 덧붙여서 저장
:e [file]<CR> [file]을 불러옴
:e#<CR> 이전에 편집하던 파일을 불러옴
:e%<CR> 현재 파일을 다시 불러옴, 즉 저장하지 않은 작업 취소
:r [file]<CR> [file]을 커서위치에 끼워넣기
:set [option]<CR> [option]을 켜기
:set [nooption]<CR> [option]을 끄기
:![command]<CR> [command] 실행
:r ![command]<CR> [command] 실행 결과를 끼워넣기

예를 들어 현재 위치에 날짜와 시간을 삽입하고 싶으면

:r !date<CR>

를 입력한다. 만약 phone 이라는 파일을 정렬하여 삽입하고 싶으면

:r !sort phone<CR>

를 입력하면 된다. 앞에서 이미 `set'명령에 사용할 수 있는 옵션을 몇 가지 배웠다. `number'와 `wrapscan'이 생각나지 않는다면 앞장으로 되돌아가 확인하기 바란다. 다른 유용한 옵션들은 다음 장에서 설명하겠다.

4. vi의 고수로

지금까지 배운 내용만 사용하더라도 이제 vi를 다른 범상한 편집기와는 비교도 할 수없을 만큼 편리하게 사용할 수 있다. 이 정도만으로도 친구에게 자랑할 수 있을 것이다. 그러나 이 정도만으로는 아직 `나는vi의 고수다!' 라고 말하기는 좀 부끄러운 감이 있다. 모든걸 정리하는 마음으로 앞에서 열어 두었던 큼지막한 파일을 닫고 새파일을 열자. 만약 vi를 종료했다가 다시 실행하는 사람이 있다면 정말 필자는 삶이 허무해진다! 다음과 같이 타이프한다.

:e newfile<CR>

4-1. 상용구 사용

아래아 한글에 `상용구'라는 기능이 있다. 이 기능을 사용하는 사람이 얼마나 될지는 잘 모르겠지만, 아무튼 vi에도 이런 기능이 있다. 다음과 같이 타이프해 보자.

:ab kuls Korea University Linux Study<CR>

이제 입력 모드로 전환해 `I'm a member of kuls.'를 입력하자. `kuls'를 타잎하는 순간 `Korea University Linux Study'로 바뀔 것이다. 등록된 상용구를 해제하는 방법은 다음과 같다.

:unab kuls<CR>

등록된 상용구를 보여주는 명령은 다음과 같다.

:ab<CR>

만약 여러 줄을 상용구로 지정하고 싶다면 다음과 같이 한다. ^M을 타이프할때는 먼저 Ctrl+v를 누른 후 이어서 Ctrl+m을 누른다.

:ab kuls2 Korea University^MLinux Study<CR>

4-2. 매크로 사용

vi의 특징중 한 가지는 있을법한 기능은 다 있다는 것이다. 아래아 한글에서 `매크로'를 이용하는 사람이 있을지 모르겠다. vi에서도 매크로를 이용할 수 있다. 다음과 같이 타이프 해 보자. `#2'는 <F2>키를 의미한다. 그냥 `<F2>' 라고 쓰면 되는 경우도 있고 안 되는 경우도 있다.

:map #2 dwelp<CR>

이제 다음 문장의 the에서 <F2>키를 눌러보자.

You can the type letter.

아래와 같이 바뀔 것이다.

You can type the letter.

매크로에서는 <CR>, <ESC>등 모든 키 입력을 포함시킬 수 있다. 매크로에서 <CR>키를 입력하려면 Ctrl+vCtrl+m을 연속으로 타이프한다. <ESC>키를 입력하려면 Ctrl+v를 누른 후 Ctrl+[키를 누른다.

vi에서는 명령 모드에서 사용하는 매크로와 입력 모드에서 사용하는 매크로를 따로 지정할 수 있다. 입력 모드에서 사용하는 매크로는 다음과 같이 지정한다.

:map! x sequence<CR>

위의 예에서는 xsequence로 정의한다. 매크로를 해제할때는 다음 명령을 이용한다.

:unmap! x<CR>

매번 이렇게 매크로를 지정해 주는 것은 귀찮은 일이다. vi를 실행할 때마다 매크로가 실행되어 있게 하려면 홈 디렉토리의 .exrc 파일에 넣어두면 된다. 다음은 LaTeX을 자주 사용하는 필자의 .exrc파일의 일부이다.


" LaTeX을 위한 매크로

" 를 누르면 Visual selection으로 선택된 부분만 컴파일하여 xdvi로 보여줌
map ^[:1,?^\\begin{document}$?w! _region_.tex^M;;R1
map ;;R1 :'<,'>w >> _region_.tex^M;;R2
map ;;R2 :/^\\end{document}$/w >> _region_.tex^M;;R3
map ;;R3 :!latex _region_.tex; xdvi -expert _region_.dvi; rm _region_.???^M^M

" 을 누르면 현재 편집중인 문서를 컴파일하여 xdvi로 보여줌
map :w^M:!latex %; xdvi -expert %<.dvi^M^M

" 을 누르면 컴파일된 문서를 ps로 출력하여 gv로 미리보기
map :!dvips -o %<.ps %<.dvi; gv %<.ps^M^M

" 를 누르면 변환된 포스트스크립트 문서를 pdf로 변환
map :!ps2pdf %<.ps %<.pdf&^M^M

" 레이텍 문서 전처리부를 자동으로 만들어주는 매크로
map ;tex i\documentclass[a4paper]{article}^[;;T1
map ;;T1 o\usepackage{hangul,a4,indentfirst}^M\setlength{\parindent}{1em}^[;;T2
map ;;T2 o\addtolength{\hoffset}{-0.5cm}^M\addtolength{\textwidth}{1cm}^[;;T3
map ;;T3 o\kscntformat{section}{}{}^M\linespread{1.3}^M^[;;T4
map ;;T4 o\begin{document}^M^M\end{document}^[ki

" 글꼴에 관계된 매크로
map ;rm i\textrm{^[Ea}^[B
map ;tt i\texttt{^[Ea}^[B
map ;sf i\textsf{^[Ea}^[B
map ;bf i\textbf{^[Ea}^[B
map! ;rm \textrm{
map! ;tt \texttt{
map! ;sf \textsf{
map! ;bf \textbf{

" 환경(Environment)에 관계된 매크로
map! ;itemize \begin{itemize}^M\end{itemize}^[O \item
map! ;enumerate \begin{enumerate}^M\end{enumerate}^[O \item
map! ;description \begin{description}^M\end{description}^[O \item[
map! ;equation \begin{equation}^M\end{equation}^[O \label{eq:}^[i
map! ;tabular \begin{tabular}[center]{}^M \hline^M\hline^M^H\end{tabular}^[3k$i
map! ;figure \begin{figure}[!hbp]^M\end{figure}^[O
map! ;table \begin{table}[!hbp]^M\end{table}^[O
map! ;verbatim \linespread{1}\begin{verbatim}^M\end{verbatim}\linespread{1.3}^[O

" 특수문자 입력을 간편하게 하기 위한 상용구
ab ;\ $\backslash$
ab ;~ \textasciitilde

4-3. vi 설정

vi의 설정 파일은 /etc/vimrc 파일과 홈 디렉토리의 .vimrc 파일이다. 만약 GUI 버전의 vi를 사용한다면 /etc/gvimrc 파일과 .gvimrc파일로 설정할 수 있다. 앞에서 이미 vi를 설정하는 명령을 배웠고 몇 가지 옵션들도 이미 살펴보았다. 아래에서 다른 몇 가지 옵션들을 필자의 .vimrc 파일을 예로 들어 설명하겠다.
set autoindent      " 자동으로 들여쓰기를 한다.
set cindent " C 프로그래밍을 할때 자동으로 들여쓰기를 한다.
set smartindent " 좀더 똑똑한 들여쓰기를 위한 옵션이다.
set textwidth=79 " 만약 79번째 글자를 넘어가면 \
set wrap " 자동으로 <CR>를 삽입하여 다음 줄로 넘어간다.
set nowrapscan " 검색할 때 문서의 끝에서 다시 처음으로 돌아가지 않는다.
set nobackup " 백업 파일을 만들지 않는다.
set visualbell " 키를 잘못눌렀을 때 삑 소리를 내는 대신 번쩍이게 한다.
set ruler " 화면 우측 하단에 현재 커서의 위치(줄,칸)를 보여준다.
set tabstop=4 " Tab을 눌렀을 때 8칸 대신 4칸 이동하도록 한다.
set shiftwidth=4 " 자동 들여쓰기를 할때 4칸 들여쓰도록 한다.

" 아래는 한글을 제대로 처리하기 위해 필요하다.
if $LANG[0] == `k' && $LANG[1] == `o'
set fileencoding=korea
endif

"터미널이 xterm-debian 혹은 xterm-xfree86일 경우 컬러를 사용한다.
if &term =~ "xterm-debian" || &term =~ "xterm-xfree86"
set t_Co=16
set t_Sf=^[[3%dm
set t_Sb=^[[4%dm
set t_kb=^H
fixdel
endif

"문법 강조 기능을 사용한다.
if has("syntax")
syntax on " Default to no syntax highlightning
endif

4-4. vim의 특별한 기능

vi의 클론인 vim에는 원래의 vi에는 없지만 편리하게 사용할 수 있는많은 기능들이 있다. 문법 강조 기능도 원래의 vi에는 없는 기능이다. vim의 기능 중 `Visual Selection'이라는 기능이 있다. 명령 모드에서 v를 누른 후 커서를 움직여 보자. 아래아 한글의 `블럭'처럼 역상으로 움직인 범위에 있는 글들이 선택될 것이다. 이 상태에서 y, c, d 키를 눌러 선택된 범위의 글들을 복사, 교체 또는 삭제할 수 있다.

프로그래밍에 편리하게 사용할 수 있는 기능으로 탭을 끼워넣거나 취소하는 기능이 있다. 만약 커서가 있는 줄에서부터 5줄에 탭을 끼워넣으려면 다음과 같이 타이프한다.

5>>

이를 취소하려면 다시 다음을 타이프한다. 물론 그냥 u를 입력해도 된다. 그러나 여기서는 어떻게 동작하는지 보자는 것이므로 `5<<'를 입력한다.

5<<

Visual Selection 기능과 결합해서 사용하면 좀더 편리하게 사용할 수 있다. v를 눌러 들여쓰기할 범위를 선택한 다음 >를 타이프하면 선택된 범위가 들여쓰기 될 것이다.

4-5. 정규식(Regular Expression)

vi의 검색 및 교체 기능에서 `정규식(RegularExpression)'이라는 특별한 표현을 사용할 수 있는데 이를 사용하면 보다 효과적인 검색/교체를 할 수 있다. 정규식은vi 뿐만 아니라 다른 명령어에서도 많이 쓰이므로 알아두면 편리하다. 그러나 정규식에 대한 내용만으로도 1시간 강의는 충분히 할수 있다. 여기서는 간단한 사용법만을 이야기하고 넘어가겠다.

우선 정규식에서 많이 쓰이는 기호는 다음과 같다.

^ 줄의 처음을 나타낸다.
$ 줄의 끝을 나타낸다.
. 아무 글자나 한 글자를 나타낸다.
[...] [] 사이에 있는 글자 중 하나
* * 앞의 내용이 0번 이상 반복됨
\{min,max\} min 이상 max 이하의 횟수만큼 반복됨

예를 들어 줄의 맨 처음에 나오는 `linux'만 검색하고 싶다면 다음과 같이 입력한다.

/^linux<CR>

만약 3~5자리로 이루어진 모든 숫자를 검색하고 싶다면 다음과 같이 입력한다.

/[0123456789]\{3,5\}<CR> 혹은 /[0-9]\{3,5\}<CR>

만약 `ab'로 시작하는 소문자로 되어 있는 모든 단어를 삭제하려면 다음과 같이 입력한다.

:%s/ab[a-z]*//g<CR>

5. 맺음말

vi의 고수가 되기 위해서 위의 내용을 무조건 외우려고 하지 말라. j키가 무슨 역할을 하느냐고 필자에게 물어본다 해도 곧바로 대답할 수 없을 것이다. 머리로 외우려고 하지 말고 감으로 익혀야한다. 한꺼번에 모든것을 익히려 하지 말고 일단 어떤 어떤 기능이 있다는 것 정도만 알아두라. 그리고 직접 문서를 편집하면서그때그때 사용 방법을 찾아보자. 처음에는 좀 귀찮겠지만, 그러는 사이 실력이 늘 것이다. 열심히 연습하면 얼마 지나지 않아윈도우용 vi를 찾아다니게 될 것이다. 그러면 성공이다! vi의 고수가 되자!
신고
http://www-128.ibm.com/developerworks/kr/library/l-playscreen/index.html

리눅스용 터치스크린 설치하기
신고
NetBSD에서 제공하는 wscons를 사용하지 않고 /dev/lcd0로 등록 하여 mmap으로 framebuffer를 얻어서 출력한 내용입니다.

wscons를 이용하면 lcd로 console message 및 keyboard를 이용하여 login, virtual console를 이용하실 수 있을 겁니다. 단, wscons를 이용할 경우 아래의 code로는 frame buffer를 얻을 수 없고 별도로 해줘야 하는 것들이 있습니다. 참고 하시기 바랍니다.

1. lcd driver수정: 자신의 lcd에 맞게 s3c24x0의 lcd관련 register value를 설정한다. 아래는 제가 사용하는 lcd의 parameter입니다. 참고로, wscons를 사용하지 않으므로 source에서 "NWSDISPLAY"는 "0"이다.
- sys/arch/evbarm/evm24x0/evm2440_lcd.c
코드:
static const struct s3c24x0_lcd_panel_info evm2440_TFT =
{
    640,                        /* Width */
    480,                        /* Height */
    25*1000*1000,               /* pixel clock = 25MHz */

#define _(field, val)   (((val)-1) << (field##_SHIFT))

    LCDCON1_PNRMODE_TFT |
    LCDCON1_BPPMODE_TFT16,

    /* LCDCON2: vertical timings */
    _(LCDCON2_VBPD, 2) |
    _(LCDCON2_VFPD, 2) |
    _(LCDCON2_LINEVAL, 480) |
    _(LCDCON2_VPSW, 2),

    /* LCDCON3: horizontal timings */
    _(LCDCON3_HBPD, 16) |
    _(LCDCON3_HOZVAL, 640) |
    _(LCDCON3_HFPD, 16),

    /* LCDCON4: horizontaol pulse width */
    _(LCDCON4_HPSW, 24),

    /* LCDCON5: signal polarities */
    LCDCON5_INVVLINE | LCDCON5_INVVFRAME,

    /* LPCSEL register */
    0xf84, /*LPCSEL_LPC_DIS,*/
#undef _
};


2. kernel config
- sys/arch/evbarm/conf/files.evm2440
코드:
# LCD
attach lcd at ssio with lcd_ssio
file    arch/evbarm/evm24x0/evm2440_lcd.c       lcd_ssio


-sys/arch/evbarm/conf/EVM2440 : wscons관련된것은 삭제하고, device-major는 option에 추가한다.
코드:
# LCD
device-major   lcd     char 145
lcd0            at ssio?
#wsdisplay*      at lcd? console ?
#options         WSEMUL_VT100            # VT100 / VT220 emulation
#options         FONT_VT220L8x16
#options         FONT_VT220L8x10


3. kernel compile 및 rebooting: 이전글(evbarm관련)에서 참고 하시고 compile 하시고 rebooting한다.

4. device file node 만들기: 부팅후 아래 command처럼 device file node를 만든다.
코드:
# mknod /dev/lcd0 c 145 0


5. 테스트: 아래 파일을 cross-compile하거나 nfs로 booting하여 직접 compile한다.
-fbtest.c
신고

GUI Tool List

분류없음 2006.10.25 19:27 by LoofBackER
GUI 라이브러리 목록 링크
http://www.atai.org/guitool


FLTK - http://www.fltk.org/index.php

인용:
; 멀티 플랫폼
; UI 툴 제공
; 포럼
; Article, FAQ, Developer Document


GTK+ - http://www.gtk.org/
인용:
; 멀티 플랫폼
; 수많은 GNU 응용 프로그램에 사용됨
; 메일링 리스트
; FAQ, Tutorial, API Reference


wxWidgets - http://www.wxwidgets.org/
인용:
; 멀티 플랫폼
; 메일링 리스트, 게시판, 위키 등
; FAQ, Book, Reference, Presentations, Tutorials, Courses, Sample Code


NGL - http://home.gna.org/ngl/about.html
인용:
; 멀티 플랫폼
; OpenGL 응용 프로그램을 위한 C++ GUI 프레임웍
; UI 툴(RADtool) 제공
; XML, 테마 기능 제공
; 포럼 미흡
; Reference Manual, FAQ


XML User Interface Language (XUL) - http://www.mozilla.org/projects/xul/
인용:
; 멀티 플랫폼
; Mozilla Project에 사용
; XUL Planet (www.xulplanet.com - Tutorial, Developer Guide, References, Forum)
; Specification, Tutorial, Reference Manual


Crazy Eddie's GUI System - http://www.cegui.org.uk/modules/news/
인용:
; 멀티 플랫폼
; 툴 제공
; 포럼, 메일링 리스트, 위키
; API Reference, Tutorials, FAQ


Para GUI - http://www.bms-austria.c...rojects/paragui/index.php
인용:
; 멀티 플랫폼
; SDL (Simple DirectMedia Layer) 기반
; 포럼, 메일링 리스트
; FAQ, API Reference, Source Code Documentation


gameswf - http://www.tulrich.com/geekstuff/gameswf.html
인용:
; 플래쉬 swf파일을 게임 상에서 보여주는 GUI 라이브러리
; 메일링 리스트
; 문서화(FAQ) 미흡


3DControls - http://3dcontrols.free.fr/
인용:
; 3차원 공간상에서 입체적인 인터페이스를 보여줌
; 데모 프로그램 내장
; 포럼(불어, 영어)
; 아직 버그 많음
; 불어의 압박
신고

Windows XP TIP

분류없음 2006.10.14 19:25 by LoofBackER

1. 여러 파일 이름을 한꺼번에 바꾸자
윈도우즈 XP는 여러 개의 파일 이름을 한꺼번에 바꾸는 재주가 있다. 파일 형식이 서로 달라도 같은 이름을 붙일 수 있다.
이름을 바꿀 파일을 모두 고르고 마우스 오른쪽 버튼을 누른 다음 ‘이름 바꾸기’를 고른다.
윈도우즈 XP에서 여러 개의 파일 이름을 바꿀 때는 첫 번째 파일에 이름만 쓴다. 예를 들어 ‘PC사랑’이라고 하면 첫 번째 파일은 ‘PC사랑’이 되고 나머지 파일들은 ‘PC사랑 (1)’ ‘PC사랑 (2)’ 등으로 바뀐다. 만약 첫 번째 파일 이름을 ‘PC사랑 (10)’이라고 하면 그 다음부터는 ‘PC사랑 (11)’ ‘PC사랑 (12)’이 된다.

새 이름을 쓰고 엔터 키를 누른 다음 이름을 바꾼 파일 다음에 있는 것들은 새 이름 뒤에 1부터 숫자가 붙는다.

2. 갑자기 재 부팅 되는 윈도우즈 XP 때려잡기
윈도우즈 XP는 너무 민감한(?) 나머지 프로그램에 조그만 오류가 생기면 저절로 재 부팅 된다. 물론 그 오류가 심각할 때도 있지만 별 문제가 되지 않는 데도 PC를 재 부팅해서 이용자를 귀찮게 한다. 프로그램에 오류가 있어도 시스템이 재 부팅 되지 않게 해보자.
바탕화면의 ‘내 컴퓨터’ 아이콘을 마우스 오른쪽 버튼으로 누르고 ‘속성’을 고른 다음 ‘시스템 등록정보’ 창의 ‘고급’ 탭에서 ‘시작 및 복구’ 칸의 ‘설정’ 버튼을 누른다.
‘시스템 오류’ 칸에 있는 ‘자동으로 다시 시작’의 체크 표시를 없애고 ‘확인’ 버튼을 누른다.

이제 윈도우즈 XP가 제멋대로 꺼지지 않는다.

3. 오류 보고 창 나타나지 않게 하기
윈도우즈 XP부터는 프로그램들이 에러를 일으켰을 때 그에 대한 자세한 사항을 마이크로소프트사로 보고한다. 이런 오류를 매번 보고하는 것도 지겹고, 보고해도 해결되지 않으므로 오류 보고 창이 뜨지 않게 해보자.
시작 → 제어판 → 성능 및 유지 관리 → 시스템으로 간 뒤 시스템 등록정보 창이 뜨면 ‘고급’ 탭에서 아래에 있는 ‘오류 보고’ 단추를 누른다. 오류 보고 대화 상자에서 ‘오류 보고 사용 안 함’을 고르고 ‘확인’ 버튼을 누른다.

4. 성인광고 나가 있어~
성인광고 사이트도 아닌데 자꾸 성인광고가 뜬다. 한두 개 정도야 바로 닫아버리면 그만이지만 여러 개의 창이 마구 쏟아져 나오면 윈도우즈 XP가 먹통이 되기도 한다. 성인광고를 막아주는 프로그램이 있지만, 괜히 하드디스크 용량만 차지하므로 윈도우즈 XP 자체에서 해결하자.
인터넷 익스플로러 메뉴에서 도구 → 인터넷 옵션을 고른 다음 ‘일반’ 탭의 임시 인터넷 파일 항목에 있는 ‘설정’ 단추를 누른다. ‘설정’ 창이 뜨면 ‘개체보기’를 누른다.
탐색기가 뜨면서 파일 이름이 나온다. 이 중에서 sender control이라는 파일을 찾아서 지우면 성인광고 사이트가 뜨지 않는다.

‘개체보기’를 누르면 내 PC에 깔려있는 개체들이 보인다.

5. 내 컴퓨터에서 ‘공유 문서’ 없애기
윈도우즈 XP에는 여러 이용자가 같이 쓸 수 있는 공유 문서가 있다. 공유 문서에는 공유 그림, 공유 음악이 있는데 집에서 혼자 쓰는 사람에게는 필요 없다. 용량만 차지하는 공유 문서를 지워보자.
시작 → 실행 → regedit 라고 누르면 레지스트리 편집기를 띄운 다음,
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\DelegateFolders에 있는
{59031a47-3f72-44a7-89c5-5595fe6b30ee}를 찾아 지운다.

이 레지스트리를 지우면 공유 문서가 보이지 않는다.

6. ‘시작’에서 문서메뉴 지우기
문서 메뉴가 있으면 작업 했던 문서를 쉽게 불러올 수 있지만, 길게 늘어져 있어 지저분하다. 문서 메뉴를 잘 쓰지 않는다면 깔끔하게 지우자.
시작 → 실행 → regedit 라고 누르면 레지스트리 편집기가 뜬다.
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer 오른쪽에 마우스를 놓고 새로 만들기 → DWORD 값을 고른 뒤,
‘새 값’의 이름을 NoRecentDocsMenu 라고 바꾼 뒤 마우스로 두 번 눌러 값 ‘1’을 넣는다.

문서 메뉴가 없어졌다. 메뉴가 한결 깔끔해 보인다.

7. 바탕화면에 내 컴퓨터 불러오기
윈도우즈 XP를 깔고 나면 바탕화면에 휴지통만 보인다. 윈도우즈 98처럼 바탕화면에 기본 아이콘이 보이게 하려면 바탕화면에서 오른쪽 마우스 버튼을 누른 뒤 → 속성 → 바탕화면 → 바탕화면 사용자지정을 차례로 누르고 ‘내 바탕화면에 아이콘’에서 골라 누르면 된다.

8. 휴지통을 변기통으로 바꾸자
다른 아이콘들은 이름을 바꿀 수 있지만, 휴지통은 ‘이름 바꾸기’가 없다. 하지만 PC사랑 사전에 불가능이 있던가? 휴지통 변기통으로 변신시키자.
시작 → 실행 → regedit 라고 누르면 레지스트리 편집기가 뜬다.
HKEY_CLASSES_ROOT\CLSID\{645FF040-5081-101B-9F08-00AA002F954E}\ShellFolder의 오른쪽 창에 있는 attributes 키를 마우스 오른쪽 단추로 누른 뒤 ‘수정’을 고른다. ‘바이너리 값 편집’ 창의 ‘값의 데이터’ 칸에서 40 01 00 20 대신 70 01 00 20을 집어넣는다. CallForAttributes=dword:00000040 의 값만 지우자.

재 부팅하고 휴지통 위에서 마우스 오른쪽 버튼을 누르면 ‘이름 바꾸기’가 생긴다.

9. 입력 도구 모음 없애기
윈도우즈 XP ‘서비스 팩이 깔려 있다면 입력 도구 모음을 간단히 닫을 수 있지만 서비스 팩이 없다면 이것을 지울 수 없다. 입력 도구 모음은 한자를 입력할 때 편하지만 게임을 자주 하는 이들에겐 눈에 거슬릴 뿐 아무런 도움을 주지 않는다. 입력 도구를 쓰지 않는다면 이 방법으로 입력도구를 날려버리자.
제어판 → 국가 및 언어 옵션 → 언어 → 자세히 → 설치된 서비스에서 ‘추가’를 눌러 영어를 새로 넣는다. 그 다음 한글 입력기(IME2002)를 고르고 기본 설정 → 입력 도구모음에서 모든 체크를 끄면 도구가 사라진다.

10. 로그 온 할 때 예쁜 메시지 띄우기
회사, 학교 등 네트워크에 연결된 PC를 켜면 ‘로그온’ 화면이 뜬다. 이 곳에 톡톡 튀는 예쁜 메시지를 넣어보자.
시작 → 실행 → regedit 라고 누르면 레지스트리 편집기가 뜬다.
HKEY_LOCAL_MACHINE\Software\Microsoft\WindowsNT\CurrentVersion\Winlogon을 찾는다.
오른쪽 창에서 마우스 오른쪽 버튼을 누르면 뜨는 ‘새로 만들기’ 메뉴에서 ‘문자열 값’을 고른 뒤, 문자열 이름을 LegalNoticeText 라고 써 넣고 엔터 키를 누른다. 이미 있는 파일이라면 새로 만들지 않아도 된다.
앞에서 만들어 놓은 문자열을 마우스로 두 번 누르면 ‘문자열 편집’ 대화 상자가 나타난다.
‘값 데이터’ 상자에 화면에 표시할 내용을 써 넣고 ‘확인’ 버튼을 누른다.
같은 방법으로 LegalNoticeCaption 이라는 문자열 값을 만들고 ‘값 데이터’에 메시지 상자의 제목을 적은 뒤 ‘확인’ 버튼을 누른다. PC를 껐다 켜면 메시지 상자가 표시된다.

11. URL 입력은 단축 키로 간단히!
PC사랑 홈페이지에서 지난달 기사를 찾아보고 싶을 때 주소 창에 www.ilovepc.co.kr을 모두 적지 않아도 된다. ilovepc만 쓰고 Ctrl+Enter 키를 누르면 http://www와 co.kr이 저절로 써진다.
.com로 끝나는지, co.kr이나 net으로 끝나는지 기억나지 않을 때 활용하면 편하다.

12. ‘드라이버가 맞지 않는다’는 메시지가 떠요!
윈도우즈 XP의 기본 드라이버를 쓰다가 부품 회사에서 만든 드라이버를 깔려고 하는데 ‘호환성 테스트에 통과하지 못했다’는 메시지가 종종 뜬다. MS가 테스트하지 않아 성능을 믿을 수 없다는 내용이다. 많은 드라이버가 테스트를 거치지 않았지만 쓰는 데는 이상이 없다. 그렇다면 이 메시지를 굳이 띄울 필요가 없다.
‘내 컴퓨터’를 마우스 오른쪽 버튼으로 누르고 ‘속성’을 고른 다음, ‘하드웨어’ 탭에서 ‘드라이버 서명’을 누른다. 여기서 ‘무시’를 고르면 다시는 호환성 메시지가 뜨지 않는다.

‘무시’를 고르면 드라이버를 깔 때 호환성 여부를 묻지 않는다.

13. 시스템 복원이 컴퓨터를 느려지게 한다?
‘시스템 복원’은 만일의 사고를 대비해 시스템 내용을 그대로 기억하는 것이다. 오류가 발생하면 사고가 나기 전 상태로 돌아가기 위해서다. 파일을 읽고, 쓰고, 지울 때마다 system volume information 폴더에 시스템 복원용 백업 파일이 저장된다. 이 때문에 PC 속도가 느려지는데, ‘시스템 복원’을 끄면 속도가 한결 빨라진다.
‘내 컴퓨터’ 아이콘을 마우스 오른쪽 버튼으로 누르고 ‘속성’을 고른다. 시스템 등록정보’ 창이 열리면 ‘시스템 복원’ 탭을 누른 다음 ‘시스템 복원 사용 안 함’을 고르고 ‘확인’ 버튼을 누르면 된다.

시스템 복원을 끄면 PC가 한결 빨라진다.

14. 하드가 이유 없이 데이터를 읽을 때는?
아무런 작업도 하지 않는데 드르륵~ 거리며 하드디스크를 읽는 소리가 난다. 본체의 HDD LED도 깜박인다. 왜 아무런 명령을 내리지 않은 하드디스크가 작동을 할까? ‘인덱싱 서비스’ 때문일지 모르므로 이 명령을 끈다. 인덱싱 서비스는 하드에 있는 파일을 정리해 빨리 뜨게 해주지만 명령을 꺼도 PC를 쓰는 데 별 문제가 없다.
제어판 → 관리도구 → 서비스 → indexing service → 속성 → 사용안함을 누른 뒤 재 부팅하면 하드가 잠잠해진다.

15. 바탕화면 단축 아이콘에서 화살표를 지우자
프로그램 파일과 단축 아이콘을 구분하기 위해 단축 아이콘에는 ‘화살표’가 붙어 있다. 알아보긴 쉽지만, 왠지 지저분해 보인다. 화살표를 지우자.
시작 → 실행 → regedit 라고 누르면 레지스트리 편집기가 뜬다.
HKEY_CLASSES_ROOT\lnkfile를 고른 뒤 오른쪽 창에서 → isshortcut를 지우면 된다.


화살표가 없어 아이콘이 깔끔하게 보인다.

16. 폴더 창을 재 빨리 연다.
탐색기에서 폴더를 이동하다보면 폴더 안에 있는 파일을 읽어 들이는 속도가 느리다는 느낌을 지울 수 없을 때가 많다. 느린 속도 때문에 답답할 때는 다음과 같이 해보자.
시작 버튼 → 설정 → 제어판 → 폴더옵션을 차례로 고른다.
‘보기’ 탭의 ‘고급설정’ 칸에서 ‘폴더 및 바탕화면 항목에 팝업 설명 표시’ ‘압축된 파일과 폴더를 다른 색으로 표시’ ‘독립된 프로세스로 폴더 창 실행’ ‘네트워크 폴더 및 프린터 자동 검색’ ‘폴더 팁에 파일 크기 정보 표시’의 체크 표시를 없앤다.

이렇게 해두면 폴더 창이 조금 더 빨리 열린다.

17. 윈도우즈 XP에서 도스 게임 하기
윈도우즈 XP는 32비트 운영체제여서 16비트 도스 게임을 누르면 실행이 되지 않고 창이 꺼져 버린다. 도스 게임을 하고 싶다면 VDM(virtual DOS machine)이란 프로그램을 내려 받아 깐다. exe 실행파일을 골라 오른쪽 마우스 단추로 메뉴를 부른 뒤 run with VDMS를 누르면 된다. VDM은 PC사랑 홈페이지 ‘프로그램 타입 캡슐’에서 내려 받을 수 있다.

윈도우즈 XP에서 추억이 담긴 게임을 즐겨보자.

18. 메신저로 파일을 받을 수 없다고?
윈도우즈 XP는 인터넷 연결 방화벽 설정 부분이 있어서 외부에서 내 PC로 접속하는 것을 막는다. 하지만 메신저나 P2P 프로그램을 쓸 때는 이 방화벽 때문에 서로 자료를 주고받지 못한다. MSN 메신저를 비롯해 메신저가 P2P 프로그램으로 자료를 주고받을 때 방화벽이 가로막으면 다음과 같이 해결한다.
바탕화면의 ‘네트워크 환경’의 ‘속성’을 연 다음 ‘로컬 영역 연결’을 한번 누른다.
마우스 오른쪽 단추를 눌러 ‘속성’을 연 뒤 고급 → 인터넷 연결 방화벽을 끈다.

인터넷 연결 방화벽을 끄면 메신저나, P2P 프로그램을 문제없이 쓸 수 있다.

19. 윈도우즈 XP에서 디스크 검사를 하자
윈도우즈는 문제가 있을 때 ‘디스크 검사’를 해 오류를 고친다. 하지만 윈도우즈 XP는 윈도우즈 98과 달리 ‘디스크 검사’ 메뉴가 따로 없다. 보조프로그램에 등록 되어 있지도 않다. 그렇다고 디스크 검사가 아예 없는 건 아니다.
내 컴퓨터 → 로컬 디스크(c:)를 오른쪽 마우스로 메뉴를 불러 ‘속성’을 누른다.
‘도구’ 탭에 가면 ‘디스크 검사’가 있다. 모든 창과 프로그램을 다 끄고 검사하도록 한다.

윈도우즈 98보다 메뉴가 간단하고 검사가 빠르다.

20. 지워도 보이는 프로그램 지우기
안 쓰는 프로그램을 제어판 → 프로그램 추가/제거에서 지우지 않고 탐색기로 폴더만 지우면 프로그램 목록에 남는다. 이것이 쌓이고 쌓이면 프로그램 설치가 안 되고, 윈도우즈까지 느려진다. 흔적이 남지 않게 깔끔하게 지워보자.
시작 → 실행 → regedit 라고 누르면 레지스트리 편집기가 뜬다.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall에 들어가 지울 프로그램을 골라 지우면 된다.

21. 시스템 종료 창 바꾸기
여러 이용자가 하나의 PC를 쓸 때 시스템을 켜면 시작 화면이 뜬다. 여기에는 각 이용자가 등록되어있고 누가 어떤 프로그램을 쓰는지 간단히 나와 있다. 내가 무엇을 할지 다른 사람이 보는 게 싫다면 윈도우즈 98처럼 이름만 보이므로 보안이 더 낫다. 윈도우즈 98처럼 바꿔보자.
시작 버튼 → 설정 → 제어판 → 사용자 계정을 고른 다음 ‘사용자 로그온 또는 로그오프 방법변경’을 누른다.
‘새로운 시작 화면 사용’의 체크 표시를 없애고 ‘옵션 적용’ 버튼을 누르면 로그 창이 고전적인 형태로 바뀐다.

‘새로운 시작 화면 적용’을 누르면 윈도우 98처럼 시스템 종료 창이 바뀐다.

22. 꼭꼭 숨겨진 윈도우즈 XP 관리 프로그램들
윈도우즈 XP의 시작 버튼 → 실행을 누르면 ‘실행’ 창이 열린다. 여기에 명령을 써넣으면 작업이 바로 실행된다. ‘실행’ 창에 쓸 수 있는 명령어와 하는 일은 다음과 같다.

compmgmt.msc 컴퓨터 관리와 관련 시스템 도구 창을 연다.
diskmgmt.msc 디스크 관리 창을 띄운다.
eventvwr.msc 윈도우즈 메시지가 담긴 이벤트를 본다.
gpedit.msc 도메인 또는 액티브 디렉토리나 PC에 저장되어 있는 조직 단위에 연결된 그룹 정책 개체를 편집하는 ‘로컬 컴퓨터 정책’을 연다.
perfmon.msc 시스템 성능을 감시하고 로그와 경고를 기록한다.
secpol.msc ‘로컬 보안설정’을 열어 도메인의 PC 보안 정책을 정의하게 도와준다.
devmgmt.msc 하드웨어 장치 목록을 보고 각 장치에 대한 특성을 정하는 ‘장치관리자’ 창을 연다.
dfrg.msc ‘디스크 조각모음’ 창을 연다.
fsmgmt.msc 공유 폴더를 띄운다.
lusrmgr.msc 로컬 이용자를 확인한다.
rsop.msc ‘정책의 결과 집합’ 창을 연다.
services.msc ‘서비스’ 창을 띄운다.

23. 메뉴를 빨리 빨리
제원이 낮은 PC를 쓰고 있다면 창이 뜰 때 나타나는 갖가지 효과를 없애 창을 빨리 띄워보자.
시작 → 실행 → regedit 라고 누르면 레지스트리 편집기가 뜬다.
HKEY_CURRENT_USER\ControlPanel\desktop에서 MenuShowDelay을 살펴보면 400
으로 되어있다. 이 값을 0으로 고쳐주면 된다.

0으로 바꾸면 메뉴가 빨리 뜬다.

24. 하드디스크 파티션 하기
윈도우즈 98에서는 ‘fdisk’라는 프로그램으로 하드디스크를 나눠 썼다. 윈도우즈 XP는 이 fdisk프로그램이 없어진 대신 파티션을 쉽게 할 수 있는 메뉴가 생겼다.
시작 → 설정 → 제어판 → 관리도구 → 컴퓨터 관리 → 디스크 관리에 들어가면 하드디스크의 갖가지 정보가 뜬다. 파티션 하려는 하드디스크에 오른쪽 마우스를 눌러 메뉴를 불러온다. 파티션 뿐 아니라 하드디스크를 매만질 수 있는 갖가지 메뉴가 있다.

윈도우즈 XP는 복잡한 하드디스크 파티션을 간단히 끝낸다.

25. 내 PC 시각이 맞지 않을 때
작업 표시 줄 오른쪽에 있는 시계를 1분 1초도 틀리지 않게 맞춰보자. 먼저 작업 표시 줄의 시계를 누르고 ‘인터넷 시간’이란 탭을 누른다. ‘인터넷 시간 서버와 자동으로 동기화’를 체크하고 ‘지금 업데이트’를 누르면 된다.

인터넷 서버에 있는 정확한 시계와 연결되어 제대로 된 시간을 보여준다.

26. 회사 이름과 이용자 이름 바꾸기
윈도우즈 XP를 처음 깔 때 넣었던 회사 이름과 이용자 이름을 바꾸고 싶다면, 레지스트리를 매만지자.
시작 → 실행 → regedit 라고 누르면 레지스트리 편집기가 뜬다.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion 에 들어가면 RegisteredOrganization과 RegisteredOwner라는 값이 있다.
RegisteredOrganization은 회사 이름, RegisteredOwner는 사용자 이름이다.
입맛에 맞게 바꾼 뒤 재 부팅하면 바뀐다.

27. CD롬 자동 삽입 통지 막기
윈도우즈 XP는 윈도우즈 98처럼 ‘자동 삽입 통지’ 메뉴가 없다. CD롬을 넣으면 CD롬 내용이 알아서 뜨는데, 이 기능이 귀찮다면 레지스트리를 만져 끄면 된다.
시작 → 실행에서 regedit 라고 쓰고 엔터 키를 누르면 레지스트리 편집기가 뜬다.
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet001\Services\Cdrom에서 Autorun값을 `0`으로 하면 CD를 넣어도 CD가 자동 실행되지 않는다.

28. 인터넷 화면이 제대로 안보일 때
인터넷 게임을 하려고 하는데 화면이 제대로 뜨지 않는다면 어떻게 할까? 인터넷을 띄우면 그 사이트에 맞는 개체가 깔리는데, 이 개체가 제대로 깔리지 않을 때 이런 일이 일어난다.
제어판 → 인터넷 옵션 → 일반 탭에서 임시 인터넷 파일의 ‘설정’ 메뉴를 찾는다.
‘개체 보기’를 누르면 내 PC에 깔려 있는 갖가지 개체들이 보인다. <Ctrl + A> 키를 눌러 ‘전체 선택’을 한 뒤 Del 키를 눌러 지운다. ‘예’를 누르면 말끔히 지워진다. 다시 인터넷 사이트에 들어가면 개체가 깔리기 전에 ‘예’ ‘아니오’라는 창이 뜬다. ‘예’를 누르면 개체가 바로 깔려 인터넷 화면을 제대로 볼 수 있다.

'예‘를 눌러야 화면을 띄우는 데 필요한 개체가 깔린다.

29. ‘도움말 및 지원’ 메뉴 지우기
윈도우즈를 쓰다가 모르는 것이 있으면 ‘도움말’을 보지만 사실 별 도움이 되진 않는다. 차라리 이것을 없애면 프로그램이 띄울 때 조금 더 빨리 뜬다.
시작 → 실행 → regedit 라고 누르면 레지스트리 편집기가 뜬다.
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer에 간 뒤 ‘새로 만들기’ 에서 DWORD값을 만든다.
이름을 NoSMHelp으로 하자. 마우스를 두 번 눌러 데이터 값을 불러와 ‘1’이라고 넣자.
재 부팅 하면 ‘도움말 및 지원’ 메뉴가 뜨지 않는다.

30. 쓰지 않는 MSN 익스플로러 지우기
윈도우즈 XP를 처음 깔면 MSN 익스플로러가 깔려 있다. MSN 익스플로러는 MSN과 핫메일을 쓰는 사람에게 유용한 프로그램이지만 쓰지 않는다면 이 프로그램을 지워 하드디스크 용량을 늘이자.
시작 → 모든 프로그램 → MSN Explorer 아이콘에 마우스를 갖다 댄다. 오른쪽 마우스 버튼으로 메뉴를 불러와 속성을 누른다. 등록정보 창이 뜨면 ‘대상 찾기’를 누른다.
Setup 폴더를 열어 보면 msnunin이란 프로그램이 있는데, 이것이 MSN Explorer을 지우는 프로그램이다. 마우스로 두 번 눌러 시작 메뉴에 있는 내 PC에서 MSN 익스플로러를 지운다.

꼭꼭 숨어 있는 이 파일을 누르면 MSN 익스플로러가 지워진다.

31. 종료 로고만 뜨고 전원이 안 꺼질 때
‘시스템 종료’를 누르면 ‘이제 시스템 전원을 끄셔도 됩니다’라는 창만 뜨고 꺼지지 않는 일이 있다. 이럴 때 제어판 → 전원 옵션 → APM 탭으로 들어가 ‘최대 절전 모드 사용’을 체크하면 된다.

32. CD를 굽고 있는 도중 PC가 먹통이 될 때
주로 4배속 아래의 낡은 CD-RW 드라이브에서 이런 일이 생긴다.
제어판 → 시스템 → 하드웨어 탭의 ‘장치 관리자’로 들어간다.
IDE ATA, ATAPI 컨트롤러를 눌러 광학 드라이브가 꽂힌 보조 IDE 채널을 두 번 누른다. 전송모드가 DMA로 되어 있다면 PIO로 바꾼 뒤 적용을 누른다.

PIO 모드로 바꾸면 오래된 CD-RW라도 CD를 척척 구워낸다.

33. 640 × 480 해상도로 띄우기
윈도우즈 XP 제어판 → 디스플레이 등록정보를 보면 800 × 600이 가장 낮은 해상도로 되어 있지만, 640×480 해상도를 불러 올 수 있다.
제어판 → 디스플레이 → 설정의 ‘고급’ 단추를 누른다.
‘어댑터’ 탭에 들어가면 아래에 ‘모든 모드 표시’라고 되어있다. 이곳을 누르면 640×480 해상도에 256 컬러로 바꿀 수 있다.

256 컬러가 아니면 뜨지 않는 고전 게임을 즐길 때 좋다.

34. 바탕 화면 보기 아이콘 만들기
바탕화면 보기 아이콘은 모든 창을 최소화 시킬 때 편하다. 이 아이콘을 실수로 지웠다면 당황하지 말고 새로 만들어보자. 시작 → 보조프로그램 → 메모장을 열어 다음과 같이 쳐 넣는다.

[Shell]
Command = 2
IconFile=explorer.exe,3
[Taskbar]
Command=ToggleDesktop

‘다른 이름으로 저장’을 고른 뒤 ‘바탕화면보기.scf'라고 저장하면 끝난다.

저장한 파일은 작업 표시 줄의 ‘빠른 실행’ 안에 끌어다 놓자.

35. 메신저 광고 메시지는 이제 그만!
인터넷 사이트에 가입하지 않았는데도 MSN 메신저를 통해 스팸 쪽지가 계속 날아온다. 이것은 사실 MSN 메신저와 아무 상관이 없다. 메시지를 보내는 이들은 무작위로 IP 주소를 뽑아 윈도우즈 NT 계열의 기본 서비스인 내부 네트워크를 이용해 광고성 쪽지를 보내는 것이다. 이 쪽지를 받지 않으려면 다음과 같이 한다.
제어판 → 관리도구 → 서비스 → Messenger에서 시작 유형을 ‘시작 안함’으로, 서비스 상태를 ‘중지’로 하면 된다.

이제 지긋지긋한 스팸 메시지가 오지 않는다.

36. 윈도우즈 포맷하기 전, 즐겨찾기 백업은 필수
윈도우즈를 포맷하고 다시 깔고 나서 해야 할 일이 너무 많다. 즐겨찾기 사이트를 일일이 다시 등록하는 일도 장난이 아니다. 하지만 즐겨찾기가 저장되는 디렉터리만 알고 있으면 이런 노가다(?)를 하지 않아도 된다.
윈도우즈를 포맷하기 전에 c:\doc-uments and settings\이용자 이름\favorites를 통째로 다른 드라이브에 복사해 놓자. 윈도우즈를 다시 깐 뒤 같은 디렉터리로 복사한다. 인터넷의 즐겨찾기를 열면 고스란히 사이트가 들어있다. 하지만 전에 저장했던 순서까지 그대로 열리는 것은 아니므로 약간 손봐야 한다.

37. 하위 폴더를 재 빨리 연다
하위 폴더를 열려면 현재 폴더를 마우스로 두 번 누르거나 그 옆에 있는 +를 고른다. 따라서 디렉토리가 여러 단계로 되어 있으면 필요한 것을 열기위해 이일을 여러 번 반복해야 한다. 하지만 맨 아래에 있는 것을 단 한번에 여는 방법이 있다.
작업하려는 폴더를 고른 뒤 숫자 키보드에 있는 * 키를 함께 누르면 아래에 있는 모든 폴더가 열린다.

38. 지운 파일 되살리기
탐색기나 내 컴퓨터에서 실수로 중요한 파일을 지우기 십상이다. 하지만 걱정하지 않아도 된다. 도구 모음에 있는 ‘실행 취소’ 버튼을 누르면 사라졌던 것이 다시 나타나기 때문이다. 단축 키는 <Ctrl + Z>다.
TR> 
‘실행취소’ 버튼을 누르면 방금 전 내린 명령이 무효가 된다.

39. 파일 이름이 안 바뀌네?
아무 작업도 하지 않는데 파일 이름이 안 바뀔 때가 있다. 이럴 때 재 부팅하지 않고 이름을 바꾸는 법을 살짝 공개한다. 파일을 고른 뒤 오른 쪽 메뉴를 불러와 ‘속성’을 누른다. 이 곳에서 이름을 바꿔보자 안 바뀌던 파일 이름이 손쉽게 바뀐다.

파일 복사 중이면 이 방법을 써도 바뀌지 않는다.

40. 내가 원하는 시각에 PC 끄기
시작 → 실행에서 ‘tsshutdn 시간(초)’을 넣자.
PC를 1분 뒤에 끌 거라면 tsshutdn 60, 1시간 뒤에 끌 거라면 tsshutdn 3600이라고 넣으면 된다. 시간이 되면 바로 종료 되는 것이 아니라 만약을 위해 30초를 더 센다.

취소하려면 꺼지기 전에 <Ctrl +C> 키를 누르면 된다.

41. 한글 자판 먹통 됐을 때
인터넷 검색을 하다가 갑자기 한글 자판이 안 먹힐 때가 있다. 이럴 때 PC를 재 부팅 하지 말고 간단하게 해결하자.
대부분 왼쪽 Alt를 한번 누른 뒤 한/영 키를 누르면 한글로 바뀐다. 이 방법이 안 되면 왼쪽 <Shift + Alt> 키와 마우스 오른쪽 버튼을 누른 뒤 한/영 키를 누르면 된다.

42. 윈도우즈 XP의 숨겨진 복사 재주
파일을 복사할 때 같은 파일이 있으면 겹쳐 쓸 것인지 물어보는 창이 뜬다. 모두 겹쳐 쓸 때 ‘모두 예’라는 항목은 편하지만, 겹쳐 쓰지 않고 이어서 복사하려면 ‘아니오’를 일일이 눌러야 된다. 이럴 때 중복된 것만 빼고 복사하는 ‘모두 아니오’가 있으면 얼마나 편할까?
윈도우즈 XP는 이런 재주가 숨겨져 있다. Shift 키를 누른 상태에서 ‘아니오’를 눌러보자. 똑같은 파일은 건너뛰고 복사 되지 않은 파일만 복사된다.

많은 파일을 복사할 때 편하다.

43. 인터넷 익스플로러 이름 바꾸기
인터넷 창 타이틀 맨 윗부분을 보면 Microsoft Internet Explorer란 꼬리표가 달려있다. 이 꼬리표 이름을 내맘대로 바꿔보자. 시작 → 실행 → regedit 라고 누르면 레지스트리 편집기가 뜬다. HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main를 찾은 뒤 편집 → 새로 만들기 한 뒤 Window Title 이라고 써 넣는다. 만들었다면 왼쪽 마우스 단추를 두 번 눌러 이름을 써 넣는다. PC를 재 부팅하면 이름이 바뀐다.


인터넷 창 위에 있던 Microsoft Internet Explorer란 글자를 내 맘대로 바꾸었다.

44. 시작 페이지 고정하기
인터넷을 하다 보면 성인사이트가 첫 페이지로 뜨는 일이 종종 있다. 인터넷 옵션에서 홈페이지를 바꿔도 계속 뜨는 사이트가 정말 짜증난다. 레지스트리를 매만져 이런 문제를 말끔히 털어버리자.
시작 → 실행에서 regedit 라고 쓰고 엔터 키를 누르면 레지스트리 편집기가 뜬다.
HKEY_LOCAL_MACHINE\Software\Microsoft\InternetExplorer\Main, HKEY_CURRENT_USER\Software\Microsoft\InternetExplorer\Main으로 가서 둘 다 Start_Page 의 값을 처음에 띄우려는 페이지 주소로 바꾼다.
그 다음 왼쪽 창 Main 에서 오른쪽 클릭 ‘사용 권한’ 고른 뒤 쓰고 있는 계정을 고른 다음 밑에 고급 → 편집을 누른다. 값 설정에서 ‘거부’에 체크 하면 끝난다.

이 곳에서 사이트 이름을 바꾼다.

45. MSN 메신저 6의 숨겨진 이모티콘들
MSN 메신저에는 재미있는 이모티콘이 들어 있다.
메신저를 띄운 뒤 이 단어들을 채팅창에서 쳐 넣으면 재미있는 이모티콘이 뜬다.
(st) = 비
(%) = 수갑
(pl) = 접시
(ci) = 담배
(li) = 번개
(tu) = 거북이
(xx) = 엑스박스
(yn) = 검지와 중지

46. 윈도우즈의 보기 설정을 한결같이
파일 목록을 특정한 방식, 예를 들어 ‘큰 아이콘’으로 표시하거나 ‘자세한 정보’와 함께 표시할 때, 모든 폴더의 보기 옵션을 이와 같은 방식으로 두루 적용할 수가 있다.
윈도우즈 탐색기의 ‘도구’ 메뉴에서 ‘폴더 옵션’을 고른다.
‘보기’ 탭의 ‘폴더 보기’ 칸에서 ‘모든 폴더에 적용’ 버튼을 누른 다음 ‘폴더 보기’ 창이 열리고 모든 폴더에 적용할 것인지 물으면 ‘예’ 버튼을 누른다.

다른 폴더에서도 보기 옵션을 일일이 정하지 않아도 된다.

47. 드라이브 순서 바꾸기
윈도우즈 98 제어판에서 바꿀 수 있던 ‘드라이브 순서’가 윈도우즈 XP에는 없다. 하지만 꼭꼭 숨겨져 있을 뿐 바꾸지 못하는 것은 아니다.
시작 → 실행 → diskmgmt.msc를 치면 ‘디스크 관리’가 뜬다. 바꿀 드라이브를 누르고 오른쪽 단추로 메뉴를 불러온 다음 ‘드라이브 문자 및 경로 변경’을 누르면 된다. 가상 드라이브와 CD롬이 뒤죽박죽일 때 이 곳에서 순서를 바꿔 정리할 수 있다.

운영체제가 깔린 드라이브는 바꿀 수 없다.
TR> 
48. 윈도우즈 미디어 플레이어 9 지우기
윈도우즈 미디어 플레이어 9는 영화를 보기에 좋지만, 실시간 방송이 뜨지 않는 일이 종종 있다. 이것은 윈도우즈 미디어 플레이어 9가 실시간 서비스인 VOD를 제대로 알아채지 못해서다.
이런 이유로 윈도우즈 미디어 플레이어 9를 지우고 종전 버전으로 돌리려면 시작 → 실행 → RunDll32 advpack.dll,LaunchINFSection %SystemRoot%INFwmp.inf,Uninstall이라고 치면 된다.

윈도우즈 미디어 플레이어 9를 깔기 전으로 돌릴 수 있다.

49. 누가 내 PC 만졌어!
내 PC가 언제 켜졌는지 남이 내 PC를 만졌는지 알 수 있는 방법이 있다.
시작 → 프로그램 → 보조프로그램의 메모장에서 다음과 같이 써 넣자.
@echo off
echo Windows 부팅 >>c:list.txt
echo %date% %time% >>c:list.txt
echo. >>c:list.txt
파일 이름을 list.bat라고 저장한 뒤 저장한 파일을 시작 프로그램에 놓는다.

c 드라이브에 들어가 list.tct 파일을 보면 PC를 켠 흔적이 남아있다.

50. 깔지마! 깔지 말란 말야!
사이트에 접속할 때마다 바탕 화면에 깔리는 아이콘을 일일이 지우는 것도 지겹다. 웹 사이트 아이콘을 바탕화면에 깔지 못하게 해보자.
제어판 → 인터넷 옵션 → 보안에서 ‘웹 컨텐트 영역’을 ‘인터넷’으로 고른다.
‘사용자 지정 수준’을 누른다. ‘바탕 화면 항목 설치’를 찾아 ‘설치 안함’을 고르면 된다.

이제 바탕화면에 웹 사이트 아이콘이 깔리지 않는다.

51. 머리글과 바닥글 없애기
인터넷 화면을 문서로 뽑으려면 파일 메뉴의 ‘인쇄’를 누르면 된다. 하지만 프린터에 http://www.ilovepc.co.kr/record_detail_read.php?NO=15879같은 경로가 같이 찍혀 나와 지저분하다. 이것이 싫으면 파일 → 페이지 설정을 눌러 ‘머리글’과 ‘바닥글’에 있는 칸을 깨끗이 지운다음 인쇄하면 된다.
TD style="PADDING-RIGHT: 10px; PADDING-LEFT: 15px; PADDING-BOTTOM: 0px; PADDING-TOP: 0px">
'&w&b페이지 &p / &P'라는 부분을 지우면 된다.

52. 키보드 없이 키보드를 친다?
윈도우즈 XP는 키보드가 없이 PC를 쉽게 쓸 수 있도록 ‘화상 키보드’를 지녔다. 이것은 글자 그대로 키보드 모양을 화면에 띄워 마우스로 눌러 글자를 띄우거나 프로그램을 실행시킨다. 시작 → 프로그램 → 보조프로그램 → 내게 필요한 옵션 → 화상 키보드를 누르면 된다.

화상 키보드는 움직임이 불편한 장애자들을 위해 만든 프로그램이다.

53. 플로피디스크 읽지 마!
부팅한 뒤나 탐색기를 띄웠을 때 윈도우즈는 무작정 A 드라이브인 플로피디스크를 읽는다. 이것은 하드웨어가 잘 달려 있는지를 윈도우즈가 알아보는 것이다. 이런 일을 없애도 윈도우즈를 쓰는 데 아무런 이상이 없으므로 윈도우즈가 하드웨어를 검색하는 명령을 고치자.
제어판을 띄워 ‘관리도구’를 열고 ‘서비스’ 아이콘을 골라 shell hardware detection 항목을 두 번 누른다. ‘시작 유형’을 ‘자동’으로 맞추고 ‘확인’ 버튼을 누른다.
‘서비스’ 창에서 shell hardware detection 항목을 골라 시작 유형을 ‘자동’으로 바꾼다. 이렇게 하면 플로피디스크를 읽지 않는다.

플로피 디스크를 자주 쓰지 않는다면 ‘자동’으로 바꾸자.

54. 최대 절전 모드 해제로 하드디스크 용량을 확보하자
제어판의 ‘전원 옵션’ 가운데 최대 절전 모드를 쓰면 윈도우즈는 얼마 뒤 메모리에 담긴 데이터를 하드디스크에 저장하고 적은 전기만 쓰면서 대기모드로 들어간다. 이 때 하드디스크 용량을 500MB 정도 차지한다.
대기모드를 쓰지 않는 이에게 이 옵션은 하드디스크 용량만 잡아먹는 쓸데없는 것이다. 바탕화면에 대고 마우스 오른쪽 버튼을 눌러 ‘속성’을 눌러 ‘디스플레이 등록정보’ 창을 띄운다. 화면보호기 항목에서 ‘전원’ 버튼을 누르고 전원 옵션 등록정보를 보자. ‘최대 절전 모드’ 탭에서 체크 표시를 없앤다.

55. 응답이 없는 프로그램 빨리 닫기
윈도우 XP 응답이 없는 프로그램은 시간이 얼마 지나야 닫히게 된다. 기다린다고 응답 없는 프로그램이 다시 살아나는 것도 아니므로 이 시간을 무시하고 바로 끄자.
시작 → 실행에서 regedit 라고 쓰고 엔터키를 치면 레지스트리 편집기가 뜬다.
HKEY_CURRENT_USER\Control Panel\Desktop에서 HungAppTimeout를 왼쪽 마우스로 두 번 눌러 1000으로 고치면 된다.

56. 내가 쓰는 윈도우즈 XP가 정품일까?
윈도우즈 XP는 불법 복제를 쓰지 못하게 인터넷으로 정품 등록을 한다. 이것을 흔히 ‘인증을 받는다’고 한다. 하지만 인증을 받지 않고도 정품처럼 쓰는 불법 OS가 널리 퍼져 있다. 정품인데도 인증을 받지 않으면 적어도 30일 동안 작동한다. 과연 내가 쓰는 윈도우즈 XP는 인증을 받은 것일까?
시작 → 실행 → oobe/msoobe /a라고 치면 인증 창이 뜬다.

정상적인 OS이면 그림처럼 인증을 받았다는 메시지가 보인다.

57. MSN 메신저를 지우자
프로그램 추가/제거에서는 MSN 메신저를 지울 수 없다. 지우고 싶다면 시작 → 프로그램 → 보조프로그램에 있는 메모장으로 c:\windows\servicepackfiles\sysoc.inf 파일을 연다.
msmsgs=msgrocm.dll,OcEntry,msmsgs.inf,hide,7이라고 되어 있는 줄을 찾은 뒤,
msmsgs=msgrocm.dll,OcEntry,msmsgs.inf,7로 바꿔주면 시작 → 제어판 → 프로그램 추가/제거 → windows 구성요소 추가/제거에 MSN 메신저 체크박스가 뜬다. 이 박스를 끄면 MSN 메신저를 지울 수 있다.

MSN 메신저를 쓰지 않는다면 이 곳에서 지우면 된다.

58. L2 캐시 매만져 PC를 재빨리 돌리자
윈도우즈 XP는 CPU의 L2 캐시를 알아채 PC를 재빨리 돌린다. 하지만 데이터가 많아지거나 멀티태스킹을 할 때 캐시를 읽지 못해 순간적으로 느려질 때가 있다. 캐시를 고정시켜 운영체제가 일일이 캐시 메모리를 찾는 수고를 덜어주자.
시작 → 실행 → regedit 라고 누르면 레지스트리 편집기가 뜬다.
KEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SessionManager\Memory Management를 찾은 뒤 SecondLevelDataCache를 고른다.
그 다음 내 CPU에 맞는 캐시를 넣으면 된다. 바탕화면에 있는 ‘내 컴퓨터’를 누른 뒤 오른쪽 메뉴를 불러와 ‘속성’을 누르면 내 CPU 정보가 뜬다.
TD style="PADDING-RIGHT: 10px; PADDING-LEFT: 15px; PADDING-BOTTOM: 0px; PADDING-TOP: 0px">
10진수로 바꾼 뒤 캐시를 써 넣으면 된다.

59. 다이렉트 X의 최신 버전 깔기
시작 → 실행에서 dxdiag라 쳐 넣고 엔터를 치면 다이렉트 X 버전 뿐 아니라 갖가지 정보가 뜬다. 다이렉트 X가 8.1 이하가 깔려있다면 9.0을 새로 까는 것이 좋다. 게임속도가 재빨라지기 때문이다. 다이렉트 X 9.0을 내려받고 싶다면 시작 → windows update에서 인터넷 익스플로러 창이 뜨면 ‘업데이트 검색’을 누른 다음 중요 업데이트 및 서비스 → 업데이트 검토 및 설치를 눌러 ‘지금 설치’를 누르면 된다.

다이렉트 X 9.0이상이 깔려있는지 확인하자.

60. 인터넷 익스플로러를 전체 화면으로 보자
인터넷 익스플로러를 전체 화면으로 시원시원하게 보는 방법이 있다.
인터넷 창을 띄우고 F11 키를 눌러도 되지만 항상 전체 화면으로 띄우려면 레지스트리를 매만져야 한다. 시작 → 실행 → regedit 라고 누르면 레지스트리 편집기가 뜬다.
HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main 으로 간 다음 오른쪽 창에서 FullScreen을 찾는다.
FullScreen을 두 번 눌러 no를 yes로 바꾸면 된다.

(출처 : '윈도우XP의 숨겨진 기능 60가지' - 네이버 지식iN)

 
신고
1 

카테고리

분류 전체보기 (107)
::::::Dairy::::: (5)
:::::what?::::: (1)
:::::Computer::::: (5)
:::::Idea::::: (2)
:::::Want::::: (1)

달력

«   2006/10   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        

티스토리 툴바