OS를 만들면서 지금까지는 makefile을 거의 배치 파일 수준으로 사용하고 있었습니다. 이게 무슨 말이냐 하면... 디렉토리에서 소스 파일 이름만 달랑 추출하고, .C 파일과 같은 소스 파일이 수정되었을 때만 커널을 다시 빌드한다는 이야기입니다. 귀차니즘때문에 이렇게 쓰시는 분들이 많을 것 같다는... ^^;;;; 이렇게 되면 헤더 파일이 수정되었을 때, 해당 헤더 파일을 당겨쓰는 .C 파일들이 자동으로 빌드되지 않기 때문에 문제가 생깁니다.

뭐, 사실 혼자 테스트 할때는 매번 Clean해서 전부 삭제하고 다시 빌드하면 되니 신경을 안썼는데... 거사(?)를 치루려다 보니 이런것 하나하나가 신경 쓰이더군요. 결국 makefile을 뒤엎어서 의존성 관련 부분을 추가했습니다. 거의 3시간 정도 이것만 한 것 같네요. ㅠㅠ

C 파일로 부터 의존성 정보를 뽑는건 아주 간단합니다. "gcc -c -M Main.c Main2.c > a.txt" 와 같이 옵션을 주면 아래와 같이 이쁘게 출력해 줍니다. 이렇게 생성한 a.txt 파일을 makefile에 포함시켜주면 나머지는 규칙에 따라서 알아서 빌드해 줍니다. :)
Main.o: ../Source/Main.c ../Source/Main.h
Main2.o: ../Source/Main2.c

makefile에 포함시키려면 다음과 같이 써주면 됩니다. $(wildcard a.txt)는 디렉토리에서 a.txt 패턴이 들어간 파일명들을 스페이스바로 구분한 리스트를 나타내며, ifeq는 두 항목을 비교하는 것입니다. 즉 아래 코드는 같은 디렉토리에 a.txt가 있으면 해당 파일을 makefile에 포함시키라는 의미입니다.
ifeq (a.txt, $(wildcard a.txt))
include a.txt
endif

위의 내용을 추가해서 만든 makefile을 실행한 것입니다. 의존 관계에 대한 정보가 아주 자알~ 생성되고 있음을 볼 수 있습니다. ;)
C:\MINT64\01.Kernel32>make dep
make -C Temp -f ../makefile InternalDependancy
make[1]: Entering directory `/c/MINT64/01.Kernel32/Temp'
gcc.exe -c -M ../Source/Main.c ../Source/Main2.c > .dependancy
make[1]: Leaving directory `/c/MINT64/01.Kernel32/Temp'

아아~ 이거 원... 마음이 급해서 날림으로 만들었더니, 이런데서 시간을 많이 잡아먹는군요. ㅎㅎ 하루를 그냥 날린 것 같습니다. ㅠㅠ 나머지 작업은 할 수 없이 내일 해야겠네요. ;)

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

여자 친구가 와서 주말 내내 바이오 하자드를 했습니다. ㅡ_ㅡa.. 역시 여자 친구가 헤어나질 못하더군요. ㅎㅎ 어찌나 재미있어 하던지… 덕분에 벌써 Easy 모드 끝판을 깼습니다. ㅡ_ㅡV 여자 친구가 기뻐하는 모습을 보니 사기를 잘했다는 생각이 드네요. ^^;;; 평소에 뭐하나 제대로 해준 게 없었는데, 이걸로 어느 정도 만회한 것 같습니다. 앗싸~!!!

덕분에 이번 주말은 거의 진도를 못 뺐네요. ㅎㅎ 그래도 세상에서 가장 간단한 부트 로더(?)를 만드는 내용까지는 진도를 나갔으니 다행입니다. 어찌나 간단한지 정신이 휑~ 해질 정도입니다. 이래서야 욕이나 얻어 먹지 않을까 걱정이 되는군요. ^^;;;;; 그래도 처음에는 뭐든지 다 힘들고 어려우니, 이 정도 내용은 되야 어떤 사람(?)이라 충분히 따라올 수 있을 꺼라고 위로하면서 쓰고 있습니다. 과연... 그럴지는 저도 잘… ㅠㅠ

