요 근래 Ruby on Rails로 만들어 보고 싶은 게 있어서 Rails를 좀 보고 있습니다. 아직 잘은 모르지만 그 심플함과 강력함에 깜짝 놀라고 있는데요, 우분투(Ubuntu)에 깔려있는 레일즈(Rails)버전이 2.3 버전대라 3.0 버전 이상으로 올라가고 싶어서 레일즈 버전을 올렸습니다.

레일즈 버전을 올리는 방법은 아래와 같이 하면 됩니다. ;)
sudo apt-get install ruby-full rubygems
sudo su -
export REALLY_GEM_UPDATE_SYSTEM=true
gem update --system
exit
gem install rails

레일즈 버전은 깔끔하게 올라갔는데, 문제는 그 뒤더군요. 예제를 따라한다고 rails new blog를 입력하는 순간... 아래와 같은 오류가 발생하면서 더이상 진행이 안되었습니다. OTL...
/usr/bin/ruby1.8 extconf.rb
checking for sqlite3.h... no
sqlite3.h is missing. Try 'port install sqlite3 +universal' or 'yum install sqlite3-devel'
*** extconf.rb failed ***

Could not create Makefile due to some reason, probably lack of necessary libraries and/or headers. Check the mkmf.log file for more details. You may need configuration options.

그래서 이걸 해결할려고 구글신에게 여쭈었더니... 아래와 같이 하면 된다고 알려주시더군요. 역시 구글신 쵝오... ㅠㅠ(http://stackoverflow.com/questions/3458602/sqlite3-ruby-install-error-on-ubuntu)
sudo apt-get install libsqlite3-dev

아아... 역시 구글은 최고인 것 같아요... OTL...
고향에 내려가서 포스팅을 한다는게... 내려가서 정신없이 지내다보니 연휴가 끝난 지금에서야 한자 적어 올립니다. ^^

작년에는 개인적으로 많은 일들이 있었지만... 올 해도 개인적으로 많은 일을 만들(?) 예정이라, 상당히 긴장감있는 한 해가 될 것 같습니다. ^^;;; 많은 일들(?)에 대해서는 진행하는 대로 족족 블로그에 포스팅할 예정이니 기대해주세요 ;)

드디어 음력으로도 한 해가 시작되었습니다. 올 한 해 원하시고 바라시는 일 다 이루시길 기원합니다.
모두 새해 복 많이 받으시고, 좋은 소식 많이 전해주세요. ;)
맡고 있는 일의 특성상 텍스트 파일에서 데이터 추출하여 패턴을 분석하는 일이 종종 있습니다. 특히 지금이 딱 그런 시즌인데요, 오늘은 이상하게 텍스트 파일을 열자마자 엑셀말고 다른 방법을 찾아야겠다는 생각이 들더라구요. ^^;;; 그래서 틈틈이 연습했던 루비(Ruby) 언어를 사용해서 한 번 해봐야겠다고 생각했습니다.

그.런.데... 루비를 써야겠다고 말하고 실행을 옮기려던 순간... 옆의 상사가 그러더군요.

"C로도 할 수 있는데...."

예~, 맞습니다. 물론 C로도 할 수 있지요. 다만... 루비를 쓰면 문자열 처리가 편리하고 큐와 리스트 자료구조, 정렬 등등의 기능을 좀더 편하게 쓸 수 있습니다. 뭐, 이런 빵빵한 지원이 루비같은 스크립트 언어의 강점 아니겠습니까? ^^;;; 그리고 코딩하기도 편하고 마음도 가볍고 말이죠. ㅎㅎ

이런 설명을 하려고 하는 찰나.... 이런 말이 다시 들렸습니다.

"C로도 할 수 있는데, 왜 시간 낭비를 하지...?"

아아아아아아아아아아아아아아아아아아아아앍~!!!! 정말 믿고 싶지 않은 이야기에요. ㅠㅠ 저 말을 듣고 이게 꿈인가 싶었습니다. 상사도 저랑 같은 생각을 하고 있을 줄 알았거든요. ㅠㅠ 그런데 시간 낭비라니요. ㅠㅠ 목적에 맞는 언어를 택해서 작업을 편하게 하려고 한게 시간 낭비라니... 이런게 시간 낭비면 항상 우리는 오래된 돌도끼 같은 도구를 쓰면서 몸으로 때우며 묵묵히 작업을 반복해야 하는 건가요? 어휴... 아무리 하드웨어가 강한 회사라지만... 이래서야 원... ^^;;;;;

스크립트 언어를 배우는 건 절대 시간 낭비가 아닙니다~!!!
그리고 새로운 것을 배우고 시도하는 것을 막는 건 프로그래머의 앞 길을 막는 겁니다.


쓸쓸한 날씨처럼 기분도 쓸쓸하네요. ^^;;;;


후배의 소개로 내일... 이 아니라 오늘이군요. 오늘 "아키텍트를 꿈꾸는 사람들" 스터디 그룹에서 간단히 발표를 하게 되었습니다. ^^;;; 제가 말 주변이 좋지 않아서 발표를 잘 할 수 있을지 의문이지만... 일단 초대 받았으니 가서 열심히 하고 오겠습니다. ㅎㅎ

강남역 토즈 2호점에서 한다던데... 서울 사람들은 참 멋진 것 같아요 ;) 주말에도 열심히 공부하고 토론하는 것 보면... 정말 부럽다는 생각도 들고 대단하다는 생각도 듭니다. 스터디 그룹에 계시는 분들이 다들 대단하셔서 제가 가서 정보를 전달해 드리는 건 크게 의미가 없을 것 같아서 그냥 개발 스토리 위주로 PPT를 만들었는데... 잘한 짓인지는 모르겠네요. ㅠㅠ

일단 다녀와서 후기를 남기겠습니다~ ㅎㅎ
그럼 다들 좋은 밤 되세요 ;) 



2011년을 되돌아보면 개인적으로 이룬 것이 많은 해였습니다. ^^ 가족 문제도 모두 무사히 해결되었고 회사일도 큰 탈 없이 잘 넘어갔거든요. ^^)-b 그리고 무엇보다도~ OS 프로젝트에 대한 제 책이 세상에 나온게 가장 큰 성과가 아니었나 싶군요. ^^;;;;

2012년도 2011년처럼 큰 탈 없이 잘 지나갔으면 좋겠습니다. 그리고 시간이 된다면 재미있는 프로젝트도 하나 하면서 자료를 정리해두고 싶네요. 혹시 모를(?) 나중을 위해서 말이지요 ;)

지금까지 관심을 가져주셔서 감사드리구요, 2012년도 잘 부탁드리겠습니다. ^^

그럼 새해 복 많이 받으세요 ^^)/~

<출처 플리커 - http://www.flickr.com/photos/jessfeldon/3359967900/sizes/z/in/photostream/>


업무 특성상 연말 & 연초가 아주 바쁘지만 억지로 시간을 내서 틈틈이 책을 보고 있습니다. 무슨 책인데 그렇게 열심히 보고 있냐하면... 한 권은 "만들면서 배우는 리스프 프로그래밍"이구요, 다른 한 권은 "카산드라 완벽 가이드"입니다. ^^;;;;

사실 리스프 언어에 대해서 소문(괄호로 시작해서 괄호로 끝난다는...)은 많이 들어서 한 번 구경하고 싶었는데, 때마침 이 책이 손에 떨어져서 내심 상당히 기뻤습니다. 그래서 받자마자 읽어내려가기 시작했는데, 책이 정말 재미있게 구성되어 있고 내용도 아주 깔끔하게 잘 정리되어 있더군요. ㅠㅠ)-b

아시는 분은 아시겠지만... 저는 리스프 언어를 하나도 모릅니다. ㅠㅠ 그런데, 이 책은 정말 눈으로 읽어내려가기만 해도 머리속에서 그림이 그려지는 듯한 느낌이랄까요? 저 같은 초보자를 위해 재미있는 스토리와 그림을 사용해서 만화책처럼 엮어서 그런지 정말 보기가 편합니다. ㅠㅠ)-b 그래서 리스프 언어에 대한 거부감도 별로 안생기는 것 같아요. ㅠㅠ

혹시 저처럼 리스프 언어가 궁금하셨다면 이 책을 적극 추천합니다. ^0^)-b 번역서지만 번역도 잘 되어있어요 ;)

<만들면서 배우는 리스프 프로그래밍, 한빛미디어 - 출처 yes24>



"만들면서 배우는 리스프 프로그래밍"이 만화책같다면 "카산드라 완벽 가이드"는 교과서같은 느낌입니다. 카산드라라는 분산 DB가 탄생한 이유부터 구축, 적용까지 광범위한 내용을 다루고 있더라구요. 제가 DB 쪽은 아직 깊이 다루어본 적이 없어서 NoSQL이 필요한 이유같은 부분에서 약간 공감이 적긴하지만, 나름대로 조금씩 읽고 있습니다. ^^;;;;


언젠가는 저도 NoSQL이 필요한 시점이라고 느낄날이 올지도 모르니까요. ㅎㅎ 카산드라에 대해서 궁금하신 분이라면 이 책을 한 번 보시는 것도 괜찮을 것 같습니다. ^^)/~


<카산드라 완벽 가이드, 한빛미디어 - 출처 yes24>


아아... 그러고보니 이제 조금있으면 크리스마스로군요. ㅠㅠ 이 회사에 입사한 뒤로는 크리스마스 분위기를 느껴본 적이 없는 것 같아요. ㅠㅠ 이거 원... 때려치고 마음에 여유가 있는 다른 곳으로 옮기던지 해야겠어요. ㅎㅎ 적어도 크리스마스 기분은 느낄 수 있는 곳 말이에요. ;)

그럼 즐거운 밤 되세요 ;)

ps) 좋은 책을 소개해주신 한동훈님께 감사드립니다. ;)
      매번 신경써주셔서 감사해요 ^^)/~


요즘 저희가 만든 제품이 세계 곳곳(?)으로 나가고 있어서, 정신없이 하루하루를 보내고 있습니다. 그러다가 어떤 문제를 만났는데요, 이 문제의 해법에 대해서 의견이 분분하던 차에 제가 그 문제의 수정에 합류하게 되었습니다. ^^;;;

문제를 간단하게 설명드리자면, 어떤 시점이 되면 배열의 특정 필드의 값이 A라는 값으로 초기화되는 것이었는데... 이 값이 언제 어떻게 초기화되는지를 명확하게 찾을 수가 없었습니다. 그래서, 제가 일단 이 값이 A라는 값으로 초기화되었는지 매번 확인하여 값이 바뀌었으면  배열 값이 백업되어있느 곳에서 값을 가져와서 A를 정상적인 값으로 바꿔주는 방식으로 제안을 했습니다. 왜냐하면, 배열의 값이 "A"로 바뀌기 때문이었지요.

