https://seung2344.tistory.com/112
[์ด์์ฒด์ ]๐ฆ๊ณต๋ฃก์ฑ ๐ฆ2์ฅ - ์ด์์ฒด์ ๊ตฌ์กฐ(2)
https://seung2344.tistory.com/110 [๐ฆOS๐ฆ]2์ฅ. ์ด์์ฒด์ ๊ตฌ์กฐ(1)์ด ์ฅ์ ํ์ต ๋ชฉํ์ด์์ฒด์ ์์ ์ ๊ณตํ๋ ์๋น์ค ํ์ต์ฌ์ฉ์ ์ธํฐํ์ด์ค ์ข ๋ฅ์ ๋ํด ํ์ต์๋น์ค๋ฅผ ์ ๊ณตํ๊ธฐ ์ํ ์์คํ ์ฝ์ ์ฌ์ฉํ
seung2344.tistory.com
์ด์์ฒด์ ์์ ์ ๊ณตํ๋ ์๋น์ค ํ์ต์ฌ์ฉ์ ์ธํฐํ์ด์ค ์ข ๋ฅ์ ๋ํด ํ์ต์๋น์ค๋ฅผ ์ ๊ณตํ๊ธฐ ์ํ ์์คํ ์ฝ์ ์ข ๋ฅ์ ๋ํด ํ์ต๋ง์ปค์ ๋ก๋์ ๋ํด ํ์ต์ด์์ฒด์ ์ค๊ณ๋ฅผ ์ํ ๋ชจ๋๋ฆฌ์, ๊ณ์ธตํ, ๋ง์ดํฌ๋ก ์ปค๋, ๋ชจ๋ ๋ฐ ํ์ด๋ธ๋ฆฌ๋ ์ ๋ต์ ๋ํด ํ์ต- ์ด์์ฒด์ ์ฑ๋ฅ์ ๋ชจ๋ํฐ๋ง ํ๊ธฐ ์ํ ๋๊ตฌ ํ์ต
์ด์์ฒด์ ์ฑ๋ฅ ๋ชจ๋ํฐ๋ง์ ๊ด๋ จํ ๋ด์ฉ์ XV6๋ฅผ ์ฌ์ฉํ ๊ฐ๋จํ ์ค์ต์ ํตํด ์งํํด ๋ณผ ์์ ์ด๋ค.
xv6๋ MIT์์ ๊ฐ๋ฐ๋ UNIX ๊ธฐ๋ฐ์ ์ด์์ฒด์ ๋ก ์ฃผ๋ก ๊ต์ก ๋ชฉ์ ์ผ๋ก ์ฌ์ฉ๋๋ค.
brew install qemu
brew install i686-elf-gcc
git clone https://github.com/mit-pdos/xv6-public.git
#Makefile ์์ ํ ๋ค์ ์คํ
make
make qemu
๋๋ mac m2์นฉ์ ์ฌ์ฉํ๊ณ ์๋ ์ํ์ธ๋ฐ ๋์ปค๋ ๋ณ๋์ vm์ ๊ตฌ์ฑํ๊ณ ๋๋ฆฌ๊ธฐ ์ด์ง ๊ท์ฐฎ์์ gcc์ qemu ์ค์นํด์ ์๋ฎฌ๋ ์ดํฐ ์์์ ๋์๊ฐ๊ฒ๋ Makefile์ ์์ ํ ํ ์งํํ์๋ค.
Makefile ์ฝ๋
OBJS = \
bio.o \
console.o \
exec.o \
file.o \
fs.o \
ide.o \
ioapic.o \
kalloc.o \
kbd.o \
lapic.o \
log.o \
main.o \
mp.o \
picirq.o \
pipe.o \
proc.o \
sleeplock.o \
spinlock.o \
string.o \
swtch.o \
syscall.o \
sysfile.o \
sysproc.o \
trapasm.o \
trap.o \
uart.o \
vectors.o \
vm.o \
# Cross-compiling (e.g., on Mac OS X)
TOOLPREFIX = i686-elf-
# Using native tools (e.g., on X86 Linux)
# TOOLPREFIX =
# Try to infer the correct TOOLPREFIX if not set
ifndef TOOLPREFIX
TOOLPREFIX := $(shell if i386-jos-elf-objdump -i 2>&1 | grep '^elf32-i386$$' >/dev/null 2>&1; \
then echo 'i386-jos-elf-'; \
elif objdump -i 2>&1 | grep 'elf32-i386' >/dev/null 2>&1; \
then echo ''; \
else echo "***" 1>&2; \
echo "*** Error: Couldn't find an i386-*-elf version of GCC/binutils." 1>&2; \
echo "*** Is the directory with i386-jos-elf-gcc in your PATH?" 1>&2; \
echo "*** If your i386-*-elf toolchain is installed with a command" 1>&2; \
echo "*** prefix other than 'i386-jos-elf-', set your TOOLPREFIX" 1>&2; \
echo "*** environment variable to that prefix and run 'make' again." 1>&2; \
echo "*** To turn off this error, run 'gmake TOOLPREFIX= ...'." 1>&2; \
echo "***" 1>&2; exit 1; fi)
endif
# If the makefile can't find QEMU, specify its path here
# QEMU = qemu-system-i386
# Try to infer the correct QEMU
ifndef QEMU
QEMU = $(shell if which qemu > /dev/null; \
then echo qemu; exit; \
elif which qemu-system-i386 > /dev/null; \
then echo qemu-system-i386; exit; \
elif which qemu-system-x86_64 > /dev/null; \
then echo qemu-system-x86_64; exit; \
else \
qemu=/Applications/Q.app/Contents/MacOS/i386-softmmu.app/Contents/MacOS/i386-softmmu; \
if test -x $$qemu; then echo $$qemu; exit; fi; fi; \
echo "***" 1>&2; \
echo "*** Error: Couldn't find a working QEMU executable." 1>&2; \
echo "*** Is the directory containing the qemu binary in your PATH" 1>&2; \
echo "*** or have you tried setting the QEMU variable in Makefile?" 1>&2; \
echo "***" 1>&2; exit 1)
endif
CC = $(TOOLPREFIX)gcc
AS = $(TOOLPREFIX)gas
LD = $(TOOLPREFIX)ld
OBJCOPY = $(TOOLPREFIX)objcopy
OBJDUMP = $(TOOLPREFIX)objdump
CFLAGS = -fno-pic -static -fno-builtin -fno-strict-aliasing -O2 -MD -ggdb -fno-omit-frame-pointer
CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector)
ASFLAGS = -gdwarf-2 -Wa,-divide
# FreeBSD ld wants ``elf_i386_fbsd''
LDFLAGS += -m $(shell $(LD) -V | grep elf_i386 2>/dev/null | head -n 1)
# Disable PIE when possible (for Ubuntu 16.10 toolchain)
ifneq ($(shell $(CC) -dumpspecs 2>/dev/null | grep -e '[^f]no-pie'),)
CFLAGS += -fno-pie -no-pie
endif
ifneq ($(shell $(CC) -dumpspecs 2>/dev/null | grep -e '[^f]nopie'),)
CFLAGS += -fno-pie -nopie
endif
xv6.img: bootblock kernel
dd if=/dev/zero of=xv6.img count=10000
dd if=bootblock of=xv6.img conv=notrunc
dd if=kernel of=xv6.img seek=1 conv=notrunc
xv6memfs.img: bootblock kernelmemfs
dd if=/dev/zero of=xv6memfs.img count=10000
dd if=bootblock of=xv6memfs.img conv=notrunc
dd if=kernelmemfs of=xv6memfs.img seek=1 conv=notrunc
bootblock: bootasm.S bootmain.c
$(CC) $(CFLAGS) -fno-pic -O -nostdinc -I. -c bootmain.c
$(CC) $(CFLAGS) -fno-pic -nostdinc -I. -c bootasm.S
$(LD) $(LDFLAGS) -N -e start -Ttext 0x7C00 -o bootblock.o bootasm.o bootmain.o
$(OBJDUMP) -S bootblock.o > bootblock.asm
$(OBJCOPY) -S -O binary -j .text bootblock.o bootblock
./sign.pl bootblock
entryother: entryother.S
$(CC) $(CFLAGS) -fno-pic -nostdinc -I. -c entryother.S
$(LD) $(LDFLAGS) -N -e start -Ttext 0x7000 -o bootblockother.o entryother.o
$(OBJCOPY) -S -O binary -j .text bootblockother.o entryother
$(OBJDUMP) -S bootblockother.o > entryother.asm
initcode: initcode.S
$(CC) $(CFLAGS) -nostdinc -I. -c initcode.S
$(LD) $(LDFLAGS) -N -e start -Ttext 0 -o initcode.out initcode.o
$(OBJCOPY) -S -O binary initcode.out initcode
$(OBJDUMP) -S initcode.o > initcode.asm
kernel: $(OBJS) entry.o entryother initcode kernel.ld
$(LD) $(LDFLAGS) -T kernel.ld -o kernel entry.o $(OBJS) -b binary initcode entryother
$(OBJDUMP) -S kernel > kernel.asm
$(OBJDUMP) -t kernel | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > kernel.sym
# kernelmemfs is a copy of kernel that maintains the
# disk image in memory instead of writing to a disk.
# This is not so useful for testing persistent storage or
# exploring disk buffering implementations, but it is
# great for testing the kernel on real hardware without
# needing a scratch disk.
MEMFSOBJS = $(filter-out ide.o,$(OBJS)) memide.o
kernelmemfs: $(MEMFSOBJS) entry.o entryother initcode kernel.ld fs.img
$(LD) $(LDFLAGS) -T kernel.ld -o kernelmemfs entry.o $(MEMFSOBJS) -b binary initcode entryother fs.img
$(OBJDUMP) -S kernelmemfs > kernelmemfs.asm
$(OBJDUMP) -t kernelmemfs | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > kernelmemfs.sym
tags: $(OBJS) entryother.S _init
etags *.S *.c
vectors.S: vectors.pl
./vectors.pl > vectors.S
ULIB = ulib.o usys.o printf.o umalloc.o
_%: %.o $(ULIB)
$(LD) $(LDFLAGS) -N -e main -Ttext 0 -o $@ $^
$(OBJDUMP) -S $@ > $*.asm
$(OBJDUMP) -t $@ | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $*.sym
_forktest: forktest.o $(ULIB)
# forktest has less library code linked in - needs to be small
# in order to be able to max out the proc table.
$(LD) $(LDFLAGS) -N -e main -Ttext 0 -o _forktest forktest.o ulib.o usys.o
$(OBJDUMP) -S _forktest > forktest.asm
mkfs: mkfs.c fs.h
gcc -o mkfs mkfs.c
# Prevent deletion of intermediate files, e.g. cat.o, after first build, so
# that disk image changes after first build are persistent until clean. More
# details:
# http://www.gnu.org/software/make/manual/html_node/Chained-Rules.html
.PRECIOUS: %.o
UPROGS = \
_cat \
_echo \
_forktest \
_grep \
_init \
_kill \
_ln \
_ls \
_mkdir \
_rm \
_sh \
_stressfs \
_usertests \
_wc \
_zombie \
fs.img: mkfs README $(UPROGS)
./mkfs fs.img README $(UPROGS)
-include *.d
clean:
rm -f *.tex *.dvi *.idx *.aux *.log *.ind *.ilg \
*.o *.d *.asm *.sym vectors.S bootblock entryother \
initcode initcode.out kernel xv6.img fs.img kernelmemfs \
xv6memfs.img mkfs .gdbinit \
$(UPROGS)
# make a printout
FILES = $(shell grep -v '^\#' runoff.list)
PRINT = runoff.list runoff.spec README toc.hdr toc.ftr $(FILES)
xv6.pdf: $(PRINT)
./runoff
ls -l xv6.pdf
print: xv6.pdf
# run in emulators
bochs: fs.img xv6.img
if [ ! -e .bochsrc ]; then ln -s dot-bochsrc .bochsrc; fi
bochs -q
# try to generate a unique GDB port
GDBPORT = $(shell expr `id -u` % 5000 + 25000)
# QEMU's gdb stub command line changed in 0.11
QEMUGDB = $(shell if $(QEMU) -help | grep -q '^-gdb'; \
then echo "-gdb tcp::$(GDBPORT)"; \
else echo "-s -p $(GDBPORT)"; fi)
ifndef CPUS
CPUS := 2
endif
QEMUOPTS = -drive file=fs.img,index=1,media=disk,format=raw -drive file=xv6.img,index=0,media=disk,format=raw -smp $(CPUS) -m 512 $(QEMUEXTRA)
qemu: fs.img xv6.img
$(QEMU) -serial mon:stdio $(QEMUOPTS)
qemu-memfs: xv6memfs.img
$(QEMU) -drive file=xv6memfs.img,index=0,media=disk,format=raw -smp $(CPUS) -m 256
qemu-nox: fs.img xv6.img
$(QEMU) -nographic $(QEMUOPTS)
.gdbinit: .gdbinit.tmpl
sed "s/localhost:1234/localhost:$(GDBPORT)/" < $^ > $@
qemu-gdb: fs.img xv6.img .gdbinit
@echo "*** Now run 'gdb'." 1>&2
$(QEMU) -serial mon:stdio $(QEMUOPTS) -S $(QEMUGDB)
qemu-nox-gdb: fs.img xv6.img .gdbinit
@echo "*** Now run 'gdb'." 1>&2
$(QEMU) -nographic $(QEMUOPTS) -S $(QEMUGDB)
# CUT HERE
# prepare dist for students
# after running make dist, probably want to
# rename it to rev0 or rev1 or so on and then
# check in that version.
EXTRA = \
mkfs.c ulib.c user.h cat.c echo.c forktest.c grep.c kill.c \
ln.c ls.c mkdir.c rm.c stressfs.c usertests.c wc.c zombie.c \
printf.c umalloc.c \
README dot-bochsrc *.pl toc.* runoff runoff1 runoff.list \
.gdbinit.tmpl gdbutil \
dist:
rm -rf dist
mkdir dist
for i in $(FILES); \
do \
grep -v PAGEBREAK $$i >dist/$$i; \
done
sed '/CUT HERE/,$$d' Makefile >dist/Makefile
echo >dist/runoff.spec
cp $(EXTRA) dist
dist-test:
rm -rf dist
make dist
rm -rf dist-test
mkdir dist-test
cp dist/* dist-test
cd dist-test; $(MAKE) print
cd dist-test; $(MAKE) bochs || true
cd dist-test; $(MAKE) qemu
# update this rule (change rev#) when it is time to
# make a new revision.
tar:
rm -rf /tmp/xv6
mkdir -p /tmp/xv6
cp dist/* dist/.gdbinit.tmpl /tmp/xv6
(cd /tmp; tar cf - xv6) | gzip >xv6-rev10.tar.gz # the next one will be 10 (9/17)
.PHONY: dist-test dist
xv6์์ ์์คํ ์ฝ๊ณผ ๊ด๋ จ๋ ์ค์ต์ ์งํํ๊ธฐ ์ํด ํ์ ํด๋์ด์ผ ํ ํ์ผ๋ค์ ๋ค์๊ณผ ๊ฐ๋ค.
- user.h : xv6์ ์์คํ ์ฝ ์ ์ํ๋ ํค๋ ํ์ผ
- usys.S : xv6์ ์์คํ ์ฝ ๋ฆฌ์คํธ
- defs.h : ๋ฐ์ดํฐ ํ์ , ๋งคํฌ๋ก, ์์, ํจ์ ์ ์๋ฅผ ๊ฐ๋ ํค๋ ํ์ผ
- syscall.h : ์์คํ ์ฝ ๋ฒํธ๋ฅผ ๋งคํํ๋ ํคใทใฑ๋ ํ์ผ. ์๋ก์ด ์์คํ ์ฝ์ ์ถ๊ฐํ๋ ค๋ฉด ๋ฒํธ๋ฅผ ์ถ๊ฐํด์ผ ํจ
- syscall.c : ์์คํ ์ฝ ์ธ์๋ฅผ ๊ตฌ๋ฌธ ๋ถ์ํ๋ ํจ์ ๋ฐ ์ค์ ์์คํ ์ฝ ๊ตฌํ์ ๋ํ ํฌ์ธํฐ
- sysproc.c : ํ๋ก์ธ์ค ๊ด๋ จ ์์คํ ํธ์ถ ๊ตฌํ. fork(), exec(), wait(), exit() ์ ๊ฐ์ ์์คํ ํธ์ถ์ ์ค์ ๋ก์ง์ด ์์. ์๋ก์ด ํ๋ก์ธ์ค ๊ด๋ จ ์์คํ ํธ์ถ์ ์ถ๊ฐํ ๋ ์ฌ๊ธฐ์ ์ฝ๋๋ฅผ ์์ฑํด์ผ ํจ
- proc.h : ํ๋ก์ธ์ค์ ๋ํ ๊ตฌ์กฐ์ฒด์ธ struct proc์ ์ ์๊ฐ ํฌํจ๋ ํค๋ ํ์ผ. ํ๋ก์ธ์ค์ ์ํ, PID(ํ๋ก์ธ์ค ID), ๋ถ๋ชจ ํ๋ก์ธ์ค, ์คํ ํฌ์ธํฐ ๋ฑ ํ๋ก์ธ์ค์ ๋ํ ์ถ๊ฐ ์ ๋ณด๋ฅผ ์ถ์ ํ๋ ๋ฐ ์ฌ์ฉ๋จ
- proc.c : ํ๋ก์ธ์ค ๊ฐ์ ์ค์ผ์ค๋ง ๋ฐ ์ปจํ ์คํธ ์ ํ์ ์ํํ๋ ํจ์๊ฐ ๊ตฌํ๋ ํ์ผ.
์ฑ๋ฅ ๊ด์ฐฐ ๋ฐ ์กฐ์
์์คํ ์ ์ฑ๋ฅ์ ๊ฐ์ ์ํค๊ธฐ ์ํด์ ๋ณ๋ชฉ ์ง์ ์ ์ ๊ฑฐํ๋ ๊ฒ์ด ํ์์ ์ด๋ค. ์ด๋ฌํ ๋ณ๋ชฉ ์ง์ ์ ๋ฐ๊ฒฌํ๊ธฐ ์ํ ๋ฐฉ๋ฒ์ผ๋ก๋ counter์ tracing ๋ ๊ฐ์ง ์ ๊ทผ ๋ฐฉ์์ด ๋ํ์ ์ด๋ค.
- Counter : ํธ์ถ๋ ์์คํ ์ฝ ํ์ ๋๋ ๋คํธ์ํฌ ์ฅ์น ๋๋ ๋์คํฌ์ ์ํ๋ ์์ ์์ ๊ฐ์ ์์คํ ํ๋์ ์ถ์
- Tracing : ์์คํ ์ฝ๊ณผ ๊ด๋ จ๋ ๋จ๊ณ์ ๊ฐ์ ํน์ ์ด๋ฒคํธ์ ๋ํ ๋ฐ์ดํฐ๋ฅผ ์์ง
getforkcount ์ค์ต
fork๊ฐ ๋ฐ์ํ ๋, ๊ณผ์ฐ ๊ด๋ จ ์์คํ ์ฝ์ด ์ ํํ ๋ฐ์ํ๋ ์ง ํ์ธํ๊ธฐ ์ํด ๊ทธ ์๋ฅผ ์ธ๋ ๊ฐ๋จํ ์์คํ ์ฝ์ด๋ค. ์์คํ ์ฝ์ ์ถ๊ฐํ๋ ์ ์ฒด์ ์ธ ๊ณผ์ ์ ๋ค์๊ณผ ๊ฐ๋ค.
- ์ ์ญ ๋ณ์ ์ ์ธ: sysproc.c ํน์proc.c์ ์ ์ญ ๋ณ์๋ฅผ ์ ์ธ
- ์์คํ ์ฝ ํจ์ ๊ตฌํ: ์์คํ ์ฝ์ ๋ํ ๋์์ ์ ์ํ๋ ํจ์๋ฅผ sysproc.c์ ์์ฑ
- ์์คํ ์ฝ ๋ฒํธ ํ ๋น: syscall.h์ ์๋ก์ด ์์คํ ์ฝ ๋ฒํธ๋ฅผ ํ ๋น
- ์์คํ ์ฝ ํ ์ด๋ธ ๋ฑ๋ก: syscall.c ํ์ผ์ ์์คํ ์ฝ ํ ์ด๋ธ์ ์๋ก์ด ์์คํ ์ฝ์ ๋ฑ๋ก
- ์ ์ ์ธํฐํ์ด์ค ์ถ๊ฐ: usys.S ํ์ผ์ ์์คํ ์ฝ์ ์ ์ ๊ณต๊ฐ์์ ํธ์ถํ ์ ์๋๋ก ์ ์ธ
- ์ ์ ํ๋ก๊ทธ๋จ ์ถ๊ฐ : user.h ํ์ผ์ ์ ์ ๊ณต๊ฐ์์ ์ฌ์ฉํ ํจ์์ ์ ์ธ๋ถ ์์ฑ
(user.h๋ ํจ์์ ํ๋กํ ํ์ ์ด๋ฉฐ, ์ค์ ๋ก๋ usys.S์์ ์์คํ ์ฝ๊ณผ ์ปค๋์ ์ฐ๊ฒฐ์ด ์ด๋ฃจ์ด์ง๋ค.)
// sysproc.c์ ์ ์ญ ๋ณ์ ์ค์ ํ, sys_fork ํจ์์ ๋ก์ง ์ถ๊ฐ
// fork_count ๊ฐ์ ๋ฐํํ๋ ํจ์ ์ถ๊ฐ
int fork_count = 0;
int
sys_fork(void)
{
fork_count++;
return fork();
}
int
sys_getforkcount(void)
{
return fork_count;
}
// syscall.h์ ์์คํ
์ฝ ์ถ๊ฐ
#define SYS_getforkcount 23
// syscall.c์์ ์์คํ
์ฝ ํ
์ด๋ธ์ ๋ฑ๋ก
extern int sys_getforkcount(void);
...
[SYS_getforkcount] sys_getforkcount,
//usys.S์ ps ์์คํ
์ฝ ์ ์
SYSCALL(getforkcount)
// user.h์ ์ถ๊ฐ. ์ฌ์ฉ์ ๋ชจ๋์์์ ์ฌ์ฉ์ ์ํจ
int getforkcount(void);
//getforkcount.c์์ ์์คํ
์ฝ ํธ์ถ
#include "types.h"
#include "user.h"
int
main(void)
{
int count = getforkcount();
printf(1,"Initial fork count: %d\n", count);
// fork ํธ์ถ
if (fork() == 0) {
// ์์ ํ๋ก์ธ์ค์์๋ exit๋ง ์ํ
exit();
}
wait(); // ์์ ํ๋ก์ธ์ค๊ฐ ์ข
๋ฃ๋ ๋๊น์ง ๋๊ธฐ
count = getforkcount();
printf(1,"Fork count after fork: %d\n", count);
exit();
}
//Makefile์ ps ์ถ๊ฐ
UPROGS = \
...
_getforkcount \
EXTRA = \
mkfs.c ... getforkcount.c\
fork ๋ฐ์ ์์ counter๊ฐ ๋์ํด์ผ ํ๊ธฐ ๋๋ฌธ์ ๊ธฐ์กด์ ์ด๋ฏธ ์์ฑ๋์ด ์๋ fork ์์คํ ์ฝ ๋ก์ง์ count๊ฐ์ ๋๋ฆฌ๋ ์ฝ๋๋ฅผ ์ถ๊ฐํ๋ ๋ฐฉ์์ผ๋ก ์งํํ์๋ค.

getforkcount์๋ fork๋ฅผ 1ํ ์ํํ๊ฒ๋ ์ฝ๋๋ฅผ ์์ฑํด ๋ ์ํ์ด๋ค. getforkcount ๋ช ๋ น์ด ์ฌ์ฉ์ ํตํด forkcount ์๊ฐ 1 ์ฆ๊ฐ ๋จ์ ํ์ธ ํ ์ ์์ผ๋ฉฐ, xv6์์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณตํ๋ forktest ์ดํ ๋ค์ ์์คํ ์ฝ ํธ์ถ ์ forkcount ์๊ฐ ๋ ์ฆ๊ฐํ ๊ฒ์ ํ์ธ ํ ์ ์๋ค.
trace ์ค์ต
์์คํ ์ฝ์ด ๋ฐ์ํ๋ฉด ์ด๋ค ํ๋ก์ธ์ค๊ฐ ํ ์คํฌ๋ฅผ ํ ๋น๋ฐ์ ์์คํ ์ฝ์ ํธ์ถํ๋์ง ํ์ธํ ์ ์๋ ์์คํ ์ฝ์ด๋ค. ์์คํ ์ฝ์ ์ถ๊ฐํ๋ ๋๋ต์ ์ธ ๊ณผ์ ์ counter ์ค์ต๊ณผ ๋์ผํ๊ฒ ์งํ๋๋ค.
// sysproc.c์ ์ ์ญ ๋ณ์ ์ค์
// trace ๊ธฐ๋ฅ์ ์ ์ดํ๋ ์์คํ
์ฝ ์ถ๊ฐ
extern int tracing_enabled; // 0: tracing ๋นํ์ฑํ, 1: tracing ํ์ฑํ
int
sys_trace(void)
{
int enable;
if(argint(0, &enable) < 0)
return -1;
tracing_enabled = enable;
return 0;
}
// syscall.h์ ์์คํ
์ฝ ์ถ๊ฐ
#define SYS_trace 24
// syscall.c์์ ์์คํ
์ฝ ํ
์ด๋ธ์ ๋ฑ๋ก
// syscall์ ์์ ํ์ฌ ์์คํ
์ฝ ๋ฐ์ ์, ์ฝ์์ ์ถ๋ ฅํ๊ฒ๋ ์์
int tracing_enabled = 0;
extern int sys_trace(void);
...
[SYS_getforkcount] sys_trace,
void
syscall(void)
{
int num;
struct proc *curproc = myproc();
num = curproc->tf->eax;
if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {
if(tracing_enabled) { // tracing์ด ํ์ฑํ๋ ๊ฒฝ์ฐ
cprintf(" pname : %s pid : %d syscall : %d\n", curproc->name, curproc->pid, num);
}
curproc->tf->eax = syscalls[num]();
} else {
cprintf("%d %s: unknown sys call %d\n",
curproc->pid, curproc->name, num);
curproc->tf->eax = -1;
}
}
//usys.S์ ์์คํ
์ฝ ์ ์
SYSCALL(trace)
// user.h์ ์ถ๊ฐ. ์ฌ์ฉ์ ๋ชจ๋์์์ ์ฌ์ฉ์ ์ํจ
int trace(int enable);
//trace.c
#include "types.h"
#include "user.h"
int
main(int argc, char *argv[])
{
if(argc != 2) {
printf(2, "Usage: trace [0|1]\n");
exit();
}
int enable = atoi(argv[1]);
if(enable != 0 && enable != 1) {
printf(2, "Invalid argument. Use 0 to disable or 1 to enable tracing.\n");
exit();
}
// ์์คํ
์ฝ์ ํตํด tracing ํ์ฑํ ๋๋ ๋นํ์ฑํ
trace(enable);
if(enable)
printf(1, "Tracing enabled\n");
else
printf(1, "Tracing disabled\n");
exit();
}
//Makefile์ ps ์ถ๊ฐ
UPROGS = \
...
_trace \
EXTRA = \
mkfs.c ... trace.c\
์์คํ ์ฝ์ด ๋์ํ ๋๋ง๋ค ์ด๋ค ํ๋ก์ธ์ค๊ฐ ์ด๋ค ์์ ์ ํ๋์ง ์๊ธฐ ์ํด์ ๊ธฐ์กด์ ์์ฑ๋์ด์๋ syscall ํจ์๋ฅผ ์์ ํ๋ ๋ฐฉ์์ผ๋ก ์ค์ต์ ์งํํ์๋ค. trace 1 ์ ๋ ฅ์ ํตํด tracing์ ์์ํ๊ณ trace 0์ ํตํด tracing์ ์ข ๋ฃํ๊ฒ ๋๋ค.


์คํ ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ๋ค. 70๋ฒ ํ๋ก์ธ์ค๊ฐ trace๋ฅผ ์ํ ์์ ์ ์ํด ํ ๋น๋์ด ์์คํ ์ฝ์ ํธ์ถ ์ค์ด๋ฉฐ trace ์์ ์ Tracing enabled๋ฅผ ์ถ๋ ฅํ๊ธฐ ์ํด write ์์คํ ์ฝ(16๋ฒ)์ ํธ์ถ ํ์์ผ๋ฉฐ ์ถ๋ ฅ์ด ๋๋์ exit ์์คํ ์ฝ(2๋ฒ)์ ํธ์ถํ์ฌ ์ข ๋ฃํ๊ณ ์์ ์ํ 2๋ฒ ํ๋ก์ธ์ค์๊ฒ ์ ์ด๋ฅผ ๋๊ฒผ๋ค. 2๋ฒ ํ๋ก์ธ์ค๋ ๊ณต๋ฐฑ๊ณผ $ ๋ฌธ๊ตฌ ์ถ๋ ฅ์ ์ํด 16๋ฒ ์์คํ ์ฝ์ ํธ์ถํ ํ ์ฌ์ฉ์์๊ฒ ๊ฐ์ ์ ๋ ฅ๋ฐ๊ธฐ ์ํด read ์์คํ ์ฝ(5๋ฒ)์ ํธ์ถํ์๋ค.
์ดํ getforkcount ์์คํ ์ฝ์ ๋ถ๋ฌ๋ณด์๋ค. ์์ฑํ ๊ธ์๋ฅผ ์ฝ์ด๋ค์ด๊ธฐ ์ํด 5๋ฒ ์์คํ ์ฝ์ด ๊ธ์์ ๋งํผ ํธ์ถ๋์์ผ๋ฉฐ, ์ดํ fork ์์คํ ์ฝ(1๋ฒ)์ ํธ์ถํ์ฌ ํ๋ก์ธ์ค๋ฅผ ์์ฑํ๊ณ ๋๊ธฐ ์ํ๋ก ๋ค์ด๊ฐ(3๋ฒ) ์์ ํ๋ก์ธ์ค(71๋ฒ ํ๋ก์ธ์ค)์๊ฒ ์ ์ด๋ฅผ ๋๊ฒผ๋ค. 71๋ฒ ํ๋ก์ธ์ค๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋น๋ฐ๊ณ (12๋ฒ) ํ์ฑํ ์ํ(7๋ฒ)๋ก ๋ค์ด๊ฐ๋ค. ๊ทธ ํ getforkcount ์์คํ ์ฝ(23๋ฒ)์ ํธ์ถํ๊ณ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์ถ๋ ฅํ๊ธฐ ์ํด write ์์คํ ์ฝ์ ๋ฐ๋ณตํ์๋ค.
ํด๋น ์ค์ต์ ํตํด ํ๋ก์ธ์ค๊ฐ ์์คํ ์ฝ์ ํธ์ถํ๋ ์์ฃผ ๋๋ต์ ์ธ ๊ณผ์ ์ ํ์ธ ํ ์ ์์๊ณ ์์๋๋ก ๋์ํจ์ ํ์ธํ ์ ์์๋ค.
'CS' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[์ด์์ฒด์ ]๐ฆ๊ณต๋ฃก์ฑ ๐ฆ3์ฅ - ํ๋ก์ธ์ค(1) (6) | 2024.10.16 |
---|---|
[์ด์์ฒด์ ]๐ฆ๊ณต๋ฃก์ฑ ๐ฆ2์ฅ - ์ด์์ฒด์ ๊ตฌ์กฐ(2) (1) | 2024.10.07 |
[์ด์์ฒด์ ]๐ฆ๊ณต๋ฃก์ฑ ๐ฆ2์ฅ - ์ด์์ฒด์ ๊ตฌ์กฐ(1) (1) | 2024.09.26 |
์ฝ๋ฉ ํ ์คํธ ์ดํดํ๊ธฐ (1) | 2024.03.29 |