개구리가 올챙이적 모른다고... 처음에 OS를 만들 때는 힘들고 어려운 게 사무쳐서 내가 나중에 잘 알게 되면 이런 이런 내용을 주로 다뤄야겠다고 생각 많이 했었는데... 지금은 그런 내용들이 하나도 생각 안 나는군요. 오히려 지금은 당연히 알고 있어야 하는 내용이라고 생각도 하는 부분도 있어서 상당히 조심스럽습니다. 아무래도 이런 가정들이 하나 둘 늘어 가다 보면, 중요한 내용을 빠뜨릴 것 같다는 느낌 때문일 겁니다. ^^;;;

어휴… 역시나 쉽지 않군요. 그래도 일단 달려 보겠습니다. 듬직한 후배들만 믿고 말이죠. ;)

ps) 이 글을 보고 있는 후배야... 바로 너란다 ㅋㅋ 앞으로 잘 부탁하께 ㅋㅋ

이거 뭐… 원래 퇴근 시간이 5시인데… 처음에 야근할 때는 6시만 되도 화가 나더니만, 이제는 9시 30분에 퇴근해도 일찍 온다고 좋아하는 군요. ㅡ_ㅡa.. 이거 원... 이렇게 살면 안 되는데 ㅎㅎ

덕분에 오늘은 빨래도 하고, 청소도 했습니다. ㅎㅎ 이제 작업도 좀 해야겠습니다. 요즘 계속 64bit 멀티 코어 OS에 대한 내용을 정리하고 있어서 다른 곳에 신경을 쓸 틈이 별로 없네요. 계속 마음은 급하고, 시간은 안나고... 욕심에 쓸 내용은 많은데 정리는 잘 안되고... ^^;;;;

그래도 조금씩 체워져가는 A4 용지를 보니, 뿌듯하네요. 뭔가 하고 있다는 느낌이 듭니다. ^^)-b 에궁~ 그럼 또 작업 하러 가야겠습니다.

다들 건강 조심하시고 좋은 밤 되세요 ;)

이번 주말은 좀 특별해서 시간이 많이 날 줄 알았는데, 결혼식이다 뭐다 하는 바람에 결국 시간에 쫓기고 말았습니다. ㅠㅠ 주말에 해야지 하면서 잡았던 스케줄은 엉망이 됐습니다. 이궁…

결국 이렇게 되면 또 평일에 번개같이 집으로 달려와서 이것 저것 하는 수 밖에 없는데… 어쩔 수 없군요. 이번 주도 미친듯이 집으로 달려와야겠습니다. @0@)-b 물론 며칠이나 가능할지는 두고 봐야 알겠지만 말입니다. ㅎㅎ

요즘 계속 글 쓰는게 어렵다는 생각을 합니다. 예전부터 느끼고 있던 거였지만, 요즘 들어 쓰는데 시간을 많이 투자하다보니 더 깊이 와 닿습니다. 정말 무슨 책이라도 한권 봐야할까요? ㅠㅠ 이럴 줄 알았으면 책이라도 왕창 읽어 놓는건데… 한참을 쓰다 보면 내가 무슨 말을 하고 싶은 건지 잊어 먹는 경우도 종종 있고, 적당한 어휘가 떠오르지 않아 한참을 고민하는 경우도 많습니다. 아무래도 국어가 따리는거 같네요. ㅠㅠ

아흑… 계속 쓰다보면 좀 나아지려나… 글짓기에 소질이 없어서 그런가보다 하고는 있는데, 무지 힘들군요. ㅎㅎ 그래도 시작한 일이니 계속 해야겠지요. ;) 일단 열심히 해볼 생각입니다. @0@)-b 홧팅~!!!

헛… 벌써 시간이 이렇게… 이만 자야겠습니다. 다들 좋은 밤 되세요~ ;)

ps) elf64 관련 문서는… 결국 주중에 업데이트 해야겠네요. ㅠㅠ)-b 아흑…

