<깔끔하게(?) 정리된 MINT64 OS의 실행 화면>


한동안 정신 없이 바쁘다가 다시 코드를 볼 일이 생겨서 얼마 전부터 코드를 보고 있습니다. :) 코드를 새로 추가하는 것은 아니고 기존 코드를 정리한 것뿐이지만… 어쨌든 내부가 변하긴 했으니 기념 삼아 올려봅니다. ^^;;; 가만히 생각해보니, 그동안 MINT64 OS에 대해서 많이 올리긴 했지만 제대로 된 설명을 한번도 한적이 없는 것 같네요. 코드도 한번 정리한 김에 MINT64 OS에서 실행 가능한 애플리케이션과 커맨드도 같이 정리해둡니다.

MINT64 OS가 기본으로 내장하고 있는 애플리케이션은 5개로 왼쪽 위에 있는 “Application” 버튼으로 실행할 수 있습니다. 각 애플리케이션의 역할은 아래와 같습니다.


  • Base GUI Task : 모든 GUI 애플리케이션의 기본 뼈대 역할을 하는 태스크로 윈도우를 생성하고 윈도우에 관련된 이벤트를 처리하는 단순한 애플리케이션입니다.
  • Hello World GUI Task : 가장 기본적인 GUI 애플리케이션으로 윈도우 시스템이 전달하는 메시지를 화면에 출력하고 자신과 같은 Hello World GUI Task로 유저 이벤트를 전송하는 기능도 같이 가지고 있습니다.
  • System Monitor Task : OS의 상태를 표시하는 애플리케이션이며 프로세서의 상태와 메모리의 상태를 표시합니다.
  • Console Shell for GUI : GUI 모드에서 동작하는 콘솔 셸로 커맨드 라인 해석기(Command Line Interpreter) 입니다. 여기에 대해서는 잠시 후에 설명하겠습니다. ;)
  • Image Viewer Task : JPG 파일을 읽어서 화면에 출력해주는 애플리케이션입니다. 하드 디스크에 image1.jpg와 image2.jpg, 그리고 image3.jpg가 있으니 파일명에 이를 입력하면 이미지를 볼 수 있습니다.


  <MINT64 OS에 내장된 GUI 애플리케이션들>


GUI 애플리케이션도 좋지만 키보드로 커맨드를 입력하는 재미(?)도 무시할 수 없어서, 초반에 MINT64 OS를 개발할 때 쓰던 콘솔 커맨드를 그대로 GUI 애플리케이션으로 만들었습니다. 콘솔 셸에서 테스트할 수 있는 커맨드에는 여러 가지가 있지만, 그 중에서 특히 유용한 몇 가지를 추린다면 아래와 같습니다.


  • help : 콘솔 셸이 지원하는 커맨드 목록을 출력합니다.
  • dir : 하드 디스크에 들어있는 파일을 출력합니다.
  • hddinfo : 하드 디스크의 정보를 출력합니다.
  • filesysteminfo : 파일 시스템의 정보를 출력합니다.
  • exec <application nane> <argument> : 파일 시스템에 저장된 애플리케이션 파일을 실행합니다. 애플리케이션은 ELF 파일 형식을 사용하며, 하드 디스크에 helloworld.elf부터 onelinememo.elf까지 총 6개가 저장되어 있습니다. <Argument> 부분은 옵션으로 애플리케이션마다 필요로 하는 정보가 다르고, 이는 잠시 후에 설명하겠습니다. ;)


콘솔 셸 커맨드 중에서 exec는 아주 특별한 커맨드로 파일 시스템에 저장된 GUI 애플리케이션을 실행하는 역할을 합니다. 파일 시스템에 저장된 애플리케이션은 6가지가 있고 각 애플리케이션마다 필요한 Argument와 역할은 아래와 같습니다.


  • exec helloworld.elf : MINT64 OS에 내장된 helloworld 애플리케이션과 같습니다.
  • exec textviewer.elf asciiart.txt : 파일 시스템에 저장된 파일을 읽어서 화면에 출력해주는 애플리케이션으로, Argument로 넘어온 파일을 읽어서 표시합니다.
  • exec bubble.elf : 풍선을 쏘는 버블 슈터라는 게임입니다. ^^;;;
  • exec hexa.elf : 같은 색깔의 블럭을 없애는 헥사 게임입니다. ^^;;;
  • exec hangulviewer.elf main.c : 파일 시스템에 저장된 파일을 읽어서 화면에 출력해주는 애플리케이션으로, textviewer.elf와 다른 점은 한글을 지원한다는 것입니다.
  • exec onelinememo.elf : 한 줄 메모장으로 간단한 메모를 남길 수 있는 애플리케이션입니다.


  <exec 커맨드로 실행한 애플리케이션들>

 

