에구에구... 오늘 교육 끝나고 집으로 쏜살같이 달려와서는 그 동안 마음에 걸렸던 부분들을 수정했습니다. 사실 더이상 손대기에는 시간도 부족하고, 목표로 정한 것이 있어서 더이상 구현만 할 수는 없었다는... ㅠㅠ 그래서 완성도는 약간 떨어지지만, 프로토타입을 완료했습니다. ㅎㅎ

 지금까지 진행된 것은 멀티 태스킹 + 파일 시스템 + 동적 메모리 관리 + GUI 시스템 + 기타 시리얼, 마우스, 하드 디스크 드라이버 등등 정도 입니다. 뭐 많이 하긴했는데, 적어놓고보니 별거 없군요. ㅠㅠ 아래는 1.0 버전의 스크린샷입니다.

 파일 시스템이 추가되어서 시리얼로 실행파일을 매번 전송해서 실행하는 번거로움이 없어졌습니다. "Application Pannel"에서 "GUI Shell"을 실행한 다음 루트 디렉토리에 있는 테트리스 실행파일을 load 명령으로 실행하면 테트리스가 실행됩니다. ^^)-b GUI 쉘은 화면을 지우는 cls 명령과 디렉토리를 표시하는 dir 또는 ls 명령만 가지고 있습니다. 

 기념삼아 프로토타입을 테스트할 수 있는 파일을 올립니다. 아래 파일을 다운 받으셔서 압축을 푸신 다음 "qemu64MyOs.bat" 파일을 실행하시면 됩니다. 


 아아~ 오늘도 늦게까지 작업했더니 피곤합니다. ㅠㅠ. 일찍 끝낼 수 있었는데 QEMU가 Single Core 모드로 동작할때 IOAPIC 쪽을 사용하지 않는 걸 몰라서 한참 삽질했습니다. ㅡ_ㅡa... 커널이 잘못된 줄 알고 2시간동안 갈아 엎었습니다. 디버그 코드 덕에 겨우 알았다는... 싱글 코어일때는 PIC를 그대로 쓰도록 바꿔놔야겠군요. ㅎㅎ

 이크~ 저는 이만 자야겠습니다. 다들 좋은 밤 되세요~ ㅎㅎ

 

 
 이번주는 결혼식이다 뭐다해서 그렇게 많은 시간을 투자하지 못했습니다만, 막판 스퍼트해서  파일시스템을 추가하는데 성공했습니다. >ㅁ<)-b 사실 대부분의 코드는 윈도우 환경에서 시뮬레이션하면서 검증했기 때문에, 그냥 컨트롤 C+V 신공으로 끝냈습니다. ㅎㅎ

 그리고 내친김에 GUI 쉘에 dir 기능도 추가했습니다. GUI 쉘을 만든지는 좀 됬지만 귀찮아서 그냥 뒀는데, 점점 불편함이 커지더군요. 쉘 기능이 필요할때는 콘솔 모드 커널로 빌드해서 쉘을 쓰다가 다시 GUI 테스트할때는 윈도우 모드로 빌드해서 부팅하고... 이걸 수백번 정도 반복하다보니 그냥 만드는게 편하겠다는 생각이 들었습니다. 그래서 뚝딱~!!! 만들었습니다(사실 이 일이 더 많이 걸렸다는... ㅠㅠ).

 아래는 GUI 쉘로 루트 폴더와 이미지 폴더를 본 화면입니다. 깔끔하게 잘 나오는 걸 볼 수 있습니다. ㅎㅎ (이미지 윈도우는 /image/image0.img 파일을 읽어서 화면에 표시하도록 수정되었습니다)

 이거 뭐 점점 기능이 추가될수록 갈아 엎는 코드의 양도 많아지는군요. 이번에도 몇군데나 갈아 엎었습니다. ㅠㅠ 처음에는 간단한 OS를 만들자는 생각이었는데, 욕심이 자꾸 생겨서 이것도 추가하고 저것도 추가하게 되네요. 이렇다 언제 거사(?)를 시작하게 될지... ㅡ_ㅡa...

 진짜 내일 동적 메모리 할당쪽 알고리즘만 좀 더 수정하고, 거사를 시작해야겠습니다. 고칠게 있으면 거사를 진행하면서 고치던가 해야겠군요. ㅎㅎ

 내일 교육은... 또 물건너 간 것 같습니다. 푹 자다 올듯... ㅠㅠ
 다들 좋은 밤 되시길 ;)

 어이쿠 또 시간이 이렇게나 흘렀군요. ㅠㅠ 방금 파일 시스템에 FAT(File Allocation Table) 영역에 해당하는 부분에 캐시 버퍼를 추가했는데, 대충 캐시 히트률이 60% 정도 나왔습니다. 생각보다 좀 저조한듯 하기도 하고... 일단 Sequential Write를 랜덤하게 돌려서 쓰고 읽고 검증하는 테스트를 돌리고 있는데, 에러가 안나오는거 보면 큰 문제는 없는 것 같습니다. 약간 문제라면... 캐시 히트률이 좀 낮은 게 문제라면 문제랄까요? ^^;;;;

 일단 캐시 알고리즘은 LRU(Least Recently Used)을 선택했고, Dirty 비트를 추가해서 Dirty 또는 Clean 중에 왠만하면 Clean인 놈을 선택하도록 했습니다. 물론 단순히 Age 만을 비교하는 것도 괜찮지만, 만약 쓰기가 수행된 캐시 버퍼 즉 Dirty 비트가 켜진 캐시 버퍼를 선택하게 되면 하드에 한번 더 써야하는 문제가 발생할 수 있어서 Clean을 우선적으로 선택하게 만들었습니다. Clean 인 놈은 쓰기가 수행되지 않고 읽기만 수행된 버퍼기 때문에 플러쉬(캐쉬에서 내보낼때)할 때 HDD에 안써도 되기 때문이지요. ㅎㅎ

 아흑... 원래는 더 일찍 끝났어야 하는데, lseek를 추가한다고 시간이 이렇게 흘러버렸군요. 처음에 예상했던 크기보다 점점 커지고 있어서 살짝 걱정이 됩니다. 어휴... 이걸 어떻게 해야될지... ㅠㅠ 그래도 일단 하던 작업은 끝내는게 맞는 듯 하니 이것까지만 해야겠습니다. ^^;;;

 내일은 알고리즘을 좀 손보고 데이터가 있는 클러스터 영역을 캐싱하는 기능도 추가해야겠습니다. 그리고 OS에 바로 옮겨봐야겠군요. ㅎㅎ 살짝 기대가 된다는... 과연 캐시를 사용하는 것과 사용하지 않는 것이 가상 머신에서 어떻게 차이가날지... 완전 기대됩니다. ㅎㅎㅎ

 그럼 내일 출근을 위해 전 이만 취침하러... ㅎㅎ
 다들 좋은 밤 되시길~ ;)


 아이쿠... 원래 계획은 좀 더 진도를 나가는 거였는데... 그 동안 무리를 좀 했더니 저녁에 잠깐 졸았습니다. 한 40분 잤으니 존거 치고는 시간이 좀 길군요. ^^;;;; 아무리 피곤해도 존적은 별로 없는데... 몸이 좀 피곤하긴 한가 봅니다. 그러거나 말거나 할꺼는 해야하니 세수 한판하고 또 진도 나갔습니다.

 일단 어제 대충 만든 테트리스를 좀 수정해서 블럭 색깔하고, 내부 알고리즘을 좀 정리했습니다. 원래 테트리스가 그리 복잡한 알고리즘이 필요없는 게임이라... 알고리즘이라는 말을 쓰기도 부끄럽습니다만... ㅡ_ㅡa... 발로 짜다보니 도저히 안되겠더군요. ㅎㅎ 내일쯤 정리되면 한번 올리겠습니다. ^^;;;;

 테트리스를 수정한 뒤에 한참을 고민했습니다. 이제 더 뭘 구현해야 하는가.... 가만히 보니 3개 정도가 더 남았더군요. 디지털 시계, 텍스트 뷰어, 이미지 뷰어 정도 남았던데... 디지털 시계는 텍스트로 날짜와 시간만 표시해줄 생각이니 크게 어렵지는 않을 것 같고... 텍스트 뷰어는 말 그대로 뷰어니까 그냥 텍스트만 출력해주면되니 이것도 별로 어렵지 않을 것 같았습니다.

 그렇다면 남은 것은 이미지 뷰어인데, 어떤 파일 포맷을 사용할 것인가가 문제더군요. 가장 쉽게 처리할 수 있는게 BMP 파일 형식인데... BMP도 다양한 버전이 있기 때문에 어떤걸 해야할지 고민이 됬습니다. 그러다가 문득 NDS 홈브루를 개발할때 만들었던 KNG(kkamagui NDS Graphic) 파일 포맷이 생각나서 그걸 사용하기로 했습니다. NDS 홈브루도 16bit Color로 설정되어있고, 마침 지금 만드는 OS도 16bit Color로 설정되어있으니 큰 수정없이 사용할 수 있을 것 같았습니다. KNG를 사용하는 NDS 홈브루는 http://kkamagui.tistory.com/49http://kkamagui.tistory.com/468 에서 보실 수 있습니다.


 위의 화면은 수정된 테트리스와 그 뒤로 이미지 뷰어가 실행된 화면입니다. 이미지는 KNG로 변환해서 OS에 시리얼로 전송하는 방식으로 했습니다. KNG를 사용한 덕분에 작업이 상당히 빨리 끝났습니다. ^^;;; 이것 저것 많이 만들다보니 이런 날도 오는군요~ 좋구로 ㅎㅎ

 작업을 진행하면서 느끼는 QEMU의 장점은 TCPIP로 가상 시리얼을 연결할 수 있어서 굉장히 편리하게 시리얼 통신을 할 수 있는 점입니다. 속도도 굉장히 빠르고 QEMU 내부적으로 버퍼 관리도 해주니 OS에서 구현된 허접한 시리얼 드라이버로도 잘 됩니다. 덕분에 귀찮은 작업이 얼마나 줄었는지... ㅠㅠ)-b QEMU 만세~!!!

 아아... 벌써 또 시간이 이렇게 됬군요. ㅠㅠ 언제쯤 일찍 자려나... 그러려면 집에 굉징히 일찍오던지... 아니면 컴퓨터를 안켜야하는데, 둘다 실현 가능성이 낮군요. ㅠㅠ 거의 다 완료될때까지 잠을 줄이는 수 밖에는 없을 것 같습니다. 아흑....

 그럼 다들 좋은 밤 되세요. ^^)/~