소프트웨어 멤버십에서 활동할 때 자료 남기는 습관이 든 이후로,  뭘 했다 하면 주절 주절 적어 놓는 게 버릇이 됬습니다. 메모장은 보통 회사 밖에서는 스프링노트(http://kkamagui.tistory.com)을 많이 쓰고, 요즘은 회사 때문에 미투데이(http://www.me2day.net/kkamagui)를 씁니다. 회사에서는 블로깅하기도 힘들 뿐더러, 회사가 보안이 나름 엄격한지라 외부로 뭘 보내면 의심을 받거든요. ^^;;;;

요즘 OS를 만드는 내용에 대해서 정리를 하고 있는데, 초반 설치부터 GUI 애플리케이션까지 모든 과정을 다 다루려고 하니 쓸게 한두가지가 아니더군요. 쩝쩝 힘듭니다. ㅠㅠ 오늘은 GCC 소스를 이용해서 크로스 컴파일러를 만드는 내용을 좀 적어 봤는데, 예전에 블로그에 남긴 글을 참고하면서 썼습니다. 정말 간단한 메모만 남겼는데 그것 때문에 훨씬 수월하게 끝낼 수 있었습니다. 처음에 크로스 컴파일할 때는 옵션부터 시작해서 빌드 순서까지 수많은 시행착오를 거치며 며칠 동안 했었는데, 오늘은 1시간도 안 걸려서 끝나더군요. ㅠㅠ)-b GCC 소스를 통해 크로스 컴파일러를 만드는 방법은 http://kkamagui.tistory.com/507 에서 볼 수 있습니다.

아흑... 정리란 역시 좋은 것이군요. 이게 없었더라면 주말 다 날릴 뻔 했습니다. ㅠㅠ 얼마나 다행인지... ㅎㅎ 앞으로도 계속 열심히 남겨야겠습니다.

메모 쵝오 >ㅁ<)-b

ps) 그러고보니 스프링노트에 elf64 파일 포맷 재배치하는 방법에 대한 글을 쓰다 말았는데, 언능 마무리해서 포스팅해야겠군요. (근데 볼 사람이 있을라나… ㅡ_ㅡa..)

이거 원… 오늘 메타 블로그 사이트에 들어갔다가 고전 게임인 테트리스에 저작권이 걸려있다는 글을 봤습니다. 몇 해전에 그 많던 온라인 테트리스 게임이 사라진 이유도 저작권 계약을 하지 못해서였다네요.

이런… OS에 응용 프로그램으로 테트리스 만드는 걸 하려고 했는데, 다른 게임으로 대체해야겠습니다. ㅠㅠ 이거 원 만들어 놓고도 못쓰니 살짝 답답하군요. 끄응... 그럼 당체 무슨 게임을 만들어야… ㅠㅠ 퍼즐 맞추기 같은 거는 저작권이 없을라나... 아님 피자 먹는 스네이크 게임이라도... ㅠㅠ

혹시 이런 게임이 들어갔으면 좋겠다고 생각하시는 게 있으시면 댓글로 제보 부탁 드립니다. 최대한 반영해서 OS에 넣도록 할테니, 괜찮다고 생각하시는 게 있으시면 바로 댓글 주세요 ;)  정 안되면 퍼즐 맞추기라도 해야... ㅠㅠ

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

아유… 요즘 OS를 대충 만들어 놓은 거에 대해서 글을 좀 적고 있습니다. 글 재주가 워낙 없는지라 진도가 무지 안 나가는군요. 쩝쩝… 특히 앞부분은 기술적인 내용보다는 소설(??)에 가까운 내용들이라 더 진도가 안 나가는 것 같습니다. ㅡ_ㅡa... 그렇다고 안 쓸 수도 없는 일이니… 쿨럭;;;

겨우 겨우 서론 부분을 끝내 놓고 나니 이번에는 환경 구축이 문제로군요. GCC와 NASM을 사용해서 개발했기 때문에 이 두 가지만 설치 가능하면 이론상(?) 어디서든 OS를 개발할 수 있습니다. 물론 GCC가 64Bit 빌드 옵션을 지원하지 않으면 크로스 컴파일러를 만들어야 하는 부분이 추가되긴 하지만... 이러한 수고로움 정도야 OS를 개발하는데 드는 시간과 노력에 비하면 아무것도 아니지요. ㅎㅎ

아아~ 이것 참... 그냥 윈도우에서 개발하는 걸로 못 박기는 그렇고... 이것 저것 차이를 들어서 적자니 귀차니즘이 도지는군요. ㅠㅠ 이 일을 어찌해야... 뭘 정리하는 게 쉬운 일이 아닌 것 같습니다.