기능은 얼마 없는데 쭉 나열하고 보니 많은 것처럼 보이는 군요(착시 효과가 엄청난 듯…). ㅠㅠ 실제로 어떤 모습인가 확인하고 싶은 분들은 아래에 있는 압축 파일을 다운로드한 뒤에 MINT64OS.bat 파일을 실행하면 됩니다. 가상 머신에서 동작하는지라 사용하는 PC의 성능에 따라 약간 편차가 있을 수 있는데… 듀얼 코어 정도면 실행하는데 큰 문제가 없을 겁니다. ^^;;;



아우~ 주말 내내 정신 없이 보냈더니 이제 좀 쉬어야겠네요. 그럼 다들 좋은 밤 되시길~ ;)

 

<이미지 뷰어와 콘솔 셸이 추가된 MINT64 OS>

 오늘 너무 황당한 일이 있어서 오랜 적막(?)을 깨고 한자 적어 올립니다(사실 다시 삽질 안 하려고 잊기 전에 올리는 것이지만... ㅡ_ㅡ;;;). 요즘 유저 레벨 응용 프로그램을 추가하려고 시스템 콜 부분을 구현하고 있는데, 인터럽트나 콜 게이트 방식 말고 다른 방식이 아닌 새로운 방식을 한번 도입해봤습니다. 이미 이 글의 제목에도 나와있지만 SYSCALL과 SYSRET 명령어를 사용하는 것이지요.;)


SYSCALL과 SYSRET 명령어는 INTEL과 AMD 양쪽에서 모두 사용할 수 있으며, IA-32e 모드에서 Ring 0와 Ring 3을 순식간에 오가는데 아주 유용하....다고 적혀있습니다. ㅡ_ㅡa... 실제로 얼마나 빠른지는 잘 모르겠지만 콜 게이트나 인터럽트처럼 스택에 데이터를 저장하고 특권 레벨을 체크하는 부분이 없으므로, 이전 것들(?)보다는 빠를 듯 합니다. ^^;;;;


뭐, 일단 SYSCALL과 SYSRET 명령어를 사용하려면 어떻게 환경을 설정해야 하는지는 INTEL 문서 Volume 3에 4.8.8 부분에 잘 나와있으니 생략하고... 실제로 SYSCALL과 SYSRET를 NASM으로 사용할 때 주의할 점만 한 줄로 정리해보면 다음과 같습니다.


IA-32e 모드의 64bit 서브 모드를 사용할 경우
SYSRET 명령어 앞에 REX.W 비트를 반드시 명시적으로 켜줘야 한다.


위의 사실을 찾는 데만 무려 3시간이 걸렸습니다. ㅠㅠ INTEL 문서를 보면 SYSRET의 경우 IA-32e 모드의 서브 모드 중에서 호환 모드(Compatibility Mode)와 64 비트 모드 중에서 선택해서 돌아갈 수 있으며, 그 핵심은 REX.W 비트라고 적혀있습니다. MINT64 OS는 64비트 서브 모드를 사용하니 REX.W 비트를 켜줘야 하는데, REX.W 비트가 켜지지 않아서 시스템 콜을 호출하고 돌아올 때 문제가 계속 생겼습니다.


코드를 생성할 때 64bit로 생성했기 때문에 NASM이 알아서 붙여 줄거라 생각했는데... 확인 결과 아무것도 없이 그냥 SYSRET 커맨드만 덩그러니 있었습니다. 그래서 시스템 콜을 호출한 뒤에 돌아오면... 잘못된 명령어라는 예외가 발생하더군요. ㅠㅠ 그래서 REX.W 비트를 키려고 봤더니... 


얼래... NASM에는 SYSRET 명령어 앞에 REX.W 비트를 명시적으로 붙이는 접두사나 키워드가 없었습니다~!!! (여운산님이 o64 키워드가 있다는 사실을 제보해주셨습니다. o64 키워드를 붙이니까 잘 되더군요 >ㅁ<)-b 완전 감사합니다). ㅠㅠ 오퍼랜드가 있는 다른 명령어들은 뒤에 오는 오퍼랜드의 크기에 따라 REX.W 비트를 켜주는 모양이던데, SYSRET는 오퍼랜드가 없으니 그냥 넘어간 모양입니다. ㅠㅠ 그래서 아래처럼 설정해줬습니다.


DB 0x48  <== REX Prefix로 W 비트가 1로 설정된 상태입니다. ^^;;;; (제가 해결한 무식한 방법입니다)
SYSRET

o64  <== REX.W 비트를 1로 설정하는 키워드 입니다. ;) (여운산님이 제보해주신 방법입니다, 아주 깔끔하네요 ;) )
SYSRET