ps) 헛... 이런 잠결에 만들다보니 화면에 있는 이미지 뷰어에 스펠링이 틀렸군요. 이런 ㅠㅠ

 이제까지 GUI 어플리케이션은 모두 커널레벨에서 동작하는 커널 스레드와 같은 개념이었습니다. 즉 커널 코드에 포함되어있으며, 스택만 별도로 사용하는 존재였지요. ^^;;; 그래서 "어플리케이션"이라고 확실히 부를 수 있는 유저 레벨 태스크를 이용해서 GUI 어플리케이션을 만들어봤습니다.

 위의 화면에서 좌측 상단에 보이는 User Level Application이라고 표시된 윈도우가 유저 레벨에서 동작하는 GUI 어플리케이션입니다. OS 코드가 아주 간단하지만, 현대 OS가 갖추고 있는건 쪼금 쪼금씩 구현해 놓은지라, 당연히 커널 영역에는 접근하지 못하고 시스템콜(System Call)을 통해서만 커널 함수를 쓸 수 있습니다. 다만 아직 GUI 관련 시스템콜이 그리 많지 않아서 덩그러니 윈도우 기본 화면만 표시하고 있다는... ㅠㅠ 원래는 Hello, World를 찍어야하는데 시스템 콜을 만드는게 귀찮아서 그냥 뒀습니다. ㅠㅠ 너무 늦게 퇴근해서... ㅠㅠ

 그리고 유저 레벨 프로그램은 역시 커널과 별도로 빌드해서 실행하는게 제 맛이기 때문에, 별도로 elf 파일을 생성했고 지난번에 만든 File Downloader를 통해 OS에 전송했습니다. OS에는 당연히 윈도우 버전의 File Downloader를 만들었구요. ㅎㅎ 위의 화면에서 가운데 있는 것이 윈도우 버전의 File Downloader 입니다. Memory Monitor의 그라데이션 태스크 바를 그대로 썼습니다. ㅎㅎ 그러고보니 스프링노트에 ELF 재배치에 대한 글을 적어놨었는데, 깜빡했군요. 언능 마무리해서 포스팅해야겠습니다. ㅎㅎ

 시간이 지날수록 점점 커지는 걸 보니 흐믓합니다. ^^ 이제 조금만 더하면 되겠군요. ㅎㅎ 내일은 좀 일찍오면 테트리스를 만들어 올려봐야겠습니다. 그리고 가능하면 텍스트 뷰어나 BMP 뷰어같은 것도 만들어봐야겠네요. ㅎㅎ

 어이쿠 벌써 이렇게 시간이.... 전 이만 자러가야겠습니다.
 다들 좋은 밤 되세요 ^^)/~



 다들 즐거운 추석 연휴를 보내시고 계신가요? ㅎㅎ 저는 할머니댁에 당일치기로 갔다오는 바람에 시간이 많이 남아서 오늘도 어김없이 OS를 만들고 있습니다. 이런 걸 보면 역시 프로그래머가 천직인 것 같네요. ㅎㅎ ^^;;; 다만 좀 아쉬운 점이 있다면 마제스터치 키보드와 함께하지 못하고 허접한 삼성 멤브레인 키보드를 치고있다는 것... 기계식 키보드를 치다가 멤브레인 키보드를 치니 끝까지 눌렸는지를 확실히 알 수 없군요. ㅡ_ㅡa... 오타 작렬입니다. ㅠㅠ

 잡담은 이쯤하고... OS 개발도 거의 막바지로 가고 있어서 그 동안 고민했던 것들을 하나, 둘 마무리하고 있습니다. 옛날부터 OS를 몇번이나 뒤엎고 다시 들고 있지만, FPU 즉 실수 연산에 대해서는 그리 깊게 고민하지 않았습니다. 왜냐하면 finit, fxrstor, fxsave와 같은 멋진 어셈블리어 명령어들이 x387 Coprocessor의 상태를 관리해줬기 때문이지요. 그때는 단순히 이 명령들만 호출하면 된다고 생각했습니다. ^^;;

 그런데 막상 해보니 실상은 좀 다르더군요. ㅡ_ㅡa... fxsave 및 fxrstore를 이용해서 FPU 상태를 저장/복원했을 때 사용되는 메모리의 크기는 총 512Byte 입니다. 이건 상당히 큰 사이즈입니다. @0@)/~!!! 이것을 만약 Task Switching 시마다 저장/복원을 한다고 가정하면 Core에 있는 Register를 저장/복원하는 크기보다 더 크기때문에 거의 2배 정도의 Context Switching 시간이 걸립니다. ㅡ_ㅡa... 무시무시한 시간이지요.

 요 며칠동안 고민을 많이 했었는데, 가만히 생각해보니 뭔가 답이 나오더군요. Task 중에 FPU를 사용하는 Task가 여러개 있다고 가정하면, 인코딩 프로그램과 같은 프로그램을 제외하고는 실수 연산이 그리 빈번하지 않습니다. 즉 Task의 전체 코드에 비해 FPU 연산이 차지하는 비중이 작다는 것이지요. 그리고 또 한가지 포인트는 모든 Task가 FPU를 사용하는 것은 아니라는 겁니다. 경우에 따라 정수 연산으로도 충분한 Task가 있으니까요. ^^

 그래서 OS에서 마지막으로 FPU 연산(mmx, sse, sse2, sse3관련 어셈블리어 명령 사용)을 사용한 Task를 저장하고 있다가, 어떤 Task가 FPU 연산을 수행하면 마지막으로 사용한 Task와 비교해서 처리하는 방식을 생각했습니다. 사실 이 방법은 INTEL 문서(Volume 3)에도 나와있는 방법입니다. ^^;;; CR0 레지스터의 TS bit를 잘 사용하면 FPU 연산이 발생할때마다 7번 Exception이 발생하게 할 수 있고, 이것을 이용해서 처리하도록 가이드가 나와있습니다.

 제가  사용한 간략한 알고리즘은 아래와 같습니다.
  • FPU 연산이 발생했을 때, 마지막으로 FPU를 사용한 Task가 있는지 확인한다.
  • 마지막으로 FPU를 사용한 Task가 현재 Task이면 아무것도 해줄 필요 없다.
  • 마지막으로 FPU를 사용한 Task가 현재 Task가 아니면 마지막으로 사용한 Task에 FPU의 상태를 저장한다(fxsave).
  • 현재 Task가 FPU를 사용한 적이 없으면 FPU 상태를 초기 상태로 설정한다(finit).
  • 현재 Task가 FPU를 사용한 적이 있으면 Task에서 FPU 상태를 복원한다(fxrstor).
  • FPU를 마지막으로 사용한 Task 정보를 현재 Task로 설정한다.

 위와 같은 방식으로 총 300개의 FPU Task를 생성해서 돌려봤습니다. 처음에 FPU 상태를 저장하지 않았을때는 FPU가 여기저기 Task에서 건드려져서 정상적으로 계산 결과가 나오지 않더군요. 하지만 위와 같은 알고리즘으로 구현하고나니 계산 결과가 정확하게 나왔습니다. >ㅁ<)-b

 이렇게 또 한고비가 넘어가니 기분이 좋습니다. ㅎㅎ 잠깐 나갔다 와서 다른 장난(?)도 좀 쳐봐야겠군요. ㅎㅎ
 다들 즐거운 연휴 보내세요. ^^)-b



 
 드디어 응용프로그램을 외부에서 전송하여 실행하는데 성공했습니다. 외부 즉 윈도우와 가상 머신은 Serial Port로 연결했습니다. QEMU의 옵션 중에 가상 Serial Port를 열어주는 옵션이 있는데, 그것을 이용해서 가상머신에 Serial을 만들고 제가 만든 OS에서 그 Serial을 사용함으로써 통신에 성공했습니다. @0@)/~

 QEMU에서 TCP/IP로 Serial Port를 생성할 수 있는데, 아주 편하더군요. 덕분에 간단한 윈도우 소켓 프로그램으로 파일을 OS에 넘겨줄 수 있게 됬습니다. 아래는 제가 사용하는 QEMU 옵션인데, 맨 뒷줄 -serial 부터가 TCP/IP로 Serial Port를 생성해주는 옵션입니다. ^^