그래서 다들 동의하고 그렇게 코드를 수정했는데요, 다른 팀에서 코드 리뷰를 하다가... 배열에서 A 값으로 바뀌는 인덱스만 배열과 백업 배열을 비교한 뒤에 값을 덮어쓰자는 의견을 냈습니다. 가만히 생각해보니 이게 더 맞는 수정이더군요. 사실 우리가 배열의 값이  "A"로 바뀌는 상황만 봤는데, 사실 지금은 A지만 나중에는 B가 될 여지도 있었거든요. ㅠㅠ

하지만, 이미 코드는 수정되어 릴리즈된 뒤라 더 이상 고칠 수가 없어서 그냥 두었습니다. ㅠㅠ 왠지 찝찝한게 다시 문제가 생길 것 같은 느낌이 들어서 마음이 무겁네요.

제가 한 곳에 꽂히면 계속 그 부분만 파고드는 스타일이라서... 넓게 생각하지 못한 것이 많이 아쉽군요. 다음 부터는 조금 더 여유를 갖고 생각한 뒤 문제를 풀어야겠습니다. 에혀... 이런 걸 보면 전 아직 멀었나봅니다. ^^;;; 기본 중에 기본에서 흔들리니 원....

내공이나 쌓으러 가야겠군요. ㅠㅠ
그럼 즐거운 주말 되세요 ;)

굵게 표시된 부분이 오타가 수정된 부분입니다.


==== 1권의 오탈자 내용 ====

*. 79 Page, 아래에서 5 번째 줄

보호 모드는 IA-32e 모드로 전환하려면 공식적으로 거쳐야 하는 모드로, 32비트 윈도우나 리눅스 OS가 동작하는 기본 모드입니다.


*. 80 Page, 위에서 6 번째 IA-3e 모드를 IA-32e 모드로 수정

IA-32e 모드


*. 80 Page, 아래에서 5 번째줄

리얼 모드에서 전환할 수 있는 모드는 공식적으로 보호 모드뿐 이며, 보호 모드에서는 가상 8086 모드나 IA-32e 모드, 다시 리얼 모드로 전환할 수 있습니다. 시스템 관리 모드는 모든 모드에서 진입할 수 있고, 처리가 끝나 이전의 운영 모드로 복귀하거나 리셋을 통해 리얼 모드로 진입할 수 있습니다.


*. 80 Page, 아래에서 3 번째 줄

화살표가 연결되지 않은 리얼 모드에서 IA-32e 모드로 전환하는 것은 불가능하며, 무리하게 시도하면 리셋이나 예외가 발생할 수있습니다(실제 편법을 사용하면 가능하긴 하지만 여기서는 다루지 않습니다).


*. 83 Page, [그림 3-3]에서 128비트 XMM 레지스터(16개), 64비트 RIP, 64비트 RFLAGS, CR8 레지스터 부분 수정됨

[그림 3-3].PNG


*. 85 Page의 "여기서 잠깐"의 시작에서 6번째 줄

곱셈 명령은 AX와 오퍼랜드를 곱한 후, 그 결과를 DX:AX나 혹은 AX에 저장하도록 설계되었습니다.


*. 87 Page 아래에서 5번째 줄부터...

그렇다면 어떻게 해야 할까요? 프로세서 제조사에서는 이런 경우를 대비하여 무조건 분기 명령어(jmp)에 예외를 두었습니다.

즉, 무조건 분기 명령어의 오퍼랜드의 크기는 기본 64비트로 하여 전체 어드레스 범위에서 이동이 가능하도록 한 것입니다.

[그림 3-5]는 RIP 상대 어드레스를 사용하여 표현 가능한 어드레스 영역과 무조건 분기 명령어를 사용해서 접근할 수 있는 영역에 대해

나타낸 것입니다.


*. 88 Page [그림 3-5]

           [그림 3-5].png


*. 113 Page 아래에서 8번째 줄

그 위쪽에서 두 파일은 a.c와 b.c로부터 생성되는 것을 알 수 있습니다.


*. 141 Page 위에서 6번째 줄, 154 Page 아래서 5번째 줄, 2861 Page 위에서 7번째 줄, 2872 Page 맨 밑줄

xor byte [ HEADNUMBER ], 0x01 ; 헤드 번호를 0x01과 XOR 하여 토글(0->1, 1->0)


*. 142 Page, 아래서 3번째줄

x86 프로세서의 스택은 [그림 5-3]과 같이 데이터가 삽입될 때마다 스택의 상위(Top)를 나타내는 스택 포인터 레지스터(SP)가 낮은 어드레스(0x00에 가까운 어드레스)로 이동합니다.


*. 143 Page, 밑에서 10째줄

또한 스택은 넉넉한 것이 좋으므로 스택 포인터 레지스터(SP)와 베이스 포인터 레지스터(BP)를 0xFFFF로 설정하여, 스택 영역의 크기를 세그먼트의 최대 크기로 지정하겠습니다.


*.149 Page, 아래에서 13번째 줄

        ret 12                   ; 호출한 함수로 복귀한 후, 스택에 삽입된 파라미터 3개를 제거(3*4) "ret" "add esp, 12"와 같은 역할

        ^^^^^^

            ret 수행 후 스택 포인터(SP)를 12만큼 더함. 보호모드 코드이므로

            레지스터의 기본 크기 및 스택의 기본 크기가 32비트(4바이트)이기 때문에 4*3 = 12만큼 더함


*.151 Page, 위에서 15번째 줄

        ret 4                     ; 호출한 함수로 복위한 후, 스택에 삽입된 파라미터 1개를 제거(1*4) "ret" "add esp, 4"와 같은 역할

        ^^^^^^^

             ret 수행 후 스택 포인터(SP)를 4만큼 더함. 보호 모드 코드이므로

             레지스터의 기본 크기와 스택의 기본 크기가 32비트(4바이트)이기 때문에 4*1 = 4만큼 더함


*. 161 Page, 아래서 5번째줄 Code

; 512 - ( $ - $$ ) % 512 : 현재부터 어드레스 512까지


*. 213 Page, 가장 아래번째 줄

보호 모드 엔트리 포인트(EntryPoint.s) 코드에서 최초로 실행되는 C 코드입니다.


*. 251 Page, [그림 9-2] 페이지 디렉터리 엔트리 부분에서 PS1을 PS로 수정

[그림 9-2].PNG


*. 261 Page, 위에서 4번째 줄

kSetPageEntryData( &( pstPML4TEntry[ 0 ] ), 0x00, 0x101000, PAGE_FLAGS_DEFAULT, 0 );


*. 263 Page, [그림 9-5]의 XMSE를 SMXE로 수정


[그림 9-5].PNG


*. 266 Page, 소스 코드에서 위에서 10째줄

// 1 비트 P, RW, US, PWT, PCD, A, D, PS, G, 3 비트 Avail, 1 비트 PAT, 8 비트 Reserved,


*. 283 Page, [표 10-2] IA32_EFER 레지스터의 비트 구성에서 7번째 줄 LMA 항목

LMA 읽기 전용 -1로 설정되면 프로세서 모드가 IA-32e 모드(호환 모드 또는 64비트 모드)임을 나타내며, 0으로 설정되면 프로세서 모드가 기타 모드임을 나타냄


*.283 Page, 밑에서 10째줄

[표 10-2]에서 보는 것과 같이 IA-32e 모드 활성화 여부는 비트 8에 위치하는 LME 비트와 관계가 있고 이 비트를 1로 설정하면 IA-32e 모드를 활성화할 수 있습니다.


*.288 Page [예제 10-2] 위에서 1째줄

#ifndef __MODESWITCH_H__

#define __MODESWITCH_H__


*. 333 Page 아래쪽과 351 Page 가운데 부분, 482 Page 윗부분

BOOL kChangeKeyboardLED( BOOL bCapsLockOn, BOOL bNumLockOn, BOOL bScrollLockOn )

