Geek OS 0.1.0 소스 분석 - Makefile (1)

charsyam의 이미지

처음에 GeekOS 0.2.0 으로 소스를 분석하려다가 보니, 교육용으로 일부러 기능을 빼버리고 추가한 부분이 있어서 실제로 bochs 등에서 돌려보려면 GeekOS 0.1.0이 낫다고 생각이 들어서 GeekOS 0.1.0으로 바꿉니다. 능력이 부족해서 죄송합니다.

geekos 0.1.0 소스 분석(1) - Makefile

작성자 : 강대명
작성일 : 2003-06-30
homepage : http://ns.mykernel.net

리눅스나, 그 외의 소스를 볼 때, 간과하기 쉬운 부분이 바로 Makefile 입니다.
보통 Makefile 을 모르면, 부트로더에서 사용하는 몇몇, 파라매터 들이나, 또는
왜 이것들이 합쳐져서 하나의 커널 이미지가 되는지 이해할 수 없을 경우가 많습니다.
( 즉, Makefile 에 대해서 알아야 된다 이겁니다. ^^ )

geekos 자체는 Makefile 이 아주 간단하게 되어 있더군요. 그래서 간단하게 분석을 해봤습
니다.
틀린 부분을 찾으시면 바로 바로 알려주시길 바랍니다. ^^

# Unix/Windows makefile for GeekOS
# Copyright (c) 2001, David H. Hovemeyer <daveho at cs.umd.edu>
# $Revision: 1.44 $

# This is free software. You are permitted to use,
# redistribute, and modify it as specified in the file "COPYING".

# This makefile works (well, is intended to work) on both
# Unix (including Linux) and Windows platforms. On Windows,
# you need a recent version of the cygwin toolkit, available
# at
# http://sources.redhat.com/cygwin/

# On any platform, you need gcc/binutils with an i386 target
# (http://gcc.gnu.org/), Nasm (http://www.web-sites.co.uk/nasm/),
# and perl (http://www.perl.com/).

# GNU make is required for this makefile.

# ----------------------------------------------------------------------
# Configuration stuff
# ----------------------------------------------------------------------

# Try to figure out if we're compiling on Unix or Windows.
# You may want to override this. OS should be set to
# "Windows_NT" for *any* version of Windows.

OS 타입에 따라서 몇몇 변수의 설정을 다르게 하는 부분들입니다. 이 부분은 그렇게
중요한것이 없으므로 그냥 넘어갑니다. 자세히 살펴보면, Windows 와 UNIX 부분이
조금씩 틀립니다.

ifneq ($(OS),Windows_NT)
OS := Unix
endif

# Uncomment this if you're using the i386-elf cross compiler and
# binutils.
#CC_PREFIX := i386-elf-

# In theory, you should not need to modify anything beyond this point...

# ----------------------------------------------------------------------
# Tools and definitions
# ----------------------------------------------------------------------

# The C compiler used to compile the kernel.
CC := $(CC_PREFIX)gcc

# Compiler flags.
ifeq ($(OS),Windows_NT)
EXTRA_CFLAGS := -DNEED_UNDERSCORE -DGNU_WIN32
endif
CFLAGS := -O -Wall -Werror -DGEEKOS $(EXTRA_CFLAGS)

# GNU linker and GNU objcopy. These are provided with the
# cygwin tools.
LD := $(CC_PREFIX)ld
OBJCOPY := $(CC_PREFIX)objcopy

# Objcopy flags.
# On Unix/ELF we get rid of some unnecessary sections.
ifeq ($(OS),Unix)
-R 옵션을 찾아보지는 않았지만, 아마도 elf 타입에서 특정 섹션들을 제거하는 옵션일겁니
다.
즉 dynamic, note, comment 부분은 빼라 이말입니다.
OBJCOPY_FLAGS := -R .dynamic -R .note -R .comment
endif

# Nasm. I'm using version 0.98
ifeq ($(OS),Windows_NT)
NASM := nasmw
NASMFLAGS := -f win32 -DNEED_UNDERSCORE
else
NASM := nasm
NASMFLAGS := -f elf
endif