qemu-system-x86_64.exe -L . -fda d:/64bitos/disk.img -hda 64BitOS.img -m 32 -localtime -M pc -smp 2 -boot a -serial tcp::4444,server,nowait


 아래는 QEMU에서 돌고 있는 제 OS에 파일 매니져가 응용프로그램 바이너리(elf64 파일 포맷)을 넘겨주는 화면입니다. OS에서 Serial로 열심히 데이터를 다운받아서 "."을  찍고있는 걸 볼 수 있습니다. ^^;;;;
사용자 삽입 이미지

 다운로드가 끝나면 OS에서 ELF64 파일 포맷인가 확인한 뒤, Relocation을 수행합니다. 그후 메모리를 할당받아 Relocation된 실행 파일을 복사하고 프로세스를 생성합니다. 원래는 ELF64 파일 포맷을 가공하려고 했습니다만, Relocation을 분석하는 과정에서 크게 복잡한 부분이 없어서 그냥 쓰기로 했습니다. ^^;;;

 아래는 여러 개의 Application을 OS에 업로드하여 실행한 화면입니다. 각자 자신의 Task ID를 표시하게 되어있습니다.
사용자 삽입 이미지

 어휴... 진짜 이것 저것 많이 했군요. 이제 내일은 GUI 쪽 System Call을 추가하고 좀 복잡한 Application을 로딩해서 정상적으로 동작하나 확인해 봐야겠습니다. >ㅁ<)-b

 이크~ 벌써 시간이 이렇게 됬군요. 그만 자야겠습니다. ㅎㅎ
 그럼 다들 좋은 밤 되세요 ;)


 이제 OS를 만드는 작업이 거의 막판까지 왔습니다. 커널에서는 이미 System Call 처리를 위한 준비를 끝낸 상태이며, 이제 응용프로그램을 적절히 로드해서 실행하는 것만 남았습니다. ^^;;; 그동안 작업을 주로 윈도우 환경에서 했기때문에 PE 파일 포맷을 주로 다뤘습니다(PE 파일 포맷에 대한 내용은 http://kkamagui.tistory.com/search/PE%20%ED%8C%8C%EC%9D%BC 을 참고하세요).

 이번에 ELF 파일 포맷 쪽을 다루는 김에 문서를 좀 남겨둘려고 허접하지만 문서 작업을 같이 했더니, 이해하는데 훨씬 도움이 되더군요. 물론 아는 내용을 정리하는 작업이 좀 지루하기는 하지만, 시간이 지나면 다 잊어먹으니 나중을 대비해서라도 정리하는 게 좋을 것 같더라구요. ㅎㅎ

 정리를 죽 하다보니, 머리로만 이해하고 있던 내용 중에 잘못된 것도 찾을 수 있었고, 확실히 보지 않으면 정리를 할 수 없으니 문서를 세세히 찾아볼 수 있었습니다. ^^;;; 어제 늦게 정리된 내용을 바탕으로 ELF64 Relocator(가칭)을 만들었는데, 나름대로 잘 동작하더군요. :)

 ELF64 Relocator는 Relocatable 파일 형식으로 생성된 ELF64 파일을 Relocation을 수행해서 마치 Executable 파일 형식으로 생성된 것 처럼 만들어주는 프로그램입니다. 만약 문서를 제대로 이해했다면 Relocatable 파일 형식으로 나온 것을 Relocation 시킨 결과나 Executable 파일 형식으로 만든 결과가 같아야 합니다. 간단한 테스트 프로그램으로 테스트 해본 결과 디스어셈블리한 결과가 똑같이 나왔습니다. >ㅁ<)-b

 아아~ 이제 남은 것은 OS에서 ELF64 형식을 그대로 쓰느냐, 아니면 별도의 가공을 통해 새로운 파일 포맷을 만드느냐인데... 사실 가장 좋은 방법은 ELF64의 Relocatable 파일 형식을 그대로 쓰는 겁니다. 이렇게되면 별 다른 수정없이 윈도우나 리눅스 계열에서 빌드된 ELF64 파일을 그대로 실행할 수 있는 장점이 있습니다. 하지만 단점은 커널에 들어있는 실행파일 로더(Loader)가 복잡해진다는 것이지요. ㅠㅠ

 새로운 파일 포맷을 만드는 방법은 커널에 있는 로더를 간단히 할 수 있는 장점이 있습니다만, 파일 포맷을 변환하는 단계를 거쳐야되서 빌드 시에 단계가 하나 더 추가되는 단점이 있습니다. 파일 포맷 변환 프로그램도 작성해야하구요. ㅎㅎ

 이거 어느 것을 선택하는 게 옳은 건지 판단을 내리기가 좀 힘들군요. 빨리 이걸 결정해야 실행파일을 돌려볼 수 있을텐데... ㅠㅠ 어휴... 고민입니다. ㅠㅠ


 와우~ 거의 일주일 동안 작업해서 GUI 프로토타입을 완성했습니다. ㅠㅠ 삽질한걸 생각하면 눈물이 앞을... ㅠㅠ 흑흑... 오늘 윈도우 매니져가 개별 윈도우 메시지 큐에 메시지를 전달하는 기능을 추가하면서, 프로토타입을 겨우 완성했습니다.
 
 항상 추가된 기능은 어떻게라도 테스트를 해야하는 법~!! 테스트는 마우스가 윈도우 위를 지날때 윈도우 매니져가 마우스 이벤트를 윈도우 큐에 넣고,  윈도우는 큐에 데이터가 있는지 체크하는 방식으로 했습니다. 만약 마우스 데이터가 큐에 있다면 윈도우 가운데 있는 사각형 색깔을 바꾸도록 말이지요. ^^

 궁금하신 분들은 아래 파일을 다운 받으셔서 압축을 푸신 다음 "qemu64MyOs.bat" 파일을 실행하시면 GUI 프로토타입을 테스트 할 수 있습니다. ^^ 마우스가 클릭되거나 윈도우 위를 지나면 사각형이 반짝이는 걸 보실 수 있습니다.