{

    int i, j;


    // 키보드에 LED 변경 커맨드 전송하고 커맨드가 처리될 때까지 대기

    for( i = 0 ; i < 0xFFFF ; i++ )

    {

        // 입력 버퍼(포트 0x60)가 비었으면 커맨드 전송 가능

        if( kIsInputBufferFull() == FALSE )

        {

            break;

        }

    }

...   생략 ...


*. 334 Page 위에서 3번째 줄

// 입력 버퍼(포트 0x60)로 LED 상태 편경 커맨드(0xED) 전송

kOutPortByte( 0x60, 0xED );

... 생략 ...


*. 341 Page 위에서 15번째 줄, 357 Page 아래에서 5번째 줄

BOOL kIsUseCombinedCode( BYTE bScanCode )


*. 341 Page, 위에서 18번째 줄, 357 Page, 아래에서 2번째 줄

BOOL bUseCombinedKey = FALSE;


*. 343 Page 아래쪽359 Page 가운데 부분

void UpdateCombinationKeyStatusAndLED( BYTE bScanCode )

{

    BOOL bDown;

    BYTE bDownScanCode;

    BOOL bLEDStatusChanged = FALSE;


    // 눌림 또는 떨어짐 상태처리, 최상위 비트(비트 7)가 1이면 키가 떨어졌음을 의미하고

    // 0이면 눌림을 의미함

    if( bScanCode & 0x80 )

    {

        bDown = FALSE;

        bDownScanCode = bScanCode & 0x7F;

    }

    else

    {

        bDown = TRUE;

        bDownScanCode = bScanCode;

    }


*. p.363 페이지 (02.Kernel64/Source/Keyboard.h)의 Down을 On으로 변경
// 키보드의 상태를 관리하는 자료구조
typedef struct kKeyboardManagerStruct
{
    // 조합 키 정보
    BOOL bShiftDown;
    BOOL bCapsLockOn;
    BOOL bNumLockOn;
    BOOL bScrollLockOn;
    
    // 확장 키를 처리하기 위한 정보
    BOOL bExtendedCodeIn;
    int iSkipCountForPause;
} KEYBOARDMANAGER;


*. 365 Page, 아래에서 12번째 줄

BOOL kIsUseCombinedCode( BYTE bScanCode );


*. 365 Page, 아래에서 17번째줄 변수 선언 부분 굵게 처리

void Main( void )

{

    char vcTemp[ 2 ] = {0, };

    BYTE bFlags;

    BYTE bTemp;

    int i = 0;


    ... 생략 ...



*. 383 Page의 [그림 12-7]에서 16~31 비트의 값(크기를 기준 주소로 수정)

그림 12-7.PNG


*. 386 Page, 위에서 21번째 줄 30번째 줄

#define GDT_FLAGS_LOWER_TSS ( GDT_FLAGS_LOWER_DPL0 | GDT_FLAGS_LOWER_P

#define GDT_FLAGS_UPPER_TSS ( GDT_FLAGS_UPPER_G )


*. 428 Page 아래에서 18번째 줄, 436 Page 아래에서 3번째 줄, 600 Page 아래에서 9번째 줄, 606 Page 위에서 7번째 줄

%macro KLOADCONTEXT 0      ; 파라미터를 전달받지 않는 KLOADCONTEXT 매크로 정의


*. 483 Page, 위에서 10번째 줄, 굵게 표시

// 키를 저장하는 큐와 버퍼 정의

static QUEUE gs_stKeyQueue;

static KEYDATA gs_vsKeyQueueBuffer[ KEY_MAXQUEUECOUNT ];


*. 492 Page의 위쪽

사실 14장은 앞 장과 비교해서 변한 것이 거의 없습니다.


*. 498 Page의 "GCC 헤더 파일에 정의된 가변 인자 매크로와 리스트"의 위쪽 문단

각 매크로와 데이터 타입이 어떻게 정의되어 있는지 코드를 직접 확인해 보겠습니다.


*. 609 Page, 첫 번째 줄  굵게 표시

{ "createtask", "Create Task", kCreateTestTask },


*. 620 Page의 [그림 18-3]

그림 18-3.png


*. 627 Page, "TCB 할당 및 해제 함수의 코드"에서 위로 2번째 줄

다음은 앞서 설명한 내용에 따라 구현한 TCB 할당 및 해제 함수의 코드입니다. ID를 처리하는 부분을 제외하고는 평이한 코드이므로

이해하는데 큰 어려움이 없을 것입니다. TCB 자료구조에 추가된 stLink 필드는 18.2.4절에서 살펴보겠습니다.


*. 660 Page의 위에서 4째줄

콘솔 화면의 주변을 돌면서 문자를 출력하는 태스크와 자신의 ID에 해당하는 위치에 바람개비를 출력하는 태스크를 작성했습니다.


*. 741 Page 위에서 7 번째 줄

태스크의 수를 제한하려면 임계 영역 진입 여부를 나타내는 플래그와 잠금 횟수를 나타내는 카운터, 그리고 임계 영역에 진입한 태스크의 ID만 있으면 처리할 수 있습니다.


*. 742 Page 아래에서 8번째 라인

만약 잠근 태스크가 해제를 요청하는 것이고 잠긴 횟수가 2 이상이면 중복으로 잠긴 것이므로 횟수만 1 감소시키고 실제로 해제하는 작업은 수행하지 않습니다.


*. 751 Page 그림 [20-4]

[그림 20-4].PNG


*. 769 Page 맨 윗 라인

콘솔 셸 파일에는 태스크를 생성하고 종료하는 태스트 때문에 killtask 커맨드의 기능이 수정되고 동기화 기능을 테스트하는 testmutex 커맨드가 추가되었습니다.


*. 791 Page의 밑에서 셋째줄

하지만 멀티코어 프로세서 환경일 경우 자식 스레드는 다른 코어에서 실행될 수 있으며, 이런 경우 태스크를 즉시 대기 리스트로 옮길 수 없습니다.


*. 815 Page의 밑에서 8째줄

[그림 21-4]의 위를 보면 콘솔 셸(태스크 ID: 0x100000000)과 유휴 태스크(태스크 ID: 0x200000001)의 태스크 플래그를 보면 최상위 바이트가 각기 0x60과 0x58로 시작하는 것을 볼 수 있습니다.


*. 825 Page [그림 22-2]

[그림 22-2].PNG


* 843 Page, 밑에서 10 째줄

또 FPU 예외 처리가 끝나면 다시 0으로 설정해서 같은 태스크가 FPU를 사용할 때 예외가 발생하지 않도록 해야 합니다.


* 876 Page, 밑에서 두번째 줄

1KB 블록 2개를 생성한 후 1KB 블록 하나를 할당해주면 남은 블록은 [그림 23-3]과 같이 1KB 블록 1개, 2KB 블록 1개, 4KB 블록 1개가 됩니다.


* 879 Page, 위에서 3번째 줄 그림 제목

[그림 23-6] 블록 크기에 맞지 않는 메모리를 할당받았을 때 할당된 메모리의 구조(4.3MB 할당)


* 933 Page 위에서 7 째줄

하지만, LBA 어드레스 모드일 때는 레지스터가 LBA 어드레스로 통합되어 섹터 번호 레지스터는 LBA 어드레스의 0비트~7비트, 실린더 LSB 레지스터는 8비트~15비트, 실린더 MSB 레지스터는 16비트~23비트, 드라이브/헤드 레지스터의 헤드 필드는 24비트~27비트를 저장합니다.


* 1049 Page, 위에서 6번째 줄 자료구조에서 아래의 굵게된 부분 추가

typedef struct kFileHandleStruct
{
    // 파일이 존재하는 디렉터리 엔트리의 오프셋
    int iDirectoryEntryOffset;
    // 파일 크기
    DWORD dwFileSize;
    // 파일의 시작 클러스터 인덱스
    DWORD dwStartClusterIndex;
    // 현재 I/O가 수행중인 클러스터의 인덱스
    DWORD dwCurrentClusterIndex;
    // 현재 클러스터의 바로 이전 클러스터의 인덱스
    DWORD dwPreviousClusterIndex;
    // 파일 포인터의 현재 위치
    DWORD dwCurrentOffset;
} FILEHANDLE;


* 1120 Page 위에서 6 째줄

// 파일 이름 삽입

kMemCpy( vcBuffer, pstentry->d_name, kStrLen( pstEntry->d_name ) );


* 1161 Page, [그림 27-5]의 가장 마지막 부분

[그림 27-5].PNG


*. 1174 Page, 위에서 11 번째 줄

iRealReadCount = MIN( gs_stRDDManager.dwTotalSectorCount -

dwLBA, iSectorCount );


*. 1174 Page, 밑에서 9 번째 줄

iRealWriteCount = MIN( gs_stRDDManager.dwTotalSectorCount -

dwLBA, iSectorCount );


*. 1186 Page, 밑에서 16 번째 줄

iRealReadCount = MIN( gs_stRDDManager.dwTotalSectorCount -

dwLBA, iSectorCount );

*. 1186 Page, 밑에서 2 번째 줄

iRealWriteCount = MIN( gs_stRDDManager.dwTotalSectorCount -

dwLBA, iSectorCount );


*. 1239 Page, 위에서 10째줄과 13째줄

// LSB 제수 래치 레지스터(포트 0x3F8)에 제수의 하위 8비트를 전송

// MSB 제수 래치 레지스터(포트 0x3F9)에 제수의 상위 8비트를 전송


*. 1246 Page, 위에서 2째줄과 5째줄

// LSB 제수 래치 레지스터(포트 0x3F8)에 제수의 하위 8비트를 전송

// MSB 제수 래치 레지스터(포트 0x3F9)에 제수의 상위 8비트를 전송


*. 1251 Page, [예제 28-3]의 소스 부분
#include "FileSystem.h" <-- Normal 글씨체로 수정
#include "SerialPort.h" <-- Bold 글씨체로 수정

*. 1280 Page, 위에서 5번째줄, 맨 앞의 "-"를 "*"로 대체하고 위의 *와 같은 레벨로 들여쓰기 수정
* BIOS의 롬 영역 중에서 0x0F0000~ 0x0FFFFF 범위 내에 존재

* 1291 Page, [그림 29-13]에서 전달할 로컬 APIC INTIN을 전달할 로컬 APIC LINTIN으로 수정, 0x000x04로 수정
[그림 29-13].PNG  
* 1399 Page, [그림 31-1]에서 오른쪽 아래에 있는 "ㅁ: 비활성화 된 부분"의 사각형을 회색으로 변경
[그림 31-1].PNG

==== 2권의 오탈자 내용 ====

*. 1528 Page, 아래에서 11번째 줄

태스크 풀을 관리하는 함수를 수정하는 방법은 33.2.2절에서 살펴보므로, 이번 절에서는 수정된 태스크 풀 자료구조만 살펴보고 넘어가겠습니다.


*. 1539 Page, 위에서 7번째 줄, 1580 Page, 아래에서 12번째 줄

// 나머지 코어에서 현재 태스크와 같은 레벨을 검사


*. 1612 Page, 아래에서 2째줄

하지만, 7부가 지나면 곧 다시 돌아오니 너무 아쉬워 할 필요는 없습니다.


*. 1655 Page, 위에서 5번째 줄

브레슨햄 직선 알고리즘을 사용한 선 그리기 함수의 코드 - 최적화 후


*. 1672 Page, 35.2.1절에서 아래로 8번째줄

하지만, 문자 정보가 비트맵으로 들어 있으므로 확대하거나 축소했을 때 문자가 깨끗하게 표시되지 않고, 굵게하거나 기울일려면 해당 스타일의 비트맵을 모두 생성해야하는 단점이 있습니다.


*.1764 Page, 아래에서 10번째줄, kDrawMouse -> kDrawCursor로 수정

kDrawCursor( &stScreenArea, pstVideoMemory, iX, iY );


*. 1882 Page, 위에서 7번째 줄

이 절에서 작성할 윈도우 매니저는 더 이상 테스트 코드가 아닌 실제 코드로서, 키보드와 마우스 데이터를 이용해 윈도우로 이벤트를 전달하는 기능과 업데이트를 수행하는 기능을 구현합니다.


*. 1946 Page, 위에서 4번째 줄

//----------------------------------------------------------------------------------------------

// 제목 표시줄 그리기

//----------------------------------------------------------------------------------------------

// 제목 표시줄을 채움

        if( bSelectedTitle == TRUE )
        {
            stTitleBarColor = WINDOW_COLOR_TITLEBARACTIVEBACKGROUND;
        }
        else
        {
                stTitleBarColor = WINDOW_COLOR_TITLEBARINACTIVEBACKGROUND;

        }


kInternalDrawRect( &stArea, ... 생략 ...)


*. 1951 Page, 위에서 6번째 줄

39장의 내용을 MINT64 OS에 추가한 뒤 make를 입력하면 Disk.img 파일이 생성됩니다.


*. 1994 Page, 위에서 6번째 줄 제목

41.1.1 Z 순서의 가장 아래에서 위로 그리는 알고리즘의 문제점


*. 1998 Page, 위에서 3번째 줄

윈도우 1은 자신의 영역에 포함된 픽셀 오프셋 5~7 부분을 비디오 메모리로 전송한 뒤 해당 영역의 비트맵을 모두 0으로 표시합니다.


*. 2027 Page, 아래에서 3번째 줄

특히 마우스 데이터를 처리하는 부분과 화면 업데이트 요청을 처리하는 부분은 조금만 수정하면 화면 업데이트 횟수를 많이 줄일 수 있기 때문에 속도에 목마른 우리에겐 아주 중요한 포인트입니다.


*. 2150 Page, 위에서 첫번째 줄

43장에서는 프로세서의 정보와 메모리 정보를 표시하는 시스템 모니터 태스크를 구현해 봤습니다. 


*. 2150 Page, 위에서 6번째 줄

44장에서는 다시 고전으로 돌아가 역사의 뒤안길로 사라졌던 콘솔 셸을 GUI 버전으로 부활시킬 것입니다.


*. 2169 Page, 위에서 7번째 줄 도움말

while( kGetKeyFromGUIKeyQueue( &stData) == FALSE)

        |---------- 그래픽 모드용 키 큐에서 데이터를 꺼내는 함수


*. 2182 Page, "44.3.2 콘솔 파일 수정"에서 아래 첫번째 줄

콘솔 파일은 그래픽 모드 지원을 위해 입출력 함수의 코드를 일부 수정하고, 그래픽 모드용 화면 버퍼와 키 큐를 추가했습니다.


*. 2309 Page 전체를 아래 내용으로 교체2309 페이지의 내용.PNG


*. 2400 Page, 아래에서 4번째 줄

MINT64 OS에는 아직까지 MSR에 읽고 쓰는 함수가 없으므로 MSR에 관련된 어셈블리어 함수부터 만들겠습니다.


*. 2546 Page, "[표 50-2] e_entry 필드의 세부 구성과 의미"를 "[표 50-2] e_ident[16] 필드의 세부 구성과 의미"로 변경


*. 2546 Page, 아래에서 7번째 줄

가장 먼저 할 일은 e_ident 필드의 상위 4바이트가 매직 넘버이므로, 파일의 첫 4바이트가 매직 넘버와 일치하는지를 검사하여 올바른 ELF64 파일인지 확인하는 것입니다.


*. 2548 Page, 아래에서 5번째 줄

현재 섹션의 타입에 따라 필드의 의미가 달라지며 자세한 내용은 [표50-6]을 참조


*. 2616 Page, 위에서 첫번째 줄

[그림 51-2]는 이러한 처리 과정을 나타낸 그림입니다.


*. 2625 Page 위에서 14번째 줄,  2641 Page 아래에서 8번째줄, 2785 Page 밑에서 7번째줄, 

// 현재 라인에서 남은 문자 수와 한 라인에 출력할 수 있는 문자 수 를 비교하여 작은 것을 선택


*. 2692 Page, 위에서 12번째 줄

g_stGameInfo.iBlockX = -1;

g_stGameInfo.iBlockY = -1;


*. 2693 Page, 위에서 10번째 줄

게임판의 블록이 존재하는지 여부는 게임 자료구조의 vvbBoard 필드에 저장되어 있습니다.


*. 2694 Page, 위에서 5번째 줄

게임 자료구조에는 현재 게임판의 정보를 저장하는 vvbBoard 필드가 있으므로 움직이는 블록의 현재 좌표를 그대로 게임판에 저장하면 됩니다.


*. 2720 Page, 아래에서 13번째 줄

g_stGameInfo.iBlockX = -1;

g_stGameInfo.iBlockY = -1;


*. 2766 Page, 위에서 4번째 줄

텍스트 뷰어에 한글 출력 기능을 추가하려면 한글인지를 판단해 2바이트씩 출력하는 코드만 추가하면 되기 때문입니다.


*. 2846 Page, 위에서 1번째 줄

만든 첫 번째 한글 입력 모듈은 오토마타를 사용했습니다.


*. TODO...


OS 제작을 시도해본 분들은 아시겠지만...

OS를 개발하려면 PC 하드웨어부터 OS 관련 지식까지 많은 정보가 필요합니다. ^^;;;


저 역시 책도 많이 보고 웹 사이트도 많이 찾아다녔는데요,

OS를 개발할 때 도움이 되었던 책과 사이트를 정리해둘 필요가 있는 것 같아서 한자 남겨둡니다.


OS를 개발하시는 다른 분들에게 도움이 되었으면 좋겠네요.



책 목록



사이트 목록


그럼 즐거운 OS 프로그래밍하세요 ;)
요즘 새로운 프로젝트 때문에 정신없이 하루하루를 보내다보니... 프로젝트 팀이 빌딩되고 약 2달이나 지나서야 제대로 회식다운 회식을 했습니다. ^^;;; 프로젝트 기간이 4개월 밖에 안되는 말도 안되는 프로젝트라 처음에 시작할 때는 모두 거부를 했지만... 일이 일이니만큼 위에서 밀어붙이는 바람에 다들 울며 겨자먹기로 시작했지요. ㅠㅠ

그래도 사람들 능력이 워낙 좋아서 막바지에 다다른 지금까지 꽤나 많은 일을 해냈습니다. "거의" 못할 것 같았던 일들을 "거의" 마무리하고 있거든요. 그래서 기분 좋게 한 잔하고 들어왔는데... 문득... 이런식으로 가다가는 점점 일정이 줄어드는 악순환을 면치 못하겠다는 생각이 들었습니다. ㅠㅠ

한 일은 많지만 야근과 과로로 쌓아 올린 탑이라 그런 생각이 드는 것 같네요. 이런 생각을 하고나니 기분이 싸악~ 다운되면서 우울해지더군요. 이 시간까지 잠도 잘 안오고... ㅎㅎ 병역특례로 어린 나이에 회사 생활을 시작했는데... 내년이 되면 딱 회사 생활한지 10년차가 되네요. 아참 중간에 학교 간다고 2년 쉬었으니 8년차군요. ^^;;;;

되돌아보면 그동안 앞만 보고 달려온 것 같습니다. 뭐, 젋었으니가 그랬겠지요. ㅎㅎ 이제 제 나이도 30을 넘어 30 중반을 향해 달려가는데... 슬슬 진로에 대해서 진지하게 고민할 때가 된 것 같다는 생각이드네요. 앞만 보고 달리기에는 너무 멀리 왔으니 방향을 잘 잡아야 할텐데 말입니다. 마음같아서는 컴퓨터하고 관련없는 사업을 하면서 컴퓨터는 취미로 했으면 좋겠는데... 절대 무리겠죠? ^^;;;

추운 밤에 머리가 복잡해서 한 자 남깁니다. 에궁... 조금 있으면 출근해야겠군요. ㅎㅎ
그럼 다들 좋은 밤 되세요 ;) 
오늘 제가 가끔 들리는 이정환닷컴 사이트에서 재미있는 글을 읽었습니다. 제목은 조선일보가 "국민연금 더 내게 해달라고 때쓰는 이유"인데요... 국민연금을 낼 수 있는 소득 상한선을 월 소득 375만원에서 더 높여 달라는 내용이더라구요.

처음에는 상한선이 없어지는게 뭐 대수인가 생각했는데... 글을 읽다보니 부자들은 소득 상한선 제한이 없어져야 좋은 거라는 걸 알았습니다. ㅡ_ㅡa... 아무래도 더 많이 내고 노후에 더 많이 가져가려는 수작인 것 같은데.... 정말 부자들은 이런데 머리를 잘 굴리는 것 같아요. ㅠㅠ 신문사에서 이런 글을 쓰다니... 어찌될 세상인지 정말... 어휴...

서민들은 진짜 매달 국민연금이 빠져나가는 것만 해도 좀 부담인데 말이죠. ㅠㅠ 컴퓨터만 너무 붙들고 있지 말고 이런 부분도 신경을 좀 써야겠다는 생각이 드는군요. 에궁...

시간나시면 한 번 정독해보시는 것도 좋을 것 같습니다. ^^
그럼 좋은 하루 되세요 ;)
아아... 점점 프로젝트 마감은 다가오고... 책임의 압박은 슬슬 강해지는 이 시점에서... 어쩌다보니 버그 하나를 발견하게 되었습니다. ㅠㅠ 그것도 다들 보는 앞에서 "제대로" 말이지요. ㅠㅠ 그래서 빼도 박도 못하고 제가 디버깅을 맡아서 하게 되었는데... 얼래? 생각보다 이게 간단한 문제가 아닌겁니다. ㅠㅠ