각종 컴파일할 소스들이 있습니다. 주의할 것은 이 부분들은 부트로더를 제외한 실제 커널
이미지( 보호모드로 들어와서 main.c 의 Main 으로 점프하는 부분부터 ) 부분의 소스들입니
다.
부트로더 부분은 따로 컴파일됩니다.
# Kernel source and object files.
C_SRCS := screen.c idt.c int.c irq.c io.c keyboard.c mem.c string.c \
gdt.c kthread.c thrqueue.c timer.c segment.c tss.c bget.c malloc.c \
user.c trap.c syscall.c synch.c main.c
ASM_SRCS := lowlevel.asm
OBJS := $(C_SRCS:.c=.o) $(ASM_SRCS:.asm=.o)

# Perl (needs to be version 5 or later).
PERL = perl

# Utility scripts
pad 부분은 파일을 특정 크기 단위로 만들어주는 것입니다. 보통 x86의 경우 섹터가
512 byte 크기이므로, 밑에 보면 512 단위로 padding 을 하는 부분이 나옵니다.

PAD := $(PERL) pad

NUMSECS 는 파일이 구성하는 섹터의 크기를 알려줍니다. 이 부분을 동적으로 실행하는 이
유는
커널 이미지의 크기를 항상 알고 있을 수 없기 때문입니다. 즉, 커널 이미지가 먼저 생성되

그 이미지 크기를 알아내서 부트 로더 소스에 추가해서 그 크기만큼 부팅시 이미지를 읽어
드리게
됩니다.

NUMSECS := $(PERL) numsecs

ZEROFILE은 분석하지 않았지만, 아마도 NULL 값이 쭉 들어가는 데이터를 생성할 때 쓸 듯
합니다.
ZEROFILE := $(PERL) zerofile
CAT := $(PERL) pcat
RM := rm -f

# Kernel entry point.
ifeq ($(OS),Windows_NT)
ENTRY := _Main
else
ENTRY = Main
endif

# ----------------------------------------------------------------------
# Compilation rules
# ----------------------------------------------------------------------

.SUFFIXES:
.SUFFIXES: .c .asm .o

.c.o:
$(CC) $(CFLAGS) -c $<

.asm.o:
$(NASM) $(NASMFLAGS) -o $*.o $<

# ----------------------------------------------------------------------
# Targets
# ----------------------------------------------------------------------

# Default target.
# Create floppy and hard drive image files needed to
# start bochs.
all : fd.img hd.img

# Create the boot floppy, consisting of the boot sector followed by
# the setup code and binary kernel image.

fd.img는 bootsect.bin setup.bin kernel.bin 이 있어야만 생성됩니다.
cat 으로 fd.img 이라는 이름으로 하나의 파일로 연결시키라는 뜻입니다. 여기서
$@는 앞의 fd.img 이 이름을 가리킵니다.

fd.img : bootsect.bin setup.bin kernel.bin
$(CAT) bootsect.bin setup.bin kernel.bin > $@

# Create a nice 10MB hard disk for bochs to use.
hd.img 를 만들어냅니다. 20808 * 512 를 하면 10MB 가 나오는것 같습니다.
hd.img :
$(ZEROFILE) $@ 20808

# Setup code (16 bit real mode), loaded by the bootsector.
# Its purpose is to set up the hardware sufficiently such that
# the kernel can start running. Note that the kernel storage map
# is a prerequisite, since the setup code needs to know the address
# of the kernel entry point.

이제 setup.bin 을 만듭니다. 이 때 storage.txt 에서 Main 이라는 Symbol의
주소를 찾아내서 그걸 ENTRY_POINT로 지정합니다. 이 부분이 필요한 이유는 실제
보호모드 설정을 하고 나서 커널 이미지의 시작부분을 찾기 위해서 입니다. 실제로
보호모드가 설정되는 것도 CR0의 PE bit가 설정되고 long 점프가 있어야만 보호모드로
변경이 될겁니다.

setup.bin : setup.asm defs.asm util.asm storage.txt
$(NASM) -DENTRY_POINT=`perl findaddr storage.txt Main` \
-f bin -o $@ setup.asm

512 바이트로 패딩을 합니다.
$(PAD) $@ 512

# Create a binary image of the kernel code and data.
# The file produced can be loaded into memory as-is and executed.
# The -S option stips out the symbol table.
kernel.bin 은 위에서 커널 이미지가 kernel.exe 로 만들어집니다. 그걸 pure binary 형태로
만들어 주는 겁니다. 역시 512 크기로 패딩합니다. 즉, 커널 이미지 부분은 그냥 일반 프로
그램이
컴파일 되는 것과 동일하다고 보시면 되겠습니다.