아래는 스크린샷입니다. ㅎㅎ
사용자 삽입 이미지


 마지막으로... QEMU에서 마우스를 빠져나오게 하려면 Ctrl 과 Alt를 몇번 동시에 누르면 됩니다. ^^;;; 한번에 빠져나오는 경우도 있지만 몇번 눌러야 빠져나오는 경우도 있으니 당황하지 마시고 몇번 더 시도해보세요 ;)

 아아~ 이제 그만 자야겠습니다. 이번 주는 대충 여기까지~!!!
 그럼 좋은 밤 되세요 ^^)/~

 요 며칠 계속 알고리즘 고민한다고 거의 코딩 안하고 그림만 계속 그렸습니다. 자꾸 마음 속에 메모리를 적게 사용하고픈 하는 욕망이 타올라서 어떻게 하면 메모리 사용량을 줄일까만 고민했습니다.ㅠㅠ 메모리를 적게 사용하려면 결국 개별 윈도우가 임시 버퍼를 가지지 않고 프레임 버퍼에 바로 그려줘야 하는데, 이때 발생하는 깜빡임과 화면 업데이트 속도때문에 결정을 못하겠더군요. ㅠㅠ

 메모리를 적게 쓰려다 속도를 포기하는 상황까지 오게되자, 결국 개별 윈도우가 임시 버퍼를 가지는 방식으로 확!! 기울었습니다. ㅡ_ㅡa... 어플리케이션 몇개 실행하지 않을 건데 굳이 메모리를 아껴야하는 생각도 들고, 전체 화면으로 생성하는 어플리케이션이 몇 안되면 크게 문제가 안될 것 같은... ^^;;;; 어차피 간단한 GUI를 구현하고 잘 동작함을 보여주는 것이 목적이라서, 간단히 구현할 수 있는 방향으로 가는 것이 옳은 것 같습니다. ㅎㅎ

 아래는 간단히 구현해 본 윈도우 겹침 테스트 화면입니다. 총 3가지 색의 윈도우가 있고 마우스 포인터(파란색 작은 사각형)로 클릭하면 윈도우를 움직일 수 있도록 했습니다. memcpy, memset 함수가 대충 구현되어있을 때는 무시무시하게 느리던데(그리는게 다보여요 ㅠㅠ), 약간 튜닝해주니 광속으로 움직이는군요. @0@)-b 역시 64bit 짱~!!! 1024 * 768 화면 전체를 다시 그리는 최악의 경우에도 볼만하네요. ;)
사용자 삽입 이미지

 이제 윈도우 메니져와 응용 프로그램 사이에 Lock 처리만 해주고 API만 구현하면 대충 될 것 같습니다. 아휴~ 이거 원 정신이 하나도 없네요. ㅠㅠ 왜 이렇게 할 게 많은지... 어서 빨리 마무리해야 할텐데 말이죠. ;) 이렇게 나가다간 끝이 없겠습니다. 그런데 초보자용으로 시작한건데... OS 코드가 점점 복잡해지는군요. ㅠㅠ 어휴~ 이일을 어째... ㅠㅠ

 끄응~ 밤이 깊었으니 나머지 구현은 내일해야겠습니다.
 그럼 다들 좋은 밤 되시길 ;)


 
아유... 이것 참... 머리가 아픕니다. ㅠㅠ GUI Architecture를 구상하고있는데 어떤 것이 더 간단하고 효과적일지 고민하고 있습니다. GUI를 구현하는 방법에는 여러가지가 있겠지만 크게 아래와 같이 세가지를 생각하고 있습니다.

  1. 윈도우를 그릴때 Application에서 직접 Graphic Buffer에 접근해서 그린다.
  2. Window Manager가 Application의 Draw 함수를 호출해서 Serialize 해서 그린다. 즉 Kernel이 개별 Application의 함수를 호출한다.
  3. Application은 자신의 윈도우를 위한 임시 Graphic Buffer를 가지고 있고, 다 그리고 난 후 Graphic Buffer로 바로 복사해준다.

 1번처럼 구현하는 것이 가장 효과적일 것 같은데, 가장 마음에 걸리는 부분이 윈도우 겹침 처리더군요. 각 Application이 그리는 시간이 틀릴텐데, 마구잡이로 그리다가는 겹치는 부분에 대한 처리가 정상적으로 될 것 같지 않더군요. 아우... ㅠㅠ

 일단 좀 고민을 더 해봐야겠습니다. ㅠㅠ 어흑... 정말 산 넘어 산이군요.

ps) 혹시 Linux나 Windows의 GUI 구현에 대한 문서가 나온 게 있나요? 혹시 보신분 있으시면 덧글로 제보 부탁드립니다. ㅠㅠ


 요즘 야근이 너무 잦아서 생각보다 진도를 빨리 못나가고 있습니다. ㅎㅎ 그래서 밤잠을 줄여가며 코딩하고 테스트하고 있는데, 아흙 죽을 것 같군요. 내일도 회사에 출근해야해서 더 죽겠다는... ㅠㅠ

  현재 OS 진행 상황은 그래픽 모드로 전환까지는 완료한 상태입니다. 이제 남은 것은 Mouse를 사용하는 간단한 GUI를 만드는 것 정도인데... ^^;;; GUI를 만드는 것은 둘째치고 지금 Mouse 인터럽트 처리 때문에 고전하고 있습니다. ㅠㅠ

 아시는 분도 계시겠지만, PS/2의 Mouse 같은 경우 Keyboard의 데이터 포트와 같이 사용합니다. 즉 데이터 포트를 읽었을때 이것이 마우스 데이터가 될수도 있고 키보드 데이터가 될수도 있는 것이지요. ;) 자~ 그럼 어떻게 하면 가장 빨리 구분할 수 있을까요? 권장하는 방법은 인터럽트를 사용해서 인터럽트 서비스 루틴에서 바로 읽는 겁니다. 인터럽트는 데이터를 포트에 밀어넣은 즉시 발생하므로 정확하게 구분해서 읽을 수 있습니다.

 하지만 멀티 프로세서 환경에서 인터럽트를 사용하니, 기존에 없던 문제가 생기더군요. ㅡ_ㅡa... 인터럽트를 각 프로세서에 브로드캐스팅(Broad Casting)하므로, 프로세서 #0 이 마우스 인터럽트를 처리하는 동안 프로세서 #1은 키보드 인터럽트를 처리할 경우가 생기는 겁니다. @0@)-b

 위와 같은 상황에서 싱글 프로세서는 인터럽트 서비스 루틴에서 인터럽트가 불가로 설정하고, 순차적으로 데이터를 읽는 방법으로 처리할 수 있습니다. 하지만 멀티 프로세서의 경우는 동일한 포트에 순차적으로 접근하는 것을 보장해주는 기능이 추가적으로 필요합니다. 즉 프로세서 #0이 마우스 데이터를 읽는 동안, 프로세서 #1이 먼저 접근해서 키보드 데이터인줄 착각하고 읽는 일을 막아야한다는 것이지요. ㅡ_ㅡa...

 어떻게 처리할 지 상당히 고민됩니다. 같은 포트를 사용하는 서로 다른 인터럽트 소스의 경우에 싱글 프로세서처럼 하나의 프로세서에 할당해주면 간단히 해결할 수 있는데... 더 좋은 방법이 있을 것 같아서 ^^;;;; 아우... 생각보다 빡시군요. ㅎㅎ

 일단 고민을 좀 더 해봐야겠습니다. ;)
 그럼 다들 좋은 밤 되시길~

ps) Qemu 같은 경우 키보드 컨트롤러와 CPU의 키보드 인터럽트 간에 타이밍 문제(?) 비슷한게 있는 것 같더군요. 각 인터럽트에서 데이터를 읽을 때, 데이터 포트에 데이터가 있는지 확인하도록 했더니 마우스와 키보드를 동시에 움직이는 경우 간혹 문제가 발생했습니다. ㅡ_ㅡa... 키보드 데이터가 마우스 인터럽트에서 나오더군요. 싱글 프로세서인데 말이지요. ㅡ_ㅡa... 결국 데이터가 있는지 확인 안하도록 해서 해결했습니다. 이건 뭐... ㅎㅎㅎ


 주말에 살짝 작업해서 시리얼 통신과 그래픽 모드로 전환하는 기능을 추가했습니다. @0@)/~ 예전에 썼던 코드들을 그대로 긁어 붙였더니 진도는 잘나가는데... 왠지 좀... 찔리는 것이... ㅎㅎㅎ

 아래는 1024 * 768에 16bit Color로 설정해서 파란 사각형을 그린 화면입니다. ;) 아우 신납니다. ㅎㅎ 이제 NDS에서 사용했던 그래픽 라이브러리를 올려볼까 생각 중입니다. 그래픽 라이브러리를 다시 만들려니 머리가 아파서 ^^;;;;