재현성은 확실한데 시간이 1시간쯤 걸려서 아무리 바쁘게 움직여도 하루에 10번 재현하기가 쉽지 않더군요. 디버깅에 쏟은 시간을 따지면... 지난주 금요일부터해서 꼬박 3일간(야근까지 포함)을 투자했는데요, 실제로 버그의 원인은 아주 단순한데 있었습니다. ㅠㅠ 전형적인 커뮤니케이션 오류로 인한 버그라고 할까요? ㅠㅠ

잠시 설명을 하자면... 블럭들을 관리하는 블럭 풀이 있는데 이 블럭 풀은 4바이트짜리 구조체로 이루어져 있습니다. 그리고 그 안에는 A라는 필드가 있는데요, 이 필드 값은 무조건 0이라고 합의 된 상태였습니다. 아니, 합이 된듯한 상태라고 하는게 맞을 것 같습니다. 실제로 안그런 코드가 있었으니... ㅠㅠ

블럭 풀에서 파라미터로 넘어온 블럭과 같은 블럭을 삭제하는 코드는 위의 합의된 내용을 바탕으로 모든 필드가 일치하는 블럭을 찾도록 되어 있었는데요, 블럭 구조체에서 A는 블럭의 속성을 나타내지만, ID로는 사용되지 않는 필드였기 때문에 호출하는 쪽에서 A 필드의 값을 dummy로 넘겨버린거죠. ㅠㅠ

이 Dummy Data 때문에 블럭 풀에서 제거되었어야 할 블럭이 제거되지 않아서 여러 곳에 같은 블럭이 할당되어 사용되었고, 이로 인해 문제가 발생했던 겁니다. ㅠㅠ 아아... 그런데 이런게 왜 내가 테스트할 때 나올까요? ㅠㅠ