이걸 해놓고 나니까 겨우 정상적으로 동작하네요. 이제야 겨우 유저 레벨 코드를 작업할 수 있게 되었습니다. ㅠㅠ)-b 안 그래도 할 일이 산더미 같은데... 이런 일로 시간 낭비(?)를 하고 나니 머리가 어찔하네요. ㅠㅠ 에휴... 이제 다시 작업하러 가야겠습니다.


ps) 위의 화면은 MINT64 OS에 이미지 뷰어와 콘솔 셸이 추가된 화면입니다. ㅎㅎ 조만간 또 테스트할 수 있는 바이너리... 보다는 동영상으로 한번 올리겠습니다. ;)

요즘 회사일 때문에 눈코 뜰새 없이 바쁜지라 거의 블로그를 버려뒀습니다. ㅠㅠ 회사에서 머리를 풀 회전시키고 집에 와서 잠시 쉬었다가 다시 작업하고 이런 날들을 거의 추석 근처부터 반복했더니만... 머리가 타는 듯(?) 하네요. ㅠㅠ 그래도 작업은 꾸준히 해야 하는지라 틈틈이 기능을 추가해서 화면 그리기 알고리즘 업그레이드 + 작업 표시줄 + 시스템 모니터까지 진행되었습니다. 아래는 진행된 것을 캡쳐한 화면입니다.

<작업 표시줄과 시스템 모니터가 추가된 화면>


이제 조금만 더 만들어서 콘솔 쉘까지 추가하면 그럴듯해지겠군요. ㅎㅎ 이번에는 동영상보다 직접 실행할 수 있는 QEMU의 이미지를 올렸습니다(절대 동영상을 찍기 싫어서가 아닙니다. ㅠㅠ). 어떻게 돌아가는지 궁금하신 분들은 한번 다운 받아서 실행해보시면 얼마나 허접한지(?) 볼 수 있을 겁니다. ㅎㅎ 파일을 다운받아서 압축을 푼 후 디렉터리 안에 있는 MINT64OS.bat를 실행하시면 됩니다.



아우... 새벽형 인간으로 거듭난지 꽤 되었지만 아침에 일찍 일어나는 건 여전히 힘드네요 ㅎㅎ 이제 그만 또 작업하러 가봐야겠습니다. ;) 다음 글이 또 언제 올라올지 모르겠지만, 틈나는 대로 진행상황을 올리겠습니다. 그럼 다들 좋은 하루 되세요 ;)

근 10일에 걸친 대장정이 끝났습니다. ㅠㅠ)-b 중간에 코드를 한번 잘못짜서 디버깅을 다시 하는 사태도 발생했지만, 결국 끝났습니다. ㅠㅠ 잠결에 코딩을 했더니만 알 수 없는 코드들이 중간 중간에 잔뜩 들어가 있더군요. ㅠㅠ 어흑 ㅠㅠ

코어 16개를 모두 활성화한 뒤에 대칭 I/O 모드(Symmetric I/O Mode)로 전환하여 인터럽트 처리 횟수가 전체적으로 10 이상 차이가 나면 인터럽트를 분산하도록 했습니다. 뭐, 매번 돌리면서 인터럽트를 분산시킬 수도 있지만 약간 오바인 것 같아서... ^^;;;;

아래는 인증 샷입니다. :) 코어 16개를 활성화하기 전에 인터럽트 처리 횟수를 출력하고, 16개를 활성화한 후 다시 출력했습니다. 그리고 마지막으로 인터럽트 부하 분산 기능을 활성화해서 키보드를 난타한 다음 최종적으로 처리된 횟수를 출력하도록 했습니다.

 


에혀~ 이제 스케줄러를 코어마다 추가하고 태스크 부하 분산(Task Load Balancing)만 처리하면 끝이군요. ;) 대망의 GUI로 넘어갈 수 있을 것 같습니다. ㅎㅎ 정리하면서 하느라 여기까지 오는데 꽤나 걸렸는데... 이제 좀 속도가 다시 붙을 것 같군요. ;) GUI는 지금까지 했던 것 보다는 알고리즘이 간단하니까 말이죠 ;)

에궁~ 오늘은 일찍 잘려고 했는데... 결국 또 이렇게 되는군요. ㅠㅠ 언능 누워야 겠습니다. ㅎㅎ 다들 좋은 밤 되세요 ;)


ps) 인터럽트 부하 분산 기능을 추가하긴 했는데... 시리얼 포트를 폴링 방식으로 사용하다보니 그다지 인터럽트 부하가 발생하지 않더군요. ㅡ_ㅡa... 사실 크게 이득이 없는 것 같습니다. 나중에 기가바이트 이더넷이나 추가하면 효과를 좀 볼지... ㅎㅎ :)

+ Recent posts