크으... 일단 오늘은 이만하고 내일 다시 해야겠습니다. 창작의 고통 + 잠이 몰려와서 죽을 것 같군요. ㅎㅎ

다들 좋은 밤 되세요 >ㅁ<)-b

오늘 간만에 글을 좀 썼습니다. 사실 썼다는 표현보다는 쓰고 있다는 표현이 더 맞는 것 같습니다만… ㅎㅎ  역시나 진도가 안나가는군요. 마이크로소프트웨어 기고할 때도 그랬는데, 역시 서문이 가장 어려운 것 같습니다.

저 같은 경우 본문은 소스 코드 설명이나 현상 설명 같은 내용들을 주로 넣으니 굳이 작문을 할 필요가 없는데, 서문 같은 경우는 그런 내용이 아니라 좀 가벼운 내용들 + 잡설 위주로 쓰는 편이라 상당한 고통이 따릅니다. 말 그대로 “작문”을 해야하니… 말 주변이 없는 저로서는 출산의 고통(?)과 맞먹는군요. ㅠㅠ 끄응… 그래도 넘어야 할 산이니만큼 꾸역꾸역 써야겠지요. ㅠㅠ

아래는 2004년 경에 만든 32Bit OS의 GUI 시스템 화면입니다. 내용물을 비교하자면, 지금 것과 비교하면 완전 최악이지만 GUI 시스템은 그리 크게 바뀌지 않은 것 같습니다. 그때도 상당히 고민했었는데… 지금 생각하니 그 당시는 너무 몰랐기 때문에 복잡하게 구현할 수 밖에 없었던 것 같습니다. 지금 코드는 훨씬 간단한데 말이지요. ㅎㅎ

 

마치 배경처럼 나와 있는 저 까마귀 그림은 제가 손수 그림판으로 그린 거라는… 지금 생각하니 저것도 웃기는 군요. 왜 저걸 그리고 있었을까나… ㅎㅎ 이궁…