문제를 해결하는 코드를 넣고 테스트를 돌린 뒤 새벽 바람을 맞으며 퇴근하는데... 어찌나 씁쓸하던지... 눈물이 앞을 가리더군요. ㅠㅠ 이 문제가 빙산의 일각이 아니길 바라면서 한자 끄적여 봅니다.

다들 좋은 밤 되세요 ㅠㅠ 
제가 운영하는 OS 개발 사이트(http://www.mint64os.pe.kr)에 어떤 분께서 Object File을 coff 형식으로 생성할 수 있는 방법이 있느냐고 물어보시더라구요.

사실 제가 gcc의 각종 옵션에 익숙치 않아서....(매번 기본 옵션으로만 쓰다보니.. ^^;;;;) 구글 신님께 여쭤봤는데... 디버그 정보와 함께 오브젝트 파일을 coff 파일로 생성하는 옵션을 발견했습니다.

gcc -gcoff main.c

뭐, 당연한 거지만 gcc가 coff 파일을 지원해야 가능합니다. ^^;;;
보다 자세한 내용은 http://www.hanb.co.kr/network/view.html?bi_id=1382 내용을 참고하세요 ;)

ps) 혹시 디버그 정보 없이 coff 파일 형식으로 오브젝트 파일을 생성하는 옵션 아시는분 있으세요? ㅠㅠ
웹로그도 그렇고 코딩도 그렇고 모두 소셜이 대세인 요즘... 계속 제 머리 속을 맴도는 생각이 있습니다. 웹을 기반으로 하는 소셜 웹사이트도 좋고 소셜 게임도 멋지긴 하지만... 뭔가 부족하다는 생각 말입니다. ^^;;; 조금 건방진 생각일 수 있지만, 그렇게 느끼고 또 생각하는 걸 어쩌겠습니까? ㅠㅠ

물론 다들 생각이 다르시겠지만... 소셜 웹 사이트는 뭔가 반응시간이 좀 긴 것 같은 느낌이 들고, 소셜 게임은 반응시간은 충분히 짧지만 게임의 특성상 너무 바쁘게 돌아간다라는 느낌을 받았거든요. 여기서 반응시간이란 내가 뭔가 액션을 취했을 때 그에 대한 반응이 오는 시간이라는 뜻으로 사용했습니다. 웹사이트 글이라면 글에 댓글이 달리는 시간을 의미할 수 있겠고, 소셜 게임이라면 게임 내에서 어떤 행동을 취했을 때 그에 따라오는 반응이라고 할 수 있겠군요. ^^;;;

위의 소셜 웹이나 소셜 게임을 제외하고 반응시간이 충분이 짧고 서로 재미도 있고, 그리고 여유도 있는 것이 뭐가 있을까하는 것이 요즘 저의 고민이었습니다. 뭔가 좀 여유가 있으면서 서로 즐겁게 공유할 수 있는 것... 바로 그 때 제 머리를 스친 것이 있었으니... 바로 "MUD" 게임이었습니다~!!

MUD(Multi-User Dungeon)는 지금 리니지나 ION 처럼 3D 게임 캐릭터로 게임을 하는 MMORPG의 원조격으로, 텍스트로 뿌려지는 메시지로 게임을 진행하는 방식입니다. 마치 소설책을 읽는 듯한 느낌도 들고 그래서 그런지 게임 자체보다는 사람들 간의 대화나 어떤 유대에 보다 중점을 두었습니다. 물론 이 당시에도 랩업을 위해 열심히 키보드를 두드리는 분들이 계셨지만, 적어도 지금 MMORPG처럼 대화가 없지는 않았습니다. ㅠㅠ

<대표적인 텍스트 머드 - 단군의 땅>
 
검색을 하다보니 아직까지 운영중인 MUD가 있어서 접속도 해보고, 이것 저것 둘러보니 예전 기억이 새록새록 나더라구요. 그래서 이런 MUD를 여러사람과 같이 만들어가면서 기능도 추가하고 컨텐츠도 추가하면 어떨까하는 생각이 들었습니다. 이미 틀이 짜여져 있는 것이 아닌, MUD를 즐기면서 그 안에서 새로운 컨텐츠를 계속 추가해나갈 수 있는 그런 것 말이지요 ^^;;;;

좀 막연한 생각이지만, 일단 생각이 든 김에 기본 틀이라도 만들어 놓는게 좋을 것 같아서 루비(Ruby) 언어로 프로젝트를 시작했습니다. 
예전부터 MUD를 한 번 만들어봐야겠다고 생각하고 있어서 막무가내로 시작했는데... 얼마나 완성도 있게 나올지는 모르겠네요. ^^;;;

일단 기본 스토리는 주인공이 여러 적을 쓰러뜨려 칼을 모은 뒤 7개가 모이면 소드 마스터 칭호를 받는 그런 흔한 주제로... 쿨럭..;;;; 할까 생각중입니다. ^^;;;; 뭐, 사실 기본 틀만 완성되면 그 안의 컨텐츠는 텍스트 파일을 바꾸는 것 수준으로 할 수 있지 않을까 생각하여 대충 정했는데... 어떻게 될지는 잘 모르겠군요. 쿨럭..;;;

새로운 언어도 배울 겸, 목표했던 프로그램도 만들어볼 겸... 개인적으로 괜찮은 일인 것 같네요. ;)
진행이 어느정도 되면 MINT64 OS처럼 한번 공개하겠습니다. ^^;;;

그럼 다들 좋은 밤 되세요 ;)

ps) MUD에 대한 더 많은 정보는 http://ko.wikipedia.org/wiki/MUD 에서 보실 수 있습니다. 
아시는 분은 다 아시겠지만, 티스토리에는 텍스트에 예쁜 박스를 씌워주는 글상자 기능이 있습니다. 바로 아래처럼 말이지요 ;)

이것이 바로 글상자입니다. ;)

제가 글상자를 좀 좋아하는지라 파일 목록이나 기능 목록을 나열하면서 강조할 때 종종 쓰는데요, 쓸때는 좋은데 블로그의 스킨을 바꾸고나니 살짝 문제가 있더라구요. ㅠㅠ

블로그의 스킨을 바꾸면 글자의 기본 색도 바뀝니다. 그런데 글상자는 그대로라서 지금처럼 검은 블로그 스킨을 사용하면 밝은 색 글상자 내부에 글자가 잘 보이지 않습니다. ㅠㅠ 그렇다고 안쓰기도 뭐하고... 그래서 제 블로그의 글들을 모두 긁어서 소스에 글상자가 있는지 여부를 판단하는 루비 스크립트를 만들었습니다.

코드는 아주 간단하구요, 직접 블로그 페이지에 접근한 다음 글상자를 사용하면 꼭 들어가는 "background-color: rgb" 문자열을 찾도록 했습니다. 아래는 이러한 방식으로 동작하는 루비 코드입니다. ;)


위의 코드를 저장하여 ruby로 실행하면 output.txt 파일에 결과가 저장됩니다(어휴 이거 원 생각보다 엄청 많군요 ㅠㅠ). 스프링노트에서 블로그로 내보낸 글이 거의 절반 이상인데... 이건 어떻게 처리해야할 지 암담하네요. 그냥 다시 밝은 스킨으로 돌아갈까나... ㅠㅠ

그럼 좋은 밤 되세요 ;)

그동안 사용하던 데스크탑 PC에 문제가 생겨서 OS를 얼마전에 OS를 새로 깔았습니다. ㅠㅠ 새로까는 김에 그동안 작업하는것 때문에 못깔았던 윈도우 7으로 업그레이드를 했습니다. 그래서 툴을 이것 저것 깔고 재부팅을 했는데... 디렉토리를 열었더니 예전에 쓰던 모양하고 뭔가 다른겁니다.

처음에는 뭐가 다른지 파악을 못해서 한참을 고민했는데, 불현듯 머리를 스치는 것이 있더군요. ㅠㅠ 그렇습니다. 바로 서브버전으로 관리되고 있던 디렉토리에 아이콘이 정상적으로 표시되지 않았던 겁니다. 혹시나해서 다시 봤더니 아이콘만 표시되지 않을 뿐... SVN은 정상적으로 동작을 하더군요.

그래서 구글님께 여쭤보기를 한지 30분만에 답을 찾았습니다. 윈도우 레지스트리를 보면 탐색기(Explorer)에 아이콘을 표시하는 항목이 있는데, 여기서 TortoiseSVN 항목이 뒤쪽으로 밀려나 있어서 아이콘이 표시되지 않았던 겁니다.
(이것으로 미루어보아 탐색기가 아이콘을 표시할 때 레지스트리에 들어있는 항목을 순서대로 검색하여 일치하는 것이 나오면 그냥 그것으로 표시하는 것이 아닐까 생각합니다. ^^;;;)

레지스트리는 "시작" -> "실행"으로 가셔서 "regedit"라고 입력하시면 아래와 같은 화면이 표시되는데, 여기서 HKEY_LOCAL_MACHINE -> SOFTWARE -> Microsoft -> Windows -> CurrentVersion -> Explorer -> ShellIconOverlayIdentifiers 아래의 항목을 수정하면 됩니다.

<TortoiseXXXX라고 표시된 항목을 붉게 표시된 사각형처럼 0_를 붙여서 수정하세요>

레지스트리 아래에 TortoiseXXX라고 표시된 항목이 바로 TortoiseSVN과 관련된 항목이며, 이 항목 앞에 0_라는 접두사를 붙여서 맨 앞으로 옮겨주시면 됩니다. 접두사를 붙이실 때는 해당 항목을 클릭하시고 F2 키를 누르시거나, 오른쪽 버튼을 눌러 "이름 바꾸기" 메뉴를 클릭하시면 됩니다.

그리고 마지막으로 재부팅을 한번 해주시면 예쁘게 아이콘이 오버레이된 디렉터리를 보실 수 있을 겁니다. ^^
그럼 좋은 하루 되세요 ;)

얼마전에 잡스옹께서 타계를 하셨다는 소식을 들었습니다. 터치 휴대폰이 이만큼 발전할 수 있었던건 다~ 잡스옹이 열심히 제조업체를 압박해주셨기 때문이 아닌가 생각합니다. 더불어 스마트폰이 이정도까지 온 것도 잡스옹 덕분이 아닐까 하는 생각이드네요. ㅠㅠ


