Lacti's Archive

pintos 환경 구축

April 01, 2008

Pintos를 구동시키기 위해서는 먼저 가상 에뮬레이터가 필요하다. Open source 중에 대표적으로 Bochs와 QEMU가 있는데, 설치법이 과제 문서에 기술되어있는 Bochs를 선택하여 설치하였다.

  • Bochs는 Open Source 프로젝트로 Sourceforge에서 그 소스를 다운받아 컴파일하여 설치할 수 있다. 파일을 받기 위해서 Sourceforge에 lynx로 접속하여 bochs-2.3.tar.gz를 다운 받았다.
  • tar.gz 압축이므로 tar xvzf를 이용하여 압축을 풀었다.
~$ tar xvzf bochs-2.3.tar.gz

원격으로 터미널을 통해 진행할 예정이기 때문에 bochs가 terminal이 가능하고 gui가 없어도 동작할 수 있도록 컴파일해서 설치해야 했다. 따라서 configure 옵션에 --with-term--with-nogui를 주었다. 또 과제 문서에서 제시한 바와 같이 gdb debugging을 위해 --enable-gdb-stub을 옵션으로 주었다.

~/bochs-2.3$ ./configure --with-term --with-nogui --enable-gdb-stub

그 다음에 bochs를 make하고 설치하기 위해 make와 make install 명령을 수행했다. make install은 모든 사용자가 사용하는 전역 위치에 bochs를 설치하기 때문에 일반 사용자 권한으로는 설치가 안된다. 따라서 과제 문서가 제시한 대로 root 권한으로 설치를 수행하였다.

~/bochs-2.3$ make; sudo make install

bochs의 설치가 완료 되었다. 정상 동작을 확인하기 위해 bochs --help를 수행하였다.

~/bochs-2.3$ bochs --help
========================================================================
                        Bochs x86 Emulator 2.3
              Build from CVS snapshot on August 27, 2006
========================================================================
Usage: bochs [flags] [bochsrc options]

  -n               no configuration file
  -f configfile    specify configuration file
  -q               quick start (skip configuration interface)
  --help           display this help and exit

For information on Bochs configuration file arguments, see the
bochsrc section in the user documentation or the man page of bochsrc.
00000000000i[CTRL ] quit_sim called with exit code 0

다음으로 pintos를 실행하기 위해 pintos를 다운로드 받았다. pintos는 구글 검색을 통해 다운로드 주소가 https://www.stanford.edu/class/cs140/projects/pintos/pintos.tar.gz에 있음을 찾아내서 wget 명령으로 다운로드 받았다.

$ wget https://www.stanford.edu/class/cs140/projects/pintos/pintos.tar.gz

역시 tar.gz 압축이므로 tar xvzf로 압축을 해제하였다.

$ tar xvzf pintos.tar.gz

과제 문서에 제시된 대로 pintos/src/threads로 이동하여 make를 수행하였다.

$ cd pintos/src/threads
~/pintos/src/threads$ make

make 수행이 undefined references to '__stack_chk_fail' follow이라는 에러에 의해 중단되었다. 이를 해결하기 위해 구글을 검색하여 다음의 레퍼런스를 얻었다. 이 포럼에서 권고하는 대로 make 설정에서 CFLAGS의 값에 -fno-stack-protector 옵션을 추가해주기 위해 편집기 vi를 사용하여 Make.vars에 CFLAGS += -fno-stack-protector를 추가해 주었다.

~/pintos/src/threads$ vi Make.vars

기존에 컴파일한 것들을 제거하기 위해 make clean을 수행한 후 make를 수행하여 빌드를 마쳤다.

~/pintos/src/threads$ make clean
~/pintos/src/threads$ make

Pintos를 수행하기 전에 편의를 위해서 다음과 같은 alias를 작성하였다. 이 alias를 ~/.bashrc에 추가하여 bash이 열릴 때마다 alias가 자동으로 등록되도록 했다. 그리고 어디에서나 pintos가 실행될 수 있도록 pintos 실행 파일이 있는 곳을 PATH에 추가하였다.

~/pintos/src/threads$ vi ~/.bashrc

추가한 내용은 아래와 같다.

export PATH=$PATH:~/pintos/src/utils/

alias pinv='pintos -v -- run'
alias pint='pintos -t -- run'

alias pinvg='pintos --gdb -v -- run'
alias pintg='pintos --gdb -t -- run'