사용자 삽입 이미지

 밤이 늦었으니 일단 자고 나머지는 내일해야겠군요. ㅎㅎ
 아래는 그래픽 모드 전환에 대한 문서인 VBE 3.0 스펙입니다. ;)

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


 ELF64의 Relocation 쪽을 실컷 파다가 문득 정신을 차려보니 잘 시간이 넘었더군요. 그래서 블로그의 덧글이나 확인하려고 들어갔는데, 요 며칠 포스팅한 글을 보니 잡담에 가까운 글이 많았습니다. ^^;;;; 아무래도 최근에 하고 있는 삽질 때문인 것 같습니다. ㅎㅎ

 언능 삽질을 끝내고 빨리 정리해야 할텐데... 욕심이 점점 많아져서 이것 저것 많이 하게 되는군요. 일단 지금은 간단한 GUI까지 해서 결과를 정리할까 생각 중입니다. GUI라고 해봤자 Frame Buffer 모드 비슷하게만 만들면 간단한 알고리즘으로 윈도우 비슷하게 흉내낼 수 있으니, 모양만 갖추는 거지요. ;) 아니면 닌텐도 DS에 올린 GUI 관련 소스를 사용해도 될 것 같습니다. ㅎㅎ

어휴, 할 것은 많고... 고민할 것도 많아서 머리가 지끈거립니다. 연이은 야근으로 인해 머리도 복잡하고 ㅎㅎ... 그래도 머리가 복잡한 덕분에 얻은 주옥같은 아이디어가 있어서 그나마 위로가 되는 것 같습니다.@0@)-b  주옥같은 아이디어가 뭔고 하니, 바로 한글 입력 처리에 대한 알고리즘입니다. ^^)/~

 일반적으로 한글 입력 처리는 오토마타를 사용해서 해당 상태에 따라 한글을 출력하는 방식을 사용합니다. 오토마타를 이해하면 쉽게 구현할 수 있는 부분이긴 하지만, 한글 입력 오토마타라는게 간단히 몇줄로 설명할 수 있는 내용이 아닙니다. 그래서 오토마타를 사용하지 않고 처리할 수 있는 부분에 대해서 고민하고 있었습니다. ㅠㅠ 그런데 갑자기 테이블을 사용해서 매치하는 방법이 떠오르더군요. @0@)-b

 아이디어를 간단히 설명하면 키 순서와 일치하는 한글을 테이블로 만들어서 입력된 키값과 테이블에 있는 값을 비교해서 처리하도록 하는 것입니다. 완성형 한글의 경우 숫자도 그리 많지 않으므로 충분히 테이블로 커버할 수 있을 거라는 생각이 듭니다. 구현 또한 아주 간단하고 오토마타보다는 더 직관적이지요. ;)

 아아~ 또 즐거운 주말이 다가오는군요. 이번 주말은 좀더 빡시게 굴러서 대충 마무리를 해야겠습니다. ;)
 그럼 다들 좋은 밤 되세요. ^^)/~



 며칠째 DMA만 계속 파고 있는데, 이거 아무래도 가상 머신에는 ISA DMA 3번과 HDD가 연결되지 않은 것 같습니다. 아무리해봐도 DMA가 시작되지 않는 걸 보니, 문제가 좀 있는 것 같군요. ㅠㅠ 분명 코드에는 별로 이상이 없는 것 같은데....

 답답한 마음에 이래 저래 뒤지다가 PCI쪽에 DMA를 써서 여기저기 데이터를 전송할 수 있다는 걸 알아냈습니다. PCI를 사용하면 ISA보다 빠르니 훨씬 더 빠른 전송이 가능할 거라는 생각이 들어서 PCI쪽으로 방향을 돌렸습니다. ;)

 사실 HDD에서 데이터를 읽어드리는데 DMA를 사용하지 않고 PIO를 사용해도 되지만... 뭐랄까요, 지금까지 OS를 만들면서 계속 PIO만 사용했고, 갑자기 오기같은게 생겨서... ^^;;;; 해보다 안되면 그냥 GG 치고 ELF Relocation이나 마져해야겠습니다. ㅠㅠ

 혹시 HDD와 DMA를 연결하는 방법에 대해서 아시는 분 계신가요? 계신다면 댓글 부탁드립니다.
 그럼 좋은 하루 되세요 ;)

 요 며칠간 일이 좀 있어서 소스코드를 깊게 볼 시간이 없었습니다. ㅎㅎ 그러다보니 오늘에서야 겨우 소스를 뒤져볼 수 있게 됬습니다만, 간만에 소스를 보니 너무 테스트 코드가 많아서 눈이 빙빙 돌더군요. @0@ 그래서 코드 정리에 돌입했습니다.

 사실 그동안 PIT(Programmable Interval Timer)때문에 삽질을 좀 많이 했습니다. MP Spec에 따르면 INIT -> SIPI -> SIPI를 보내는 동안 각각 10ms, 200us, 200us 씩 Delay를 하게 되어있습니다. 따라서 이 Delay를 맞추기 위해 생각한게 Timer를 사용하는 것인데... 생각보다 에뮬레이터들이 완벽하지 않더군요.

 Timer의 Interval을 변경할때 종종 문제가 발생했습니다. ㅠㅠ 그래서 Timer이 Interval을 변경하지 않고 Tick을 계속 읽어들여서 Counting하는 방법으로 해결했습니다. 약간 꼼수긴하지만 어쨋든 되긴하니 ^^;;;; 패스~

 정리하는 김에 Dual Processor만 지원하도록 되어있던 부분을 실행 시에 Processor의 수를 읽어서 동적으로 셋팅하는 코드로 변경했습니다. 커널 스택을 1M 정도로 잡아놔서 Processor가 많아지면 많아질수록 할당될 스택의 크기가 줄어드는 문제가 있긴하지만... 커널에서 큰 지역변수를 쓰지 않는다면 괜찮을 것 같습니다.

 현재 QEMU를 이용해서 16개까지 해봤는데, 큰 문제가 없는 것으로 보아 잘되는 것 같습니다. ^^)/~ 물론 더 많이도 지원할 수 있습니다만, 아직까지 그럴 필요성을 못느껴서 16개로 한정했습니다. 아래는 실제 실행한 화면입니다.