예전에 스탠포드 대학에서 잡스가 한 연설을 봤는데요, 얼마 전에 TV에서 그 연설을 다시 보여주더군요. 그 연설에서 잡스가 "Stay Hungry, Stay Foolish"라고 한 말이 정말 인상적이었습니다. 나이가 들수록 사실 뭔가 간절히 하고싶다는 게 있어도 실제로 도전하는 것은 점점 힘들어지는 걸 느끼고 있어서 그런지도 모르겠네요. ^^;;;;

그 연설에서 잡스는 이런 말도 했습니다.

"아침에 일어나서 거울을 보며 지금 하는 일이 진정 하고 싶은 일인지를 물었을 때,
아니라는 대답이 계속 나온다면 변화가 필요한 시점이다"


사실 요즘 제가 계속 생각하고 있는 부분이 바로 이점입니다. 나는 과연 지금 하고 싶은 일을 하고 있는가? 사실 이미 1년이 넘게 "아니오"라는 대답을 하고 있지만... 변화는 없군요. ㅠㅠ

과연 이대로 머무는 것이 옳은 일인지도 잘 모르겠습니다. ㅠㅠ 나이가 들수록 고민은 늘어만가고 도전 정신은 점점 줄어만 가는 것 같군요. ㅎㅎ

싸늘한 공기가 집안을 뒤덮는 새벽에 갑자기 한심한 생각이 들어서 한자 남깁니다. ^^;;;

ps) 영어 점수를 따려고 하기 싫은 공부를 저녁마다 했더니만 이런 생각이 더 드네요. ㅠㅠ
      차라리 그 시간에 코딩을 했으면 뭐라도 하나 나왔을텐데... ㅠㅠ

지난번에 출판 회식 때 기꺼이 참석해주신 백창우님의 소개로 재야의 고수이신 조경민님, 이만우님과 함께 저녁을 먹었습니다. @0@)-b 다들 쟁쟁한 고수님들이라 오가는 대화 속에 심오한 내용들이 머리와 가슴에 팍팍 박히더군요. ㅠㅠ

창우님의 뼈가 되고 살이 되는 이야기도 좋았고, 그동안 온라인에서만 뵈었던 경민님을 직접 뵐 수 있어서 굉장히 값진 시간이었습니다. ㅠㅠ 그리고 이제 겨우 앞 면을 트기 시작한 만우님과 대화도 즐거웠어요 >ㅁ<)-b 다들 바쁘신 분들이고 자기 개발에 열심히신 분들이라 실제로 오프라인에서 뵙기가 쉽지 않은데, 그것도 세 분이나 동시에 뵙게 되다니... 굉장히 즐겁고 인상적이었습니다. ;)

이런 역사적인 날은 기록을 남겨두어야 할 것 같아서 블로그에 한자 남깁니다. 창우님 맛난 고기 사주셔서 감사하구요, 나중에 경민님 & 만우님과 또 만나서 즐겁게 놀았으면 좋겠네요. ^^)-b

그럼 좋은 밤 되세요 ;)

ps) 다들 뚜렷한 목표를 가지고 계셔서 내심 좀 많이 놀랬습니다.
     제가 마치 막 살고 있는 것 같아서 조금 부끄러웠어요. ㅠㅠ
     저도 뭔가 삶의 목표를 정해야 할 것 같아요. ㅎㅎ
간만에 재미있는 질문을 받았습니다. 보안 관련 기술 쪽에 ASLR(Address Space Layout Randomization) 기법이 있는데, 이를 어떻게 MNIT64 OS에 적용할 수 있을까를 묻는 내용이었습니다.

저도 보안 쪽은 좀 생소하여 ASLR을 잠시 찾아봤는데, 응용프로그램을 로딩할 때 항상 정해진 어드레스가 아닌 매번 다른 어드레스로 로딩하여 크래커로부터 보호하는 기법이더군요. 사실 어드레스를 매번 변경한다고 해도 찾아서 뚫을려고 마음 먹으면 어쩔 수 없기 때문에 완벽한 방법은 아닙니다만, 나름대로 괜찮은 아이디어라는 생각이 들었습니다.

그래서, 어떻게 하면 MINT64 OS에도 이를 적용할 수 있을까 생각을 해봤는데 의외로 답은 간단했습니다. ^^;;; MINT64 OS는 응용프로그램을 메모리에 로딩할 때 동적 메모리 관리 모듈에서 먼저 메모리를 할당 받은 뒤에 그 메모리에 올려서 응용프로그램을 동작시킵니다. 따라서, 많은 응용프로그램이 실행되고 종료되는 상황이라면, 저절로 어드레스가 랜덤하게 할당되는 것이지요.

물론, 응용프로그램 하나만 계속 생성되었다가 종료되는 상황이라면 여전히 문제가 있습니다. 이 문제도 사실은 간단히 해결할 수 있습니다. 동적 메모리 관리 모듈에서 메모리를 할당받을 때, 메모리 블록을 항상 인덱스 0번부터 검색할 것이 아니라 랜덤한 인덱스부터 검색하도록 하면 됩니다. ^^;;; 나중에 여유가되면 한번 기능을 추가해봐야겠군요. ^^)/~

그럼 즐거운 밤 되세요 ;)
요즘 옛날에 하던 MUD 생각이 자꾸나서 간단하게 테스트나 해볼 요량으로 telnet.exe을 실행했더니, 아래처럼 당황스러운 메시지가 나왔습니다. ^^;;;

'telnet'은(는) 내부 또는 외부 명령, 실행할 수 있는 프로그램, 또는 배치 파일이 아닙니다.

아무리 그래도 그렇지... 필수 유틸리티에 속하는  Telnet이 없다니... 이게 무슨 괴상망측한 상황인가 싶어서, 한참을 생각하다가 우리의 전지전능하신 구글님께 여쭤봤더니 역시 답을 주시더군요. ^^;;;

아르님의 블로그(http://cheum.net/232)를 참고하자면...

[제어판] -> [모든 제어판 항목] -> [프로그램 및 기능]에 가서 왼쪽 아래에 있는 "Windows 기능 사용/사용 안함"을 클릭하면 뜨는 "Windows 기능" 창에서 가장 아래쪽에 있는 "텔넷 클라이언트"를 체크한 뒤 확인을 누르면 됩니다.
(아래 그림을 참고하시면 더 쉽게 하실 수 있을 겁니다 ^^)


이제야 잘 되는군요. ;)

그럼 좋은 하루 되세요 ^^

ps) 왜 윈도우 7 에서는 telnet client를 막아 놨을까요...?  보안 때문에 그런걸까요? ^^;;;;
연휴에 블로그를 돌아다니다가 루비로 간단한 웹서버를 만들어보면 어떨까하는 생각이 들었습니다. 그래서 참고 자료를 찾아보고 있었는데... MSDN 블로그(여기)에서 루비로 만든 웹서버를 찾았습니다. @0@)-b 그것도 무려 70줄짜리~!!!

물론, GET 밖에는 처리하지 못하는 초 간단한 웹서버지만 일단 루비 언어(Ruby)의 간결함과 강력함을 확인하는데는 그만인 것 같습니다. ^^;;; 저도 비슷한 역할을 하는 웹서버를 C++로 작성해봤는데, 문자열 처리하고 경로 찾는 부분이 거의 절반이고, 소켓 연결을 관리하는 코드가 절반이었습니다. ㅠㅠ

그런데, 루비로 만든 웹 서버는 그냥 몇 줄에 다 처리가 가능하군요. @0@)-b... 제가 예전에 C++로 만든 웹서버 수준으로 맞춘다면 40줄 미만으로 끝날듯도... 쿨럭..;;;; ㅠㅠ 

좋은 참고 자료가 될 것 같아서 까먹기 전에 링크와 코드를 남겨둡니다. ;)
(정말 편하기는 짱이로군요. ㅠㅠ)

require 'socket'
class HttpServer
  def initialize(session, request, basePath)
    @session = session
    @request = request
    @basePath = basePath
  end

  def getFullPath()
    fileName = nil
    if @request =~ /GET .* HTTP.*/
      fileName = @request.gsub(/GET /, '').gsub(/ HTTP.*/, '')
    end
    fileName = fileName.strip
    unless fileName == nil
      fileName = @basePath + fileName
      fileName = File.expand_path(fileName, @defaultPath)
      fileName.gsub!('/', '\\')
    end
    fileName << "\\index.html" if  File.directory?(fileName)
    return fileName
  end

  def serve()
    @fullPath = getFullPath()
    src = nil
    begin
      if File.exist?(@fullPath) and File.file?(@fullPath)
        if @fullPath.index(@basePath) == 0 #path should start with base path
          contentType = getContentType(@fullPath)
          @session.print "HTTP/1.1 200/OK\r\nServer: Makorsha\r\nContent-type: #{contentType}\r\n\r\n"
          src = File.open(@fullPath, "rb")
          while (not src.eof?)
            buffer = src.read(256)
            @session.write(buffer)
          end
          src.close
          src = nil
        else
          # should have sent a 403 Forbidden access but then the attacker knows that such a file exists
          @session.print "HTTP/1.1 404/Object Not Found\r\nServer: Makorsha\r\n\r\n"
        end
      else
        @session.print "HTTP/1.1 404/Object Not Found\r\nServer: Makorsha\r\n\r\n"
      end
    ensure
      src.close unless src == nil
      @session.close
    end
  end

  def getContentType(path)
    #TODO replace with access to HKEY_CLASSES_ROOT => "Content Type"
    ext = File.extname(path)
    return "text/html"  if ext == ".html" or ext == ".htm"
    return "text/plain" if ext == ".txt"
    return "text/css"   if ext == ".css"
    return "image/jpeg" if ext == ".jpeg" or ext == ".jpg"
    return "image/gif"  if ext == ".gif"
    return "image/bmp"  if ext == ".bmp"
    return "text/plain" if ext == ".rb"
    return "text/xml"   if ext == ".xml"
    return "text/xml"   if ext == ".xsl"
    return "text/html"
  end
end

def logger(message)
  logStr =  "\n\n======================================================\n#{message}"
  puts logStr
  $log.puts logStr unless $log == nil
end

basePath = "d:\\web"
server = TCPServer.new('XXX.XXX.XXX.XXX', 9090)
logfile = basePath + "\\log.txt"
$log = File.open(logfile, "w+")

loop do
  session = server.accept
  request = session.gets
  logStr =  "#{session.peeraddr[2]} (#{session.peeraddr[3]})\n"
  logStr += Time.now.localtime.strftime("%Y/%m/%d %H:%M:%S")
  logStr += "\n#{request}"
  logger(logStr)

  Thread.start(session, request) do |session, request|
    HttpServer.new(session, request, basePath).serve()
  end
end
log.close