에혀~ 밤이 깊었으니 자야겠습니다. 오늘은 좀 일찍 자는군요. ㅎㅎ 내일은 좀 더 일찍자야겠습니다. ;)

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

 지금까지 진행된 것은 멀티 태스킹 + 파일 시스템 + 동적 메모리 관리 + 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 영역 즉 클러스터 맵이 있는 영역에서 이상하게 캐시 히트가 낮게 나오는 문제를 뒤져봤는데... 역시나 문제가 있더군요. ㅎㅎ

 클러스터를 할당하는 코드가 클러스터 맵의 첫번째부터 마지막까지 검색하며 빈 클러스터를 찾게 되어있는데, 이런 경우 하드에 용량이 어느정도 차게되면 앞부분은 이미 대부분의 클러스터가 할당되어있음에도 불구하고 우직하게(?) 검색합니다. 따라서 클러스터 맵 영역의 캐시 또한 순차적으로 플러시되면서 거의 재사용되지 못하고 버려지게 되더군요.

 위와 같은 문제가 있어서 마지막으로 할당한 클러스터가 있는 클러스터 맵 인덱스를 저장하고, 클러스터 할당 요청이 올 때마다 가장 마지막으로 클러스터를 할당해준 클러스터 맵부터 검색을 시작하도록 수정했습니다. 이렇게 하니 거의 대부분 마지막으로 할당한 클러스터 맵에서 할당되서 거의 90%에 해당하는 캐시 히트가 나오더군요. 클러스터 맵을 쓰는 경우는 클러스터 할당/해제의 특성상 클러스터를 할당하려면 해당 맵을 읽어서 검색한 후, 할당했다고 마크를 해야하기 때문에 쓰는 경우는 100% 가 나왔습니다. 실로 엄청난 결과~!!! 이걸 실제 HDD에 적용할 경우 10번당 1번 하드를 읽는 것과 마찬가지기 때문에 시간을 엄청나게 절약할 수 있을 것 같습니다. >ㅁ<)-b

 하지만 이 기쁨도 잠시... 클러스터 영역을 캐시하는 기능도 추가했는데, 캐시 히트가... 20% 정도... ㅠㅠ 캐시 블럭의 개수를 128개 정도로 설정한 상태인데, 이를 더 늘리면 히트는 올라가겠지만 메모리 소모가 늘어나는 문제가 있기에 적당히 타협을 해야할 것 같습니다. 테스트 환경에서 캐시 블럭의 수를 2048개까지 늘리니까 40%까지는 히트가 올라가던데, 메모리 소모에 비해서 히트의 상승폭이 좀 낮아서 일단 다시 낮춰 놨습니다. 테스트는 가상으로 파일 3개를 만들고 랜덤한 파일 오프셋에서 랜덤한 사이즈를 읽고 쓰도록 하는 방법으로 하고 있는데, 아무래도 랜덤하게 읽고 쓰다보니 같은 클러스터가 다시 쓰이는 경우가 적은 것도 하나의 이유인 듯 합니다. 좀 더 고민해보고 캐시 블럭의 개수를 결정해야겠습니다. >ㅁ<)-b

 뭐든 구현하고 테스트할 때가 제일 재미있는 것 같습니다. 특히나 오늘처럼 예상하지 못한 결과가 나왔을 때는 더 즐겁습니다. 하핫~!!!
 헛.. 글고보니 내일은 고향에 가야되는데... 또 이렇게 시간이... ㅠㅠ 그만 자야겠습니다
 다들 좋은 밤 되세요. >ㅁ<)/~~


 주말 동안 쉬엄 쉬엄 파일 시스템을 설계했습니다. FAT 파일 시스템처럼 클러스터의 링크 형태로 말이지요. ^^ 최대한 간단하게 구현하려고 디렉토리 구조는 더욱 더 단순화시켰습니다. 그리고 코딩에 들어갔는데, 구현 초기에는 쉽게 쉽게 끝나는가 싶더니... 결국 또 복잡해지더군요.

 일단 멀티 태스크나 멀티 코어 환경에서 동기화 문제는 고려하지 않고, 단순히 파일 및 디렉토리 관련 API 만 만드는데, 꼬박 이틀이 걸렸습니다. 사실 API는 간단하게 만들고, 응용 프로그램이 잘 알아서 쓰도록하면 정말 간단한 구조를 유지할 수 있는데... 욕심이 생기다보니 이것 저것 많이 만들었습니다. 끄응.... ㅡ_ㅡa...

 덕분에 쓰기는 편해졌습니다만... 설명할게 많아져서 고민입니다. 현재 opendir, readdir, rewinddir, closedir, openfile, readfile, writefile, closefile, rewindfile, createfile, deletefile, createdirectory, deletedirectory까지 만들어져 있는데, 소스가 장난이 아니네요. 클러스터를 걸치는 녀석들 읽는거 처리하랴, Path 관련 처리하랴... 어휴... ㅠㅠ 하는 김에 rewindfile은 좀 더 고민해서 lseek로 만들어야겠습니다. 원래 lseek는 고려하지 않았지만... 만들다 보니 lseek 빼고는 다 만들었군요. ㅡ_ㅡa...

 만들긴 했는데... 과연 이 API가 얼마나 사용될지.... 삽질한건 아닌가 걱정이됩니다. ㅠㅠ
 억... 또 벌써 시간이 이렇게 됬군요.

 다들 좋은 밤 되시길.... ^^)-b

 ps) 아흑... 파일 동기화 문제는 또 어떻게 해결하지... ㅠㅠ


 아이쿠... 원래 계획은 좀 더 진도를 나가는 거였는데... 그 동안 무리를 좀 했더니 저녁에 잠깐 졸았습니다. 한 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) 헛... 이런 잠결에 만들다보니 화면에 있는 이미지 뷰어에 스펠링이 틀렸군요. 이런 ㅠㅠ

 헉헉... 아이구 머리야... 예전에 만든 소스를 긁어다 붙이는 것도 힘들군요. ㅎㅎ 금방 끝날줄 알았는데... 벌써 시간이 이렇게... 일단 아래는 실행한 화면입니다. 아직 프로토타입의 형태라서 버그도 좀 있고, 상태도 별로 안좋습니다. ㅎㅎ


 자세한 내용은 내일 올리겠습니다. 좀 늦어서... ㅠㅠ)-b
 그럼 다들 좋은 밤 되세요 >ㅁ<)-b



 간단히 시작한 일인데... 버그가 나오는 바람에 연짱 7시간 정도 디버깅한 것 같습니다. ^^;;; 멀티 코어라는걸 자꾸 까먹고 작업을 하다보니 이상한 고정관념에 사로잡혀서 제대로 코딩을 안했더군요. ㅠㅠ)-b 크윽... 오늘은 꼭 기억할껍니다. ㅠㅠ 이렇게 허접할수가...

 멀티 코어임에도 불구하고 CPU가 초기화되는 순서가 0번부터 순차적일꺼라는 말도 안되는 생각을 계속 하고 있었습니다. 그래서 코딩도 순차적으로 CPU가 초기화 되니 스택도 순차적으로 할당해 주도록 했더군요. 허나 실상은... 초기화 되는 순서를 아무도 모른다는... ㅠㅠ 그래서 CPU의 ID를 직접보도록 수정했습니다. 끄응... ㅡ_ㅡa...

 그리고 막판에 짬을 좀 내서 CPU Monitoring Application을 추가했습니다. 원래 이게 목적이었는데, 장난삼아 Dual Core에서 Quad Core로 QEMU 옵션을 변경했다가 버그를 발견하고 디버깅만 주구장창했다는... 내일 출근은 또 어찌할지... 머리도 띵하고... 흑흑....

 아래는 급히 찍은 스크린샷입니다. Quad Core로 만들어 놓고 실행시킨 화면인데, 원체 허접하게 CPU Load를 계산하는지라... 별로 믿음직스럽지 못하군요. ㅎㅎ 그래도 된다는데 의의를... ^^;;; 시험삼에 Hexa Core(16개)까지 QEMU에서 테스트해봤는데, PC도 버벅거리고 QEMU에서 속도가 제대로 안나오더군요. 그나마 Quad Core까지는 쓸만한 것 같습니다.