추가한 내용을 적용시키기 위해서 source를 수행했다. 수행한 후, PATH가 적용되었는지 확인하기 위해서 설정된 PATH를 출력하도록 했다. 다음과 같이 추가된 것을 확인할 수 있었다.

~/pintos/src/threads$ source ~/.bashrc
~/pintos/src/threads$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/lacti/pintos/src/utils

pintos를 수행하기 위해 threads의 build 디렉토리로 이동하였다. 미리 작성해둔 alias를 이용하여 간단하게 pintos threads를 구동하였다.

~/pintos/src/threads/build$ pinv alarm-multiple
Writing command line to /tmp/w6Pkbt7Upa.dsk...
warning: can't find squish-pty, so terminal input will fail
bochs –q

위의 alias에 정의되어 있듯이 pinv alarm-multiple을 수행했을 경우 실제 수행되는 명령어는 pintos –v –- run alarm-multiple이다.

결과는 제대로 나오지만 warning이 꺼림직했기 때문에 squish-pty를 빌드하기로 하였다. ~/pintos/src/utils로 이동하여 make를 수행하였다.

~/pintos/src/threads/build$ cd ../../utils/
~/pintos/src/utils$ make

squish-pty를 비롯한 몇 개의 파일들이 빌드되었고, 정상 작동함을 확인하기 위해 다시 pintos를 구동시켜보았다.

~/pintos/src/utils$ cd ../threads/build
~/pintos/src/threads/build$ pinv alarm-multiple
Writing command line to /tmp/UcIb0NhSWJ.dsk...
squish-pty bochs -q
========================================================================
                        Bochs x86 Emulator 2.3
              Build from CVS snapshot on August 27, 2006
========================================================================
00000000000i[     ] reading configuration from bochsrc.txt
00000000000i[     ] installing nogui module as the Bochs GUI
00000000000i[     ] using log file bochsout.txt
Kernel command line: run alarm-multiple
Pintos booting with 4,096 kB RAM...
375 pages available in kernel pool.
374 pages available in user pool.
Calibrating timer...  204,600 loops/s.
Boot complete.
Executing 'alarm-multiple':
(alarm-multiple) begin
(alarm-multiple) Creating 5 threads to sleep 7 times each.
(alarm-multiple) Thread 0 sleeps 10 ticks each time,
(alarm-multiple) thread 1 sleeps 20 ticks each time, and so on.
(alarm-multiple) If successful, product of iteration count and
(alarm-multiple) sleep duration will appear in nondescending order.
(alarm-multiple) thread 0: duration=10, iteration=1, product=10
(alarm-multiple) thread 0: duration=10, iteration=2, product=20
(alarm-multiple) thread 1: duration=20, iteration=1, product=20
(alarm-multiple) thread 0: duration=10, iteration=3, product=30
(alarm-multiple) thread 2: duration=30, iteration=1, product=30
(alarm-multiple) thread 0: duration=10, iteration=4, product=40
(alarm-multiple) thread 1: duration=20, iteration=2, product=40
(alarm-multiple) thread 3: duration=40, iteration=1, product=40
(alarm-multiple) thread 0: duration=10, iteration=5, product=50
(alarm-multiple) thread 4: duration=50, iteration=1, product=50
(alarm-multiple) thread 2: duration=30, iteration=2, product=60
(alarm-multiple) thread 0: duration=10, iteration=6, product=60
(alarm-multiple) thread 1: duration=20, iteration=3, product=60
(alarm-multiple) thread 0: duration=10, iteration=7, product=70
(alarm-multiple) thread 3: duration=40, iteration=2, product=80
(alarm-multiple) thread 1: duration=20, iteration=4, product=80
(alarm-multiple) thread 2: duration=30, iteration=3, product=90
(alarm-multiple) thread 4: duration=50, iteration=2, product=100
(alarm-multiple) thread 1: duration=20, iteration=5, product=100
(alarm-multiple) thread 1: duration=20, iteration=6, product=120
(alarm-multiple) thread 2: duration=30, iteration=4, product=120
(alarm-multiple) thread 3: duration=40, iteration=3, product=120
(alarm-multiple) thread 1: duration=20, iteration=7, product=140
(alarm-multiple) thread 4: duration=50, iteration=3, product=150
(alarm-multiple) thread 2: duration=30, iteration=5, product=150
(alarm-multiple) thread 3: duration=40, iteration=4, product=160
(alarm-multiple) thread 2: duration=30, iteration=6, product=180
(alarm-multiple) thread 4: duration=50, iteration=4, product=200
(alarm-multiple) thread 3: duration=40, iteration=5, product=200
(alarm-multiple) thread 2: duration=30, iteration=7, product=210
(alarm-multiple) thread 3: duration=40, iteration=6, product=240
(alarm-multiple) thread 4: duration=50, iteration=5, product=250
(alarm-multiple) thread 3: duration=40, iteration=7, product=280
(alarm-multiple) thread 4: duration=50, iteration=6, product=300
(alarm-multiple) thread 4: duration=50, iteration=7, product=350
(alarm-multiple) end
Execution of 'alarm-multiple' complete.