그럼 좋은 하루 되세요 ;) 
"64비트 멀티코어 OS 원리와 구조" 책의 첫 서평이 올라왔습니다. ㅠㅠ 
(다행히도 서평이 좋네요. ㅠㅠ 감사드립니다. ㅠㅠ)

<64비트 멀티코어 OS 원리와 구조 - 출처 yes24.com>

서평을 써주신  somesing님, charsyam님, niceness님, ageman1님 감사드립니다.  ㅠㅠ

앞으로 더욱 열심히하는 kkamagui가 되겠습니다. (__)

 
ps)  다들 즐거운 추석 연휴 보내세요 ;) 
제 책 "64비트 멀티코어 OS 원리와 구조"가 나온지도 벌써 3달이 다되어 가는군요. ^^ 부족한 책이지만 많은 분들이 구매해주신 덕분에 순조롭게 진행되고 있는 것 같습니다(물론 손익 분기점까지는 아직 멀었지만 말입니다 ㅠㅠ).

<64비트 멀티코어 OS 원리와 구조>



책의 내용 중에서 가장 많이 질문 받는 내용 중에 두 가지가 초반에 환경 구축할 때 크로스 컴파일러를 만드는 과정과 QEMU 0.10.4 버전을 어디서 구하는가 하는 것입니다. ^^;;; 그래서 얼마전에 Cygwin 최신 버전으로 64비트 크로스 컴파일러를 만드는 글(http://kkamagui.tistory.com/762)을 올렸습니다.

이번에는 QEMU 0.10.4 버전을 어디서 다운로드할 수 있는가 하는 것인데... 가장 간단한 방법은 여기에 올려드린 첨부 파일을 다운로드 하는 것입니다. ^^;;; QEMU 0.10.4 버전은 제가 MINT64 OS를 만들기 시작할 때 쓰던 버전이라... 지금은 구하기가 힘들기 때문이지요.


QEMU에 최신 OS를 설치하려면 최신 버전을 다운로드하시는게 아무래도 이득이겠지만, MINT64 OS를 실습하는데는 0.10.4 버전을 사용하시는 것이 정신의 평화와 안정을 유지하는데 도움이 되실겁니다. ^^;;;;

그럼 즐거운 OS 프로그래밍하세요 ;)
요즘 루비 언어(Ruby Language)를 이용해서 장난감을 만드는 재미에 푹~ 빠져 있습니다. ^^;;; 아무래도 내장 기능 자체가 강력하고 다양한 모듈들 때문에 별다른 부담없이 시작할 수 있어서, 이것 저것 재미삼아 만들기가 좋네요. ;)

사실 장난감이라고 해봤자 그냥 언어를 익히는 수준 정도라서 보잘것 없지만... 이번엔 나름대로 쓸모있는 걸 만들어놔서 올려봅니다. ^^;;; 이번에 공을 들여 만든 것은 바로... 멜론 다운로드 폴더를 정리해주는 프로그램입니다. @0@)-b

멜론은 벅스, 도시락과 더불어 많이 이용되고 있는 음악 스트리밍/다운로드 프로그램인데요. MP3를 다운로드하면 앨범 단위로 다운로드하던 개별 파일로 다운로드하던 그대로 다운로드 폴더에 주욱 쌓입니다. 그래서 조금만 방심하면 여러 파일이 뒤섞여서 충격과 공포의 도가니(?)로 변하지요. ㅠㅠ

그래서 마구 다운로드하되 파일이 Artist 별로 정리되어 폴더에 저장되면 좋겠다는 생각이 들어서, 파일을 폴더 별로 정리하는 루비 프로그램을 만들었습니다. 아이디어는 간단하구요, 멜론에서 저장하는 파일 형식이 아래처럼 Artist-Track Number-Song.mp3의 순서라 여기서 Artist 부분을 잘라내 디렉터리로 만들고 파일을 해당 디렉터리로 옮기되 Artist를 제외한 나머지로 파일명을 바꾸는 겁니다. ^^;;;

2NE1-04-Hate You.mp3

자, 그럼 아래 루비 프로그램 나갑니다. ;)



위의 코드를 arrange.rb로 저장한 뒤, 멜론 다운로드 폴더로 이동한 다음 아래와 같이 입력하시면 파일 정리가 순식간에 끝납니다. ^^;;; 배치 파일로 만들면 더 편리하게 실행할 수 있습니다(배치 파일과 arrange.rb 파일 모두 첨부 파일로 올려두었습니다). 물론 루비를 설치하지 않으셨다면 루비를 먼저 설치하셔야겠지요. ;) 루비는 http://www.ruby-lang.org/ko/에서 다운로드하여 설치할 수 있습니다.

ruby arrange.rb

아래는 충격과 공포의 도가니(?)에서 벗어나 깔끔해진 멜론 폴더입니다. ;)



첨부 파일


ps 1) Artist와 Track Number를 구분하는 규칙이 - 이기 때문에 Artist 명에 -이 들어가 있다면 정상적으로 분리가 되지 않습니다. ㅠㅠ
ps 2) 다음 버전은 MP3의 Tag 정보를 읽어서 분리하도록 만들어야 겠어요. ㅠㅠ

얼마 전(?)부터 계속 소프트웨어란 무엇이고 어떻게 하면 좀더 공수를 덜 들이고 개발할 수 있을까를 고민하고 있습니다. ㅠㅠ 뭐, 사실 답도 없고 아무리 고민해본들 머리에 든게 없는지라... 책을 봐야겠다고 생각하던 차에 손에 잡힌게 바로 "소프트웨어 컨플릭트 2.0"였습니다.

<책 표지 - 출처 Yes24>


이 책은 소프트웨어 개발에 관련된 여러 자원, 즉 사람부터 개발 언어 및 툴까지 여러가지 내용을 수필의 형식을 빌어 정리해두었는데, 여러 부분에서 공감이 가는 부분이 많았습니다. 그리고 충격적인 부분은... 이 책이 20년도 전에 쓰여진 책이라는 것이죠. @0@)-b


책을 덮고 나니... 제가 하고 있는 고민을 저만 하는게 아니라 오래전부터 하고 있던 부분이라는 것에 좀 씁쓸하더라구요. ㅠㅠ 시간이 20년이나 지났지만 예나 지금이나 소프트웨어 개발은 크게 달라진게 없는 것이 아닌가 하는 생각이 들어서... ㅠㅠ


성공적인 프로젝트 수행을 위해 디자인 패턴이나 Agile 방법론처럼 다양한 방면에서 발전을 하고 있지만, 여전히 소프트웨어는 복잡하고 개발 과정은 험난하기 짝이 없는 것 같습니다. 과연 언제쯤이면 제 고민이 싹 사라질까요? (이 바닥에 있는 한 영원히 사라지지 않을지도 모르겠네요). ㅠㅠ

제 책 "64비트 멀티코어 OS 원리와 구조"가 나온지도 벌써 2달 이상 지났습니다. ^^;;; 책이 출간됨과 동시에 가장 많이 질문을 받는 것이 OS 제작을 위한 환경 구축 방법인데요... 얼마전부터 환경 구축에 어려움을 겪는 분들이 많아지셔서 Cygwin 최신 버전을 다운 받아서 빌드를 해봤습니다. ^^;;; 실제로 빌드를 진행하다보니 한가지 변경점이 보이더군요. ㅠㅠ 그래서 그 내용을 여기다가 정리해놓습니다. ㅠㅠ


<출처 - yes24.com>