사용자 삽입 이미지

 어휴... 테스트를 제대로 안해보고 거사를 시작했다면 어찌됬을까 아찔합니다. ㅠㅠ 역시 여유를 갖고 검토하는 시간을 갖길 잘한 듯 합니다. 에혀~

 이제 자야겠군요. 내일 하루종일 좀비모드로 지낼 것 같다는... ㅠㅠ
 다들 좋은 밤 되세요 ;)


 다들 즐거운 추석 연휴를 보내시고 계신가요? ㅎㅎ 저는 할머니댁에 당일치기로 갔다오는 바람에 시간이 많이 남아서 오늘도 어김없이 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



 
 어제 급히 Application Level, 즉 User Level을 추가했다가 낭패를 크게 봤습니다. ㅡ_ㅡa...  첫번째는 아무 생각없이 Supervisor Mode로 맵핑되어있는 Paging 때문에... 두번째는 요상하게 설정된 User Level Descriptor 때문에... 세번째는 Segment Selector에서 잘못된 RPL Field 때문에... 네번째는 RFLAGS에 있는 IOPL 때문에... 다섯번째는 Interrupt 발생 시, User Level에서 Kernel Level로 변경되어 자동으로 발생하는 Stack Switching 때문이었습니다. 헥헥... 나열하니 이거 끝이 없군요. ;)

 원래의 목적은 Application Level에서 커널 함수를 사용할 때 Interrupt를 사용해서 Kernel 레벨로 바꾸고, Interrupt를 활성화 한 상태에서 커널 코드를 실행하는 것이었습니다. 이렇게 하면 인터럽트 불가로 동작하는 시간이 줄어들기 때문에 인터럽트에 좀 더 기민하게 반응할 수 있습니다. 만약 윈도우 전체를 다시 그리는 커널 코드를 실행한다고 가정하면 그 시간이 얼마나 걸릴지... 그리고 그동안 인터럽트 처리가 안되면 어떻게 될지는 금방 상상이 되실겁니다. ^^;;;;;

 그런데 이게 Stack Switching이 발생하다보니, Kernel Level Stack을 Application들 끼리 공유하게 되더군요. 32bit 같은 경우는 Task 별로 TSS 영역이 존재해서 별도의 Kernel Stack을 할당해 줄 수 있었지만, 64Bit에서는 TSS가 Task에 종속적으로 존재하는 것이 아닙니다. 거의 Global하게 공통적으로 사용한다고 해도 될만큼 말입니다. ㅠㅠ

 하지만 커널 코드 수행 시, 인터럽트를 활성화하려면 태스크 별로 커널 스택을 별도로 가져야 하는데... 어떻게 할까 고민하다가 결국 Interrupt Service Routine에서 System Call용은 Kernel Stack에서 Application Stack으로 돌아가도록 했습니다. Stack Switching을 한번 더 한다는 이야기지요. 이렇게 하면 System Call 호출로 인해 Kernel Mode에 진입해 있지만 Stack은 Application의 Stack을 사용하기 때문에 커널 함수를 수행하는 도중 Task Switching이 발생해서 다른 Application이 Kernel로 진입해도 문제 없습니다.

 일단 대충 코드를 구현했는데... 오늘은 일찍 자는 날이라서 내일 테스트 해야겠군요. 별것 아닌 것 같은데... 해보니 별거(?)였다는... ㅠㅠ

 아직 내공이 많이 부족한가 봅니다. 크윽... 저의 애마(?) 마제스터치 키보드와 함께 계속 달려야겠군요.
 다들 그럼 좋은 밤 되세요. ;)


 드디어 응용프로그램을 외부에서 전송하여 실행하는데 성공했습니다. 외부 즉 윈도우와 가상 머신은 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

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


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

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


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

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

 어제 오늘 직선을 쉽게, 그리고 제대로 그려볼려고 머리를 굴리고 있습니다. 그런데 생각보다 깔끔하게 나오지 않네요. ^^;;;; 구불구불해지거나 아니면 아예 이상해지거나... ㅠㅠ

 원래는 Bresenham 알고리즘을 사용했었는데, 좀 복잡해보여서 더 간단하게 그릴 수 있는 방법을 모색했습니다만.... ㅡ_ㅡa... 역시나 실패... 괜히 그런 알고리즘이 나온게 아니군요 ㅎㅎ

 아아... 그냥 GG 치고 Bresenham으로 가야겠습니다. ㅠㅠ 우측 상단에 X 버튼 그릴려고 별짓을 다 했군요. ㅠㅠ)-b