위와 같이 정상 작동함을 확인할 수 있었다. 종료를 위해 Ctrl + C를 누르면 다음과 같이 interrupt를 받으며 종료된다.

========================================================================
Bochs is exiting with the following message:
[     ] SIGNAL 2 caught
========================================================================

pintos –t 옵션을 사용하지 않고 pintos –v 옵션을 사용한 이유는 pintos –t 옵션을 사용하여 pintos를 구동시키게 되면 수행 후에 Ctrl + C로 interrupt를 걸어도 bochs가 수행을 종료하지 않고 메모리에 계속 남아있기 때문이다. 따라서 추가적으로 kill -9 등을 사용하여 종료해주어야 하므로 좀 더 편리한 pintos –v 옵션을 사용하였다. 물론 pintos –t 옵션을 사용하면 잠깐 지나가는 BIOS 화면을 볼 수 있다.

$ ps -ef |grep bochs
lacti    11939     1 99 02:19 pts/0    00:01:01 bochs -q
lacti    11941  3985  0 02:20 pts/0    00:00:00 grep bochs

다음 과정인 gdb를 수행하기 위해 gdb를 설치하였다.

~$ sudo apt-get install gdb

PuTTY를 하나 더 켜서 pintos를 gdb모드로 실행시켰다. 글자를 조금이라도 적게 치기 위해서 이미 위에서 alias를 정의해 놓았다. v 옵션으로 gdb를 수행하므로 pinvg이다. 따라서 과제 문서에서 제시한 대로 alarm-multiple를 수행하려면 pinvg alarm-multiple이라고 하면 되고, 실제 명령은 pintos –-gdb –v – run alarm-multiple이다.

~$ cd pintos/src/threads/build/
~/pintos/src/threads/build$ pinvg alarm-multiple

그러면 다음과 같이 bochs가 gdb의 접속을 기다리며 수행을 멈춘다.

~/pintos/src/threads/build$ pinvg alarm-multiple
Writing command line to /tmp/RArahIMk8f.dsk...
squish-pty bochs -q
========================================================================
                        Bochs x86 Emulator 2.3
              Build from CVS snapshot on August 27, 2006
========================================================================
00000000000i[     ] reading configuration from bochsrc.txt
00000000000i[     ] Enabled gdbstub
00000000000i[     ] installing nogui module as the Bochs GUI
00000000000i[     ] using log file bochsout.txt
Waiting for gdb connection on localhost:1234

다른 PuTTY에서 gdb를 켜서 원격 디버깅을 시작한다. 어차피 localhost이므로 remote localhost:1234로 연결하면 된다. 그러면 다음과 같이 접속이 이루어진다.

~$ gdb
GNU gdb 6.6-debian
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
(gdb) target remote localhost:1234
Remote debugging using localhost:1234
warning: unrecognized item "ENN" in "qSupported" response
0x0000fff0 in ?? ()
(gdb)

여기서 continue 명령인 c를 누르면 pintos가 계속 진행된다. Ctrl + C를 눌러서 수행을 중단할 수 있다. 그리고 kill 명령을 이용하여 debugging을 중단하고 pintos의 수행을 중단할 수 있다. gdb에서 작업을 끝내려면 quit 명령을 이용해서 나가면 된다.

다음과 같이 kill 명령으로 수행 중인 pintos를 종료할 수 있다.

(gdb) c
Continuing.

Program received signal 0, Signal 0.
0xc0101660 in ?? ()
(gdb) kill
Kill the program being debugged? (y or n) y
(gdb)

그러면 pintos에서는 다음과 같이 Debugger의 종료 요청에 의한 종료를 수행하게 된다.

Execution of 'alarm-multiple' complete.
========================================================================
Bochs is exiting with the following message:
[     ] Debugger asked us to quit

========================================================================
Loading script...