사용자 삽입 이미지

 Bootstrap Processor는 Task 1과 Task 2의 Multi-Tasking을 수행중이고, 나머지 15개의 Application Processor는 화면에 자신이 실행된 Count를 출력하도록 되어있습니다. 아래쪽에 각 Processor가 Keyboard Interrupt를 얼마나 처리했는가 하는 값이 출력되어있는데, 여러 Processor가 Interrupt를 처리하고 있음을 볼 수 있습니다. ^^

 아아~ 이제 ELF64에 Relocation만 보면 어느 정도 끝날 것 같습니다. ;) 오늘 저녁에 뚝딱 해치워야겠군요.
 그럼 다들 좋은 주말 보내시길~ ^^)/~


 오늘은 어플리케이션 실행때문에 elf64의 재배치(Relocation)에 대해서 보고 있습니다. 어디서 얼핏 elf64의 코드는 RIP를 Base로 사용하는 Addressing을 하기 때문에 재배치가 용의하다는 내용을 봤었는데, 용의하다는 뜻이 애매해서 한번 파봤습니다.

 테스트 결과 재배치 섹션(Relocation Section)이 역시 존재하며, 재배치를 수행해야 정상적으로 실행가능하다는 겁니다. 커널 코드를 4M 와 2M Base로 설정하여 빌드한 후 바이너리를 비교해 봤는데, 함수를 호출하는 부분의 코드는 변함이 없으나 데이터에 접근하는 부분 같은 경우는 역시나 Base Address에 영향을 받는 부분이 있더군요. Diff 프로그램으로 검사해본 결과 바이너리가 달랐습니다.

 이렇게 되면 결국 elf64 파일 포맷으로 어플리케이션을 빌드하고 OS에서 재배치해서 로딩하는 수 밖에 없겠군요. ㅎㅎ 약간 안습인 상황이... ㅠㅠ 아흑... 어찌해도 일거리가 줄어들지 않는군요.

 시간나면 elf 파일 포맷이나 봐야겠습니다. elf64 파일 포맷은 www.openwatcom.org/ftp/devel/docs/elf-64-gen.pdf 에서 보실 수 있습니다. ㅎㅎ

 오늘은 좀 일찍 컴퓨터를 꺼야겠습니다. 몸이 점점 축나서 회사 생활이 안된다는... ㅎㅎ
 그럼 다들 좋은 밤 되세요 ;)


 지금까지 진행된 소스 코드를 정리하고 있습니다. 테스트 코드를 워낙 많이 넣었더니 테스트 코드를 지우다가 실수로 원래 코드를 지우는 경우도 생겨서... ㅠㅠ 이거 표시를 제대로 해놔야겠더군요.

 제가 "변수명이나 매크로는 그 이름 자체가 자신을 설명할 수 있어야한다"는 주의라서 변수명/함수명 등등을 굉장히 길게쓰는 편입니다. ^^;;;; 특히나 커널 코드처럼 장래에 계속 볼일이 있는 코드 같은 경우는 더더욱 심한 편이지요.

 시간이 지나면 잊혀지기 마련인데, 주석이나 잡 문서로 아무리 잘 설명해 놓은들 변수나 함수 이름을 보고 무슨 뜻인지 한번에 알 수 없다면 문제가 있다고 생각합니다. 물론 각자의 스타일이 있으니 아니라고 생각하시는 분들도 있을거라 생각합니다(짧고 간결하게 쓰는게 더 낫다고 생각하시는 분들은 돌 던지지 말아주세요 ㅠㅠ 그냥 제 생각입니다. ㅠㅠ).

 그런데 너무 길게쓰니 함수 호출하거나 할 때 한 컬럼이 굉장히 길어지더군요. 저는 왠만하면 80 컬럼을 맞춰서 쓰려고 노력합니다. 따라서 개행을 해야하는데 결국 한 라인에 함수나 변수가 몇개 못 들어간다는... ㅠㅠ 크윽... 이거 최악의 조합인 것 같습니다. ㅠㅠ 소스코드가 좀 희한한 트리 모양으로 보이는 군요. ㅠㅠ

 어떻게 하는게 좋을지는 나중에 한번 의견을 나눠봐야하겠지만, 일단 길게 작업해두는 쪽으로 가야겠습니다. 일단 제가 이해하기 쉬워야 남들한테 설명하기도 쉬우니까요. ㅎㅎ

 어휴 벌써 또 시간이 이렇게 됬군요.
 다들 좋은 밤 되세요 ㅎㅎ ;)


 크윽... 죽는 줄 알았습니다. ㅠㅠ 지난 휴가와 이번주 주말을 모두 투자해서 드디어 Interrupt 처리 부분을 넣고, 나중에 사용할 APIC 와 IO APIC쪽 설정 기능을 넣었습니다. ㅠㅠ 사실 훨씬 더 일찍 끝났어야 하는 일이나... 가상 머신에 불완전함 때문에 코드를 고치고 테스트하다보니 많이 늦어졌습니다.

 현재 테스트 중인 가상머신은 총 3개인데, VMware, Bochs, 그리고 QEMU를 사용하고 있습니다. 재미있는건 각자 BIOS 설정이 조금씩 다르고, 같은 코드라도 동작하는 방식이 다르다는 것이죠. ㅠㅠ 이것 때문에 죽는 줄 알았습니다. 특히 Interrupt 처리부분에서 Bochs와 VMware에 문제가 있는 것 같더군요.

 테스트를 몇시간동안 한 결과 코드에서 Stack을 Align하지 않고 사용하는 경우, 간혹 Stack에 데이터가 덮어써져서 나중에 iretq로 돌아왔을 때 정상적으로 수행되지 않는 문제가 있었습니다. 원래 CPU가 realign을 해주게 되어있습니다만, 정상적으로 동작하지 않는 때가 있는 것 같습니다. 물론 꼼수로 해결했습니다만, 뭔가 좀 씁쓸하네요. ^^;;; 더 웃긴건 QEMU의 경우는 괜찮다는 것이죠. ;) 이 문제 때문에 거의 이틀을 꼬박 날렸습니다. 아흑 내시간...ㅠㅠ

 더 가관인 문제는 VMware에서 생겼습니다. Keyboard Interrupt를 발생하지 못하게 한 뒤에, 키를 마구 입력해서 키보드 버퍼를 체운 후 APIC쪽을 Enable 하니 Interrupt가 발생하지 않는 것이 아니겠습니까? @0@)/~!!! VMware의 APIC쪽하고 PIC쪽에 매치하는 부분에서 문제가 있는 것 같은데, 키보드 버퍼에서 데이터를 다 읽어내면 그때부터 인터럽트가 발생하기 시작합니다. ㅡ_ㅡa;;;;; 이것도 결국 땜빵코드로 해결... ^^;;;

 마지막으로 애교로 넘어가줄 수 있는 문제... Qemu에서 int 13, 즉 Disk Read에 문제가 있더군요. 여러 섹터를 읽도록 요청하면 간혹 덜 읽히고 종료되는 문제가 있었습니다. 이 문제는 어느정도 예상을 하고 있던 것이라 역시나 땜빵으로 해결... 예전에 만들면서 겪었던 문제라서 그냥 애교로 넘어갔습니다. ㅎㅎ

 결국 온갖 삽질 끝에 세가지 에뮬레이터에서 모두 동작시키는데 성공했습니다. 아래는 세가지 에뮬레이터에서 동작시킨 화면입니다.
사용자 삽입 이미지

사용자 삽입 이미지

사용자 삽입 이미지

 이제 대충 멀티 태스킹과 elf64의 재배치(Relocation) 쪽만 해결하면 되겠군요. ㅎㅎ 코어를 하나 더 활성화 시키는 것은 저번에 해봤으니 그냥 붙여넣기만 하면... (설마 이것도 쉽게 안되려나..ㅠㅠ)  그나저나 계속 삽질만 해서 큰일입니다. ㅠㅠ 크윽...

 제발 좀 한번에 가자 ㅠㅠ)/~~

 그럼 다들 좋은 밤 되시길~ ^^)-b



 Cywin에서 크로스 컴파일러를 만들기위해서는 먼저 소스 패키지를 설치해야합니다. setup.exe 를 실행해서 Devel 부분의 Binutil gcc-core 의 소스 패키지를 선택하고 설치를 수행하면 소스가 /usr/src 폴더에 설치될 겁니다. ^^

1.Binary Utility Build

 제일 먼저 해야할 일은 binutil을 빌드하는 일입니다. x86_64용 크로스컴파일러를 빌드하기 위해서는 x86_64용 ld와 as 등등 각종 링커와 어셈블러들이 필요하기 때문이지요 ;) bintul을 빌드하는 방법은 아래와 같습니다.
  • export PREFIX=/usr/cross
  • export TARGET=x86_64-pc-linux
  • ./configure --target=$TARGET --prefix=$PREFIX --enable-64-bit-bfd --disable-shared
  • make configure-host
  • make LDFLAGS="-all-static"
  • make install
 위와 같이 실행하고나면 정상적으로 build된 경우 /usr/cross 라는 폴더가 생성되어있을 겁니다. 그 폴더에 들어가보시면 빌드 결과물을 확인할 수 있습니다. ;) 현재 x86_64 용 glib가 생성되어있지 않은 상태이므로, 공유라이브러리를 사용하지 않도록 --disable-shared-all-static 옵션을 줘야합니다. 주지 않을 경우 나중에 gcc 빌드할 때 문제가 발생합니다. ㅜ_ㅜ crti.o가 없다고 계속 에러가... ㅠㅠ

2. GCC Build

 그 다음 해야할 일은 gcc를 생성하는 일입니다. cygwin에 포함된 gcc 소스에는 소스 파일과 패치파일을 포함하고 있습니다. 정상적으로 빌드하기위해서는 패치를 수행해야 하는데, 다행이도 gcc-3.4.4.sh 라는 스크립트가 있습니다. 아래의 빌드를 수행하기 전에 먼저 아래와 같이 입력해서 패치를 수행합니다.
  • gcc-3.4.4.sh prepare
 위 과정이 정상적으로 끝나고나면 gcc-3.4.4-3 이라는 폴더로 이름이 변경될겁니다. 그럼 해당 폴더로 이동해서  아래의 순서대로 실행합니다.
  • export PATH=$PREFIX/bin:$PATH
  • ./configure --target=$TARGET --prefix=$PREFIX --disable-nls --enable-languages=c --with-newlib --without-headers --disable-shared --disable-threads
  • make configure-host
  • make LDFLAGS="-static" all-gcc
  • make install-gcc
 위와 같이 실행하고나면 /usr/cross에서 gcc관련 파일들을 보실 수 있습니다.

 이 간단한걸 하려고 며칠을 해매었는지 모르겠군요. ㅜ_ㅜ)-b
 다른 분들은 이런 걸로 고생 안하셨으면 합니다. ㅜ_ㅜ
아아~ 진짜 거의 3일만에 성공했습니다. ㅜ_ㅜ 주말 내내 붙잡고 있다가 해결 못하고 있었는데... 구글의 자료를 뒤지다가 --disable-shared 옵션 및 LDFLAGS="-static" 으로 해결했습니다.

 ㅜ_ㅜ 진짜 되고 안되고가 한끗 차이더군요. 저런 옵션 하나때문에 몇시간을 날렸는지... ㅜ_ㅜ... 아래는 빌드가 끝나고 cygwin에 설치된 64bit 크로스 컴파일러(cross complier) 입니다. 감동해서 스샷 하나 찍어 올립니다(반갑다 애들아~ 우리 이제 잘해보자꾸나...). ㅜ_ㅜ)-b