사용자 삽입 이미지

 직선 만세 ㅠㅠ)-b


ps) 이게 무슨 삽질인지... 다음 부터는 그냥 있는 거 써야겠습니다. ㅠㅠ
 어제 오늘 열심히 삽질해서 GUI라고 부를 수 있는 기능을 넣었습니다. 아래는 데모 화면입니다. ㅎㅎ 고전인 Hello World를 한번 넣어봤습니다. @0@)-b
사용자 삽입 이미지
 
 일단 만들긴 만들었는데... 이게 알고리즘이 후지다보니 굉장히 느리군요. ㅠㅠ 특히 큰 윈도우가 겹쳐져서 이동하는 경우, Draw를 상당히 많이 해야되서 거의 죽음입니다. ㅠㅠ 이거 무슨 수를 내던지 해야겠군요. 나름대로 적은 부분만 그릴려고 노력했는데... 아직은 역.부.족. ㅎㅎ

 어휴... 벌써 4시... ㅠㅠ 비빔면이나 하나 먹고 자야겠습니다. 내일은 꼭 어떻게든 속도를... ㅠㅠ)-b


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

 메모리를 적게 쓰려다 속도를 포기하는 상황까지 오게되자, 결국 개별 윈도우가 임시 버퍼를 가지는 방식으로 확!! 기울었습니다. ㅡ_ㅡ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

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

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



 고민 끝에 Ultra DMA쪽은 다음에 하는 걸로 미루고, ELF64의 Relocation 처리 부분을 하고 있습니다. PCI 부분을 다루자니 배보다 배꼽이 더 커지는 것 같고, 또한 굳이 DMA를 사용하지 않아도 HDD를 읽는데 문제가 없기때문에 작업량을 늘릴 필요가 있겠나 하는 생각이 들었습니다. ㅠㅠ 그래서 결국 다음에 시간나면 천천히 하는 걸로 결정했습니다.

 ELF64 File Format Spec을 보면서 느낀건데, PE File Format과 굉장히 비슷하군요. 차이점이라면 Section 별로 Relocation 정보를 가진 Section이 딸려오는 것이랄까요... r_link 및 r_info Field를 이용해서 Relocation 및 Symbol 정보가 포함된 Section으로 찾아갈 수 있습니다.

 아래는 간단히 VC로 만들어본 ELF64 Analyzer의 화면입니다. 각 Section 정보를 추출해서 Symbal 및 Relocation 정보를 나열하고 있습니다.