Cross Compiler를 만들려면 먼저 Cygwin 사이트(http://www.cygwin.com/install.html)로 이동해서 Cygwin Installer를 다운로드 받습니다. Setup.exe 파일을 다운하면 됩니다. ^^;;;

다운로드 후 파일을 실행하면 어떻게 설치할 것이고 패키지 소스는 어디에서 다운 받을 것인지 선택하는 부분이 나오는데,

책에 나와있는 카이스트 사이트(ftp://ftp.kaist.ac.kr)가 더이상 유효하지 않으니 다른 사이트를 선택해야합니다.

우리나라 근처에 있는게 아무래도... 속도도 빠르니 가까운 일본 주소인 ftp://ftp.jaist.ac.jp를 선택하면 됩니다. ^^;;;

패키지 소스를 다운 받을 주소를 선택하고 난 뒤에는 "Select Package" 화면이 나올 때까지 적당히 Next를 선택해주면 됩니다. ^^;;;

"Select Package" 화면이 나오면 아래의 항목들을 설치해줍니다. 책을 쓸 때는 C++ 관련 항목이 없어도 정상적으로 빌드가 되었지만, 지금은 C++ 컴파일러를 설치하지 않으니 configure 중에 오류가 발생하더군요. ㅠㅠ 가장 아래쪽에 있는 libmpc-devel이 변경된 부분입니다.

+Devel  
    + binutils - 2.21.53-2 버전, 소스 및 바이너리 모두 설치  
    + bison - 2.4-2-1 버전, 바이너리만 설치  
    + flex - 2.5.35-1 버전, 바이너리만 설치  
    + gcc4-core - 4.3.4-3 버전, 소스 및 바이너리 모두 설치  
    + gcc4-g++ - 4.3.4-4 버전, 바이너리만 설치  
    + libiconv - 1.14-1 버전, 바이너리만 설치  
    + libtool - 2.2.7a-15 버전, 바이너리만 설치  
    + make - 3.81-2 버전, 바이너리만 설치  
    + patchutils - 0.3.1-1 버전, 바이너리만 설치  
+Libs  
    + libgmp-devel - 4.3.2-1 버전, 바이너리만 설치  
    + libmpfr-devel -3.0.1-1 버전, 바이너리만 설치
    + libmpc-devel - 0.8-1 버전, 바이너리만 설치

위의 항목이 설치되고 나면 binutils부터 차례대로 빌드를 시작하면 됩니다.


binutils를 빌드하려면 /usr/src 디렉터리 아래에 있는 binutils 디렉터리로 이동해서 다음과 같은 순서로 커맨드를 입력하면 빌드와 설치가 끝납니다.

// 디렉터리 이동 후 아래 작업 수행

$> cd /usr/src/binutils-2.21.53-2  <== 디렉터리 이름은 binutils 버전에 따라 다를 수 있음
$> export TARGET=x86\_64-pc-linux  
$> export PREFIX=/usr/cross  
$> ./configure --target=$TARGET --prefix=$PREFIX --enable-64-bit-bfd --disable-shared --disable-nls  
$> make configure-host  
$> make LDFLAGS="-all-static"  
$> make install  

// 아래는 테스트를 위한 부분 커맨드를 실행했을 때 x86\_64 관련 항목이 보이면 제대로 된 것입니다. ^^;;;;  
$> /usr/cross/bin/x86\_64-pc-linux-ld --help | grep "supported "  
/usr/cross/bin/x86\_64-pc-linux-ld: supported targets: elf64-x86-64 elf32-i386 a.  
out-i386-linux efi-app-ia32 efi-bsdrv-ia32 efi-rtdrv-ia32 efi-app-x86\_64 efi-bsd  
rv-x86\_64 efi-rtdrv-x86\_64 elf64-little elf64-big elf32-little elf32-big srec sy  
mbolsrec tekhex binary ihex  
/usr/cross/bin/x86\_64-pc-linux-ld: supported emulations: elf\_x86\_64 elf\_i386 i38  
6linux  

binutils 빌드 및 설치가 끝났다면 gcc를 cross compile할 차례입니다. gcc는 아래와 같은 순서로 입력하면 빌드와 설치가 완료됩니다. ^^;;;

// 압축 해제, 파일명은 cygwin에서 다운받은 GCC 버전에 따라서 다를 수 있으니 실제 디렉터리를 확인하여 입력해야 합니다. ^^;;; 아래 패치 파일도 모두 마찬가지 입니다.  
$> cd /usr/src

$> tar -xvf gcc-4.3.4.tar.bz2  
$> patch -p1 < gcc4-4.3.4-3.src.patch  
$> patch -p1 < gcc4-4.3.4-3.cygwin.patch  
$> export TARGET=x86\_64-pc-linux  
$> export PREFIX=/usr/cross  
$> export PATH=$PREFIX/bin:$PATH

// 압축 해제가 끝났으니 소스가 있는 디렉터리 이동 후 나머지 작업 수행  
$>cd /usr/src/gcc-4.3.4 <== 디렉터리 이름은 GCC 버전에 따라 다를 수 있음

$> ./configure --target=$TARGET --prefix=$PREFIX --disable-nls --enable-languages=c --without-headers --disable-shared --enable-multilib  
$> make configure-host  
$> cp /lib/gcc/i686-pc-cygwin/4.3.4/libgcc\_s.dll.a /lib/gcc/i686-pc-cygwin/4.3.4/libgcc\_s.a  
$> cp /lib/libmpfr.dll.a /lib/libmpfr.a  
$> cp /lib/libgmp.dll.a /lib/libgmp.a  
$> make all-gcc  
$> make install-gcc  

// 테스트용입니다. 아래와 같이 입력했을 때 m64가 보이면 정상적으로 설치된 것입니다.  
$> /usr/cross/bin/x86\_64-pc-linux-gcc -dumpspecs | grep -A1 multilib\_options  
    *multilib\_options:  
    m64/m32  

자, 이제 64비트 바이너리를 생성할 수 있는 gcc가 생성되었으니,
즐거운 OS 프로그래밍하세요 ;)

잘 쓰고 있던 디자이어에서 메모리가 부족하는 오류가 발생했습니다. ㅠㅠ 그래서 프로그램에서 사용하는 데이터를 지웠는데요, 갑자기 Jorte에서 "캘린더가 없습니다"하는 오류가 발생하더군요. @0@...

프로그램이 사용중인 캐시 정보를 지운 것 밖에 없는데, 이런 오류가 뜨니 상당히 당황스러웠습니다. 그래서 Jorte를 삭제하고 다시 설치해봤는데, 역시나 같은 오류가 발생하더라구요. ㅠㅠ

인터넷을 뒤져보니 안드로이드 폰을 초기화하는 방법을 해결했다는 글이 보이던데, 초기화를 하고나면 해야할 것도 많고 해서 다른 방법을 찾고 있었습니다. 그러다가 문득... 캐시 데이터를 삭제하다가 구글 캘린더를 사용하는데 필요한 정보가 삭제된 것이 아닐까 싶더라구요. ^^;;;

그래서 캘린더 동기화를 시켜봤더니 아무 문제 없이 동작했습니다. ㅠㅠ

캘린더를 동기화하는 방법은 아래와 같습니다.

"메뉴" -> "데이터 동기화" ->"캘린더" 선택

꽤나 골칫거리였는데, 해결하고 나니 좀 싱겁군요. ;)
그럼 즐거운 안드로이드 하세요 ;)

루비 개발 툴로는 이클립스를 비롯해서 여러가지가 있겠지만 저는 NetBeans를 선택했습니다. 그동안 이클립스를 써와서 좀 다른 툴을 써보고 싶었거든요. ^^;;; 실제로 써보니 NetBeans도 이클립스만큼 쓸만하더군요. >ㅁ<)-b

우분투에서 NetBeans를 설치하는 방법은 아주 간단합니다. 시작 메뉴의 "우분투 소프트웨어 센터"를 클릭하여 소프트웨어 센터를 띄운 다음 아래처럼 검색창에 NetBeans를 입력하면 됩니다. 저는 이미 설치가 되어 있어서 제거로 표시되는데, 실제로 다른 분들은 설치로 표시될 겁니다. ^^;;;

<NetBeans 설치 방법>


NetBeans를 설치하고 나면 이제 Ruby 개발을 위해 플러그인을 설치해야 합니다. NetBeans 플러그인을 설치하려면 먼저 NetBeans를 실행해야 하는데, 시작 메뉴의 "개발" 메뉴를 보면 아까 설치한 NetBeans가 표시될 것입니다. 이를 실행하면 아래와 같은 화면이 표시되는데, 화면의 오른쪽에 빨간 사각형으로 표시된 "Install Plugins"을 클릭합니다.

<루비 개발용 플러그인 설치 화면>


클릭하고나면 플러그인 설치 화면이 표시되는데 여기에 ruby를 입력하면 "Ruby and Rails" 항목이 표시됩니다. 이 항목을 설치했으면 NetBeans를 다시 시작한 뒤에 "File" 메뉴의 "New Project" 메뉴를 선택합니다. 그러면 프로젝트 항목에서 Ruby가 표시되며 Ruby 프로젝트를 만들어서 프로그래밍을 할 수 있습니다. ^^


그럼 좋은 하루 되세요 ^^


새로운 프로젝트를 앞두고 있어서 얼마 전부터 그동안 프로젝트를 하면서 가장 불만이었던 것이 무엇인가를 고민하고 있었습니다(그러고 보니 작년부터 지금까지 프로젝트가 끊이질 않는군요. ㅠㅠ 쉴 시간도 없이 계속 달려왔는데 또 달리라니... ㅠㅠ). 그러다가 문득 생각난게 반복되는 작업이 너무 많다는 것이었습니다. 개발하고 테스트 돌리고 분석하고 디버깅하는 사이클을 매번 반복하는데... 분석하고 디버깅하는 시간은 그렇다 치지만 개발하고 테스트를 돌리는데 공수가 드는건 뭔가 잘못됬다는 생각이 들더군요.

개발하는 것에 비하면 테스트 돌리는 건 일도 아니지만, 실제로 여러 옵션을 주게 되어 있어서 귀찮았거든요. 실제로 이런 옵션들 때문에 팀원들 중에서는 지금도 통합 테스트를 제대로 못 돌리는 사람이 있을 정도니까요. ^^;;;; 그래서 테스트를 좀 자동화하고 편하게 하고자 쉽게 프로그램을 만들 수 있는 스크립트 언어에 다시 눈을 돌리게 되었습니다. 물론 배치 파일로도 할 수 있지만, 이왕이면 다홍치마라고 이 기회에 새로운 언어를 배우고 싶었습니다. ;)

예전에도 이런 고민을 한번 했는데 그때 파이썬(Python)이라는 언어가 좋다는 이야기를 듣고 잠시 배웠습니다. 실제로 써보니 C와 궁합도 좋고 여러모로 강력하더군요. >ㅁ<)-b 그런데, 들여쓰기를 코드 블록으로 사용하는 점과 클래스를 만들 때 Self 키워드를 사용하는 부분이 저와 맞지 않아서 그렇게 많이 쓰지는 못했습니다. ㅠㅠ

<루비(Ruby) 사이트 - http://www.ruby-lang.org/ko/>


그래서 이번에는 좀 C/C++ 스타일과 비슷한 스크립트 언어를 찾기로 했는데, 이때 딱 눈에 띈게 바로 루비(Ruby)였습니다. 루비의 문법을 보니 C/C++과 상당이 비슷해서 조금만 익숙해지니 이것 저것 해볼 수 있더라구요. ^^;;; 거기다가 라이브러리도 꽤 많아서 완전 제 마음에 들었습니다. ^^)/~ 루비 언어를 만든 마츠모토 유키히로씨가 스트레스가 없는 쉬운 프로그래밍 언어를 목표로 했다고 하던데 정말 그런 느낌이 들었습니다(물론 스크립트 언어라서 제가 그렇게 느낀 걸수도 있습니다만... 쿨럭...;;;).

지금까지는 아이디어가 떠오르면 C나 C++로 코딩하곤 했는데, C는 뭐랄까요... 왠지 마음을 단단히 먹고 시작해야 할 것 같은데, 루비는 그런 느낌도 없고 편하니 좀더 쉽게 여러가지를 해볼 수 있지 않을까 생각합니다. ^^;;;

그럼 즐거운 루비 라이프를 위해 화이팅~!!

ps)  며칠 해본 결과 상당히 마음에 들던데... 
      이러다가 MINT64 OS에 루비를 올리는 날이 올지도 모르겠군요... ㅠㅠ

오늘 와이프와 간만에 영화를 보러 갔다 왔습니다. ^^ 와이프가 7광구가 보고 싶다고해서 갔는데, 얼래 생각보다 사람이 너무 적은 겁니다. ㅠㅠ 안그래도 평점이 좋지 않다는 이야기를 들어서 그런지 더 불안하더군요. ㅠㅠ

<7광구 포스터 - 출처: 네이버>

그런데 영화를 보면 볼수록 점점 빠져들더라구요. 영화가 마치 예전에 에어리언 시리즈처럼 긴장감도 있고 괴물도 나름대로 멋지게 잘 그렸던데... 와이프랑 영화관을 나오면서 왜 평점이 낮은 걸까 계속 고민했습니다. ㅠㅠ

물론 스토리가 살짝 부실한 부분도 있었지만 전체적으로 봤을 때는 괜찮은 영화였습니다.
평점만 보고 Skip하기에는 너무 아까운 영화로군요. ^^;;;

ps) 저만 재미있게 봤던 건가요? ㅠㅠ

+ Recent posts