사용자 삽입 이미지

 자세한 빌드 방법은 내일 정리해서 올리겠습니다. 앞으로는 저처럼 삽질하는 사람이 없었으면 하는 생각이 드는군요. 진짜 어의없습니다. ㅜ_ㅜ

 그럼 다들 좋은 밤 되시고, 내일 허접한 문서로 다시 찾아 뵙겠습니다. ㅜ_ㅜ)-b
 거의 4일 동안 문서를 뒤지고 직접 테스트를 수행한 결과, IO APIC와 APIC간의 관계와 8259A(PIC) 칩간의 관계에 대해서 알아냈습니다. 더불어 BIOS에 존재하는 MP 관련 정보와 IO APIC의 Redirection Table, CPU의 APIC의 레지스터에 의미에 대해서도 대충 알아냈습니다. ㅜ_ㅜ)-b

 어떻게 테스트 했는지는 나중에 올리겠습니다. 나름 복잡한 내용을 포함하고 있고, 또 시간이 너무 늦은지라 ㅎㅎ 대신 아래의 스샷을 첨부합니다. 제가 만든 OS(KKAMAGUI OS)에서 IO APIC를 통해 BSP(Bootstrap Processor)에 키보드와 타이머 이벤트를 밀어넣는 화면입니다. 볼품없지만 이게 4일 동안 작업한 것이라는... OTL....
사용자 삽입 이미지

 그래도 IO APIC와 Local APIC에 대해 잘 모르면 Sysmmetric I/O로 갈 수 없기 때문에 어쩔 수 없었습니다. ㅜ_ㅜ)-b 결국 하긴 했군요. 흑흑.... 8259A(PIC) 컨트롤러의 타이머/키보드 인터럽트를 발생 못하도록 mask 했는데도 인터럽트 방식으로 잘 동작하는 화면을 보니 신기하군요. ^^;;;;

 그럼 이만 자야겠습니다. 좋은 밤 되시길~ ;)
 예비군 내내 Intel Architecture Volume 3을 봤습니다. 그리고 고향에 내려오는 도중에 PSP로 Multile Processor(MP) Spec을 계속 봤었는데... 뭔가 좀 이상하더군요. Intel 문서에는 I/O APIC에 대해서 아주 조금 언급하고 있습니다. 그냥 APIC와 연결되있다는 정도로 말이지요. ^^;;;;
 
 그런데 MP Spec에 보면 PIC, Virtual PIC, Symmetric I/O의 각 방식에 대해 아래와 같이 자세히 그려놓고 있습니다.
사용자 삽입 이미지
<PIC 모드>
사용자 삽입 이미지
<Virtual Wire Mode With Local APIC>
사용자 삽입 이미지
<Virtual Wire Mode With IO APIC>
사용자 삽입 이미지
<Symmetric IO Mode>

  보시면 아시겠지만 CPU의 Boundary 안쪽에 IO APIC가 있는지 바깥쪽에 있는지 좀 불분명합니다. 어렴풋이 버스 배열 상태나 위치를 봐서 바깥쪽에 있다고 추측합니다만... 이것만 봐서는 확실히 알수가 없었습니다. 그래서 이것 저것 뒤지다보니 intel-82093-apic 문서를 찾았습니다. IO APIC 컨트롤러에 대한 문서더군요. ^^;;; 거의 바깥쪽에 있는게 확실한 것 같습니다. 그런데 이게 왜 중요했던건지... ㅡ_ㅡa;;;;

 생각난 김에 VMWare의 부팅했을때 모드가 위의 그림 중에 어떤 것인지 확인을 좀 해봤습니다. 몇가지 테스트가 있는데... 테스트 과정은 좀 복잡해서 생략하고 결론만 이야기하면 Virtual Wire Mode With Local APIC 인 것 같습니다. 왜냐하면 I/O APIC쪽에 Interrupt Remapping Table인가 하는 녀셕이 Default 값으로 되어있거든요. 즉 안쓴다는 이야기지요. ^^;;; 그동안 다른쪽 코어에는 인터럽트쪽 설정을 안했기 때문에 별 신경을 안쓰고 있었는데, 이제 다른 코어에 인터럽트를 활성화하려면 이것이 중요한 단서가 되서 한번 읽어봤습니다.

 음... 이제 몇가지 코딩을해서 Symmetric IO Mode 로 전환하고 테스트를 좀 더 진행해볼 생각인데... 이것 참... 할일이 많네요. ^^;;; 언제쯤 또 할 수 있을지... 요즘 들어 시간이 부쩍 부족한 것 같습니다. ㅎㅎ 그래도 잘 쪼개서 이것 저것 해봐야겠지요 ;)

 그럼 다음에 또 테스트해서 결과가 나오면 올리겠습니다. ㅎㅎ 다들 좋은 하루 되세요 ;)

ps) APIC 관련 자료가 참 없더군요. 참 불모지(?)스럽다는.... ㅡ_ㅡa...


 어제 갑자기 책 한권 써보는게 어떨까하는 생각이 들었습니다. 뭐 미치지 않고서야 이런 생각을 하겠냐만, 마이크로소프트웨어에 올리기에는 좀 복잡하고 양이 많다고 생각하고 있던 주제라서... ^^;;;; 해당 주제에 관한 자료가 인터넷에서 찾기 힘들 뿐더러, 실제로 구현된 사례도 그리 많지 않은 것 같더라구요. ^^;;;;

 일단 될지 안될지는 모르겠지만 한번 출판사에 연락을 취해볼 생각입니다. 기획쪽이나 그런 곳에 연락을 취하면 되겠지요. ㅎㅎ 주제나 자세한 내용은 일단 결정이 나면 올리겠습니다. ^^;;;;

 아아~ 이거 오늘은 작업을 하나도 못하고 그냥 자겠군요. 빨리 가상 HID 드라이버도 완성해야하는데... ㅎㅎ 내일 해야겠습니다. ^^)/~

 그럼 다들 좋은 밤 되세요 ^^)/~
 헛... 이런 마이크로소프트웨어 4월호가 온지 좀 됬는데 이제서야 봤습니다. ^^;;; 다른 것 하느라 정신이 없어서 미처 보질 못했네요. ;)

 이번호를 마지막으로 OS Framework에 대한 내용이 끝났습니다. >ㅁ<)/~ 사실 입사 한달 전에 4개월 연재가 결정이 나서 급하게 3개월분을 미리 썼기 때문에 내용이나 예제가 좀 미흡한 면이 있었습니다. 마지막 4월호 역시 급하게 정리해서 역시나 안타까움이 남습니다. ㅜ_ㅜ

 글을 정리하면서 꼭 해보고 싶었던 일이었기에 나름 최선을 다했는데,  다시 읽어보니 좀 부끄럽군요. 내용이 영 부실한게... ㅡ_ㅜ... 기회가 된다면 지금 보고있는 내용들(Dual Core)도 기고를 해봐야겠습니다. 뭐 실리게 될지는 알 수 없지만... 그냥 묵혀두는 것 보다는 좋겠지요 ;)

 아래는 마이크로소프트웨어 4월호의 목차입니다.

=====================================================
STEP BY STEP

VS 2008을 이용한 블로그 프로그래밍│최지훈  290
실전 블로그 프로그래밍 2

3D 소프트웨어 플러그인 개발기│조영락  298
가지각색 3ds Max 플러그인

리눅스 시스템 프로그래밍│서상원 306
고급 파일 입출력

프레임워크로 다시 보는 운영체제 개발│한승훈 314
스케줄러 및 동기화 객체 구현하기

오픈소스 검색 엔진의 세계│이성호 322
컴파스 프레임워크

=====================================================