kernel.bin: kernel.exe
$(OBJCOPY) $(OBJCOPY_FLAGS) -S -O binary kernel.exe kernel.bin
$(PAD) $@ 512

# Link the kernel. Put the .text section (which is the first
# section in the executable) at address 0x10000 (64K).

kernel.exe 를 만듭니다. 위의 .c 파일들과 lowlevel.asm 을 컴파일 해서 나온 obj 파일들과
test 안의 유저 프로그램 파일 들을 모아서 ld 파일을 통해 링크해서 하나의 kernel.exe 라는
실행파일을 만듭니다. 이 때, 시작주소는 메모리의 0x00010000 위치를 시작으로 합니다.
이것은
나중에 relocation을 피하기 위해서입니다. 기본적으로 이 위치를 지정안해주면, 재배치가
능하게
특정 위치를 대상으로 메모리 주소들이 설정되기 때문에( 예를 들어, jmp 같은 경우) ebp
를 더해
줘야하는 걸로 알고있습니다.( 이 부분은 저도 기억이 잘 안나서 나중에 보충하도록 하죠 )
ld 의 -M 옵션은 print map 이라고 해서 함수들의 메모리에서의 위치 값들을 출력하게 됩니
다.
그 정보를 storage.txt 에 저장해서 위의 setup.bin을 만들 때, Main 의 주소를 찾아서 거기로
점프하는 겁니다.

kernel.exe storage.txt : $(OBJS) uprogs.o
$(LD) -M -o kernel.exe -Ttext 0x00010000 -e $(ENTRY) $(OBJS) uprogs.o \
> storage.txt

# Assemble the boot sector.
# Note that we need to build the setup code and kernel first,
# since their sizes are referenced.

bootsect.bin 을 만들 때는 이제 define 으로 setup.bin 과 kernel.bin 의 크기를 동적으로
넣어줍니다. 컴파일 될 때, 즉 각 파일의 크기가 들어가게 됩니다. bootsect.asm 에 보면
NUM_SETUP_SECTORS 이라는 정의되지 않은 값들이 있는데, 즉 Makefile 에서 추가시켜
주는
겁니다.

bootsect.bin : setup.bin kernel.bin bootsect.asm defs.asm util.asm
$(NASM) -DNUM_SETUP_SECTORS=`$(NUMSECS) setup.bin` \
-DNUM_KERN_SECTORS=`$(NUMSECS) kernel.bin` \
-f bin -o $@ bootsect.asm

# Rules for generating user programs which live in the "test" directory.

나머지 부분들은 그냥 유저 프로그램을 컴파일 하는 부분입니다. 대충 보시면 이해하실듯

uprogs.o : uprogs.c

uprogs.c : dummy
cd test && $(MAKE) OS="$(OS)"

dummy :

# Delete generated files.
clean :
$(RM) fd.img kernel.exe kernel.bin bootsect.bin setup.bin *.o \
uprogs.c storage.txt bochs.out
cd test && $(MAKE) clean

realclean : clean
$(RM) hd.img depend.mak

# Generate header file dependencies.
depend : uprogs.c
$(CC) $(CFLAGS) -M $(C_SRCS) uprogs.c > depend.mak

depend.mak :
echo dummy: > $@

include depend.mak

일단 1편은 Makefile 로 잡았습니다. 앞으로도 제가 이해하는 부분들은 이렇게 분석
형식으로 올려보도록 하겠습니다. 아마, 저도 지금 스터디 방향대로 분석해보도록
하겠습니다. 능력이 된다면, 그냥 기본 소스에 Paging(Swap), VFS, floppy, hdd,
serial 등등의 각종 기능을 추가해서 올려보도록 하겠습니다.(과연 능력이 될지는 ^^)
그럼 고운 하루되세요.

Forums: 
charsyam의 이미지

음, OS제작에 관심이 있는데, 그래서 시작한게 Geek OS 라는 교육용 OS의 소스 분석입니다. 과연 얼마나 열심히 할지는 모르겠지만, ^^ 최대한 조금씩 도움이 될만한 내용을 올려보도록 하겠습니다. T.T 틀리면 바로 지적 부탁드립니다. 고운 하루되세요.

=========================
CharSyam ^^ --- 고운 하루
=========================

girneter의 이미지

기대됩니다.

열심히 배우겠습니다. ^^

개념없는 초딩들은 좋은 말로 할때 DC나 웃대가서 놀아라. 응?

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.