사용자 삽입 이미지

 이제 실제로 Relocation해서 메모리에 올리는 일만 남았군요. ;) 점점 삽질하는 속도가 빨라지고 있습니다. ㅠㅠ 좋은 건지 나쁜 건지... 일단 ELF64에 대한 내용은 천천히 정리해서 포스팅하겠습니다. ;)

 요거 끝나고 나면 GUI를 살짝 만들어보고 바로 작업(?)에 들어가야겠습니다. ㅎㅎ 아웅~ 잘되야할텐데... 걱정입니다. ㅎㅎ
 그럼 다들 좋은 밤 되세요 ^^)/~



 며칠째 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만 보면 어느 정도 끝날 것 같습니다. ;) 오늘 저녁에 뚝딱 해치워야겠군요.
 그럼 다들 좋은 주말 보내시길~ ^^)/~


 삽질을 끊임없이 한 결과(??) 64bit + Dual Core + Symmetric I/O System 까지 진행했습니다. 일단 다른 Core도 깨워서 64bit Mode로 전환시켜놨고, Interrupt 처리는 IO APIC와 APIC를 손봐서 두 Core에 Broadcasting 하도록 설정했습니다.

 Interrupt가 두 Core에 모두 전달되니, 서로 Interrupt를 처리하겠다고 경쟁하게 되더군요.  키보드 버퍼에 이상한 값이 들어가고 버퍼를 잘못 건드려 엉망이 됬습니다. 그래서 Spin Lock으로 먼저 Interrupt Handler에 접근한 Core가 처리하고 다른 Core는 그냥 End Of Interrupt만 송신하도록 했더니 나름대로 잘 동작합니다. >ㅁ<)/~ 이렇게 하는게 정석인지는 모르겠습니다만... 별 문제 없으니 그냥 패스.. ^^;;; 나중에 시간나면 Linux쪽에서 처리하는 방식을 한번 봐야겠군요(혹시 Linux의 Symmetric I/O 처리에 대해서 아시는 분 덧글 부탁드립니다 ㅠㅠ)-b ).

 아래는 Qemu에서 동작시킨 화면입니다. "showinterruptcount" 명령으로 각 Core가 Keyboard Interrupt를 얼마나 처리했는가를 표시했는데, 비슷하게 나오는군요. 의도하지 않은 Load Balancing이... ^^;;; 아직은 Cache 관련 부분이 Disable 되어 동작합니다.
사용자 삽입 이미지

 여기까지 해놓고 Cache를 Enable 하려니 IO APIC 및 APIC가 Memory Mapped I/O 방식으로 되어있어서 이 영역을 Cache가 불가능하게 설정해야 하더군요. 그래서 INTEL 문서를 뒤져보니 MTRR(Memory Type Range Register)를 사용해야한다고 나와있었습니다. ㅡ_ㅡa... 이것만 할게 아니라 CR0와 Page Table쪽도 다 같이 변경해줘야하고, 다른 쪽 Core 또한 같은 MTRR 설정값을 공유해야하는 문제가... 그래서 잠시 보류했습니다. ^^;;;;

 이거 생각 좀 해보고 넣어야겠군요. Cache를 활성화한다고 가상머신에서 돌아가는 OS가 크게 빨라질까 하는 생각도 들고... 차라리 Cache를 다 날려버리고 간단하게 구현하는게 더 나을지도 모른다는 생각이 계속 머리에서 맴돌아서... ㅠㅠ...

 자료가 별로 없어서 무한 테스트로 자료를 만드는데... 완전 죽음입니다. ㅠㅠ 아흑... 진도도 빨리 안나가고... 그래도 많이 왔네요. ㅠㅠ)-b 조금만 더 파보면 본격적인 작업(??)을 진행할 수 있을 것 같습니다. ;)

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



 

+ Recent posts