ps) 끝으로 아무것도 아닌 제 글을 실어주신 마이크로소프트웨어의 문경수 기자님께 감사를 드립니다.
 
 아아~ 요즘 집에오면 틈틈이 Multiple Processor에 대한 내용을 파고 있습니다. 스펙을 볼때마다 느끼는 것이지만, 스펙을 분석하는 과정은 퍼즐 맞추기와 굉장히 비슷하다는 생각이 듭니다. 퍼즐을 맞추기를 시작할때는 퍼즐 조각만 보입니다. 그러다 이제 퍼즐 맞추기에 힌트가 되는 면을 찾게되고 하나, 둘 끼워맞추다보면 어느새 전체적인 그림이 눈에 들어오고 얼마 남지않은 조각을 이용해서 쉽게 맞출 수 있습니다.

 지금 제가 하고있는 과정을 퍼즐 맞추기 과정에 대응시킨다면, 면을 찾는 과정쯤 되겠군요. 면을 찾아 퍼즐을 놓는 과정은 놓은 조각을 주위에 힌트로 쓸 수 있어 좋은 반면, 놓을 자리가 많아졌으니 고민할 것도 많아지는 단점이 있습니다. 지금 제 상황이 딱 그 상황인데, 조각이 맞춰져 가면 갈수록 궁금한 점이 생기더군요.

 현재 프레임워크를 사용해서 듀얼 코어 중에 나머지 하나의 코어를 동작시켰습니다. 물론 Real Mode지요. 이제 보호모드로 전환시키고 인터럽트 처리를 수행해야하는데, Symmetric Interrupt Mode로 동작하려하니 문제가 몇가지 생겼습니다.
 첫번째는 두 CPU에 Interrupt가 동시에 발생할텐데, 한쪽이 처리했을 때 나머지 한쪽은 어떻게 할 것인가 하는 문제입니다.
 두번째는 동일한 Interrupt가 계속해서 발생할 때, 두 CPU가 Interrupt를 처리하는 타이밍이 다르다면 언젠가는 한쪽에서 Interrupt가 밀리게 되는 일도 있을텐데 이를 어떻게 판단할 것인가 하는 것입니다.

 지금은 별로 퍼즐을 모은 게 없어서, 큰 그림이 보이지는 않지만 조만간 결판을 내고 구현에 들어갈 생각입니다. 하지만 그 전에 잠부터 좀 자야겠군요. 요즘은 12시만 넘으면 죽을 것 같습니다. ㅎㅎ

 그럼 다들 좋은밤 되세요 >ㅁ<)/~
 
 ps) TV에서 데이 브레이크를 봤는데, 상당히 흥미롭더군요. 잘못하면 드라마에 빠져서 작업을 안할 위험도... ^^;;


 고군분투 끝에 드디어 살짝(?) 동작시키는데 성공했습니다. '파랑새를 찾아서'란 고전에서 보면 그토록 찾아 다니던 파랑새가 자기 집에 있다는 내용이 나옵니다. 답이 먼곳에 있는 것이 아니더군요. 역시 처음에 보던 INTEL 메뉴얼에 있었습니다. ㅠ_ㅠ

 여기저기 다니긴 했지만 비슷한 내용만 반복해 언급되어있고, 실질적인 코드는 없었습니다. 프로그래머라면 백마디 말보다 한줄의 코드가 더 중요한법~!!! 한참을 뒤지다 문득 INTEL 메뉴얼에 나와있는 어셈코드가 떠올랐는데, 바로 그 코드가 핵심이었습니다. 물론 아무것도 모르는 상태로 그 코드를 봐봤자 평범한 어셈블리어 코드일 뿐입니다만, 여기저기를 뒤진 탓인지 다시보니 딱 알겠더군요. ^^;;;;

 일단 Real Mode에서 Halt 상태로 되어있는 Application Processor를 활성화시켜서 콘솔화면의 좌측 상단에 색깔을 바꿔가면서 문자를 찍도록 수정했습니다. 테스트를 하는 과정에 약간 문제가 있었지만, 그래도 잘 동작하네요. ^^)/~

사용자 삽입 이미지

 이제 Application Processor를 32bit 보호 모드로 바꾸고 실제 태스크를 할당해서 실행해볼 생각입니다. 조금만 더하면 어느정도 마무리가 되겠네요. 정리되면 또 올리겠습니다.

 다들 좋은밤 되세요 ^^)/~~



 3월호 원고도 무사히 넘어갔습니다. ^^)/~ 사실 글이 너무 넘친다는 기자님의 말씀이 있었습니다만, 제가 그때 PC에 아무것도 안깔린 상황이라... ^^;;; 결국 페이지가 2페이지나 늘었더군요. ㅎㅎㅎ 페이지가 늘어난다는 것은 쓰는 사람의 입장에서는 좋은 일인 것 같습니다.
 
 4월호 원고도 미리 보냈는데, 별 이야기가 없는 것을 보면 잘된 듯 합니다. 4월호가 마지막인데, 왠지 시원 섭섭하네요. ^^)/~ 다음에는 Multiple Processor Control 에 대해 다루어 볼까 합니다. 상용 OS를 제외하고 INTEL이나 AMD의 Multiple Processor를 완전히 다루고 있는 OS를 아직 못봤고, Multiple Processor에 대한 자료가 너무 없기 때문에 의미가 있을 듯 합니다. ^^)/~

 그럼 마이크로소프트웨어 3월호 목차 나갑니다.

=====================================================
STEP BY STEP

VS 2008을 이용한 블로그 프로그래밍│최지훈  290
실전 블로그 프로그래밍 1

3D 소프트웨어 플러그인 개발기│조영락  298
3ds Max SDK 레퍼런스

리눅스 시스템 프로그래밍│서상원 306
시스템 프로그래밍의 이해

프레임워크로 다시 보는 운영체제 개발│한승훈 312
스케줄러 및 동기화 객체 구현하기

오픈소스 검색 엔진의 세계│이성호 322
텍스트 검색 엔진, 루씬(Lucene)

=====================================================


 요즘 몸이 좀 허해져서 그런지 오늘 아침에 코피가 났습니다. 어의가 없더군요. ㅡ_ㅡa 뭐 그래도 요즘 잠을 별로 안자고 있기 때문에 그럴수도 있겠다는 생각을 했습니다. ^^;;; 설마 몸에 이상이 있을라구요 ㅎㅎ

 Multiple Processor 분석 쪽은 일단 문서를 정리하고 정리된 문서를 바탕으로 실제 테스트를 해보는 방식으로 진행하고 있습니다. 문서만 주구장창 읽으니 눈에 보이는 것이 없어서 더욱 깜깜하더군요. 그래서 가상머신을 이용해서 직접 테스트를 해봤는데, 의외로 결과가 잘나옵니다. 신기하네요 @0@)/~ 물론 지금은 아주 약소한 단계의 테스트만 진행하고 있습니다. ^^;;;;

 내일 일하러 가면 이틀동안 쉬는군요. 집에 내려갈까 가지말까 심하고 고민하고 있습니다. 내려가는데 걸리는 시간도 문제지만 몸이 피곤해서... ㅜ_ㅜ... 만약 안내려간다면 주말에 MP쪽 문서에 All in할 생각입니다. 이게 빨리 끝나야 본래의 목적인 Virtualization을 볼 수 있어서 ㅎㅎㅎ

 아우~ 오늘은 좀 일찍 자야겠군요. 자기 전에 오늘 테스트한 스샷 하나 올립니다.
사용자 삽입 이미지

 그럼 좋은 밤 되세요 ^^)/~


 Multiprocessor에 대한 INTEL의 문서를 읽다가, 뭔가 부족한 느낌이 들어서 웹검색을 했습니다. 여기저기를 뒤지다가 우연히 OS 개발 관련 링크에 들어갔는데, 월척(!!!!)을 낚았습니다. ㅜ_ㅜ)/~

 사이트 주소는 http://www.osdever.net/cottontail/#SMP%20(IA32)이고 가보시면 INTEL의 Multiprocessor Specification 문서와 Multiprocessing Support for Hobby OSes Explained 문서를 보실 수 있는데, Multiprocessor와 BIOS, 그리고 OS 간의 관계를 잘 설명해 주고 있습니다. 문서를 읽자마자 궁금했던 점이 바로 이해되더군요. 문서가 아주 깔끔히 정리되어있습니다.

 그런데 놀라운 사실은 Multirprocessor Specification 문서가 1997년도에 1.4 버전이 됬다는 겁니다. 좀 읽어보니 CPU가 486 정도 일때 부터 Multiprocessor에 대한 내용이 나오기 시작한 것 같던데, 역시 대단하다는 생각밖에는 안듭니다. 이렇게나 일찍부터 Multiprocessor에 대한 준비를 하고 있었다니... ㅜ_ㅜ...

 덕분에 진도를 꽤 빨리 나갈 수 있게 됬습니다. 회사 일 끝나고 틈틈이 정리해서 나중에 한꺼번에 올리겠습니다. 오늘은 잠이 잘 올 것 같군요. ;)

 그럼 다들 좋은 밤 되세요~ >ㅁ<)/~

ps) 잘하면 OS 프레임워크의 Multiprocessor 버전이 나올지도 모르겠습니다. ;)~


+ Recent posts