哈工大作業系統實驗 5 地址對映與共享
//=====================================================================================
========================================================================Bochs x86 Emulator 2.3.7
Build from CVS snapshot, on June 3, 2008
========================================================================
00000000000i[ ] reading configuration from ./bochs/bochsrc.bxrc
00000000000i[ ] installing x module as the Bochs GUI
00000000000i[ ] using log file ./bochsout.txt
Next at t=0
(0) [0xfffffff0] f000:fff0 (unk. ctxt): jmp far f000:e05b ; ea5be000f0
<bochs:1> c
^CNext at t=121516790
(0) [0x00faa06c] 000f:0000006c (unk. ctxt): jmp .+0xfffffff5 (0x10000063) ; ebf5
<bochs:2> n
Next at t=121516791
(0) [0x00faa063] 000f:00000063 (unk. ctxt): cmp dword ptr ds:0x3004, 0x00000000 ; 833d0430000000
<bochs:3> u /7
10000063: ( ): cmp dword ptr ds:0x3004, 0x00000000 ; 833d0430000000
1000006a: ( ): jz .+0x00000004 ; 7404
1000006c: ( ): jmp .+0xfffffff5 ; ebf5
1000006e: ( ): add byte ptr ds:[eax], al ; 0000
10000070: ( ): xor eax, eax ; 31c0
10000072: ( ): jmp .+0x00000000 ; eb00
10000074: ( ): leave ; c9
<bochs:4> sreg
cs:s=0x000f, dl=0x00000002, dh=0x10c0fa00, valid=1
ds:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=3
ss:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
es:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
fs:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
gs:s=0x0017, dl=0x00003fff, dh=0x10c0f300, valid=1
ldtr:s=0x0068, dl=0x52d00068, dh=0x000082fd, valid=1
tr:s=0x0060, dl=0x52e80068, dh=0x00008bfd, valid=1
gdtr:base=0x00005cb8, limit=0x7ff
idtr:base=0x000054b8, limit=0x7ff
<bochs:5> xp /2w 0x00005cb8 +13*8
[bochs]:
0x00005d20 <bogus+ 0>:0x52d000680x000082fd
<bochs:6> xp /8w 0x0052d0fd
[bochs]:
0x0052d0fd <bogus+ 0>:0x000000000x000000000x000000000x00000000
0x0052d10d <bogus+ 16>:0x000000000x000000000x000000000x00000000
<bochs:7> xp /8w 0x00fd52d0
[bochs]:
0x00fd52d0 <bogus+ 0>:0x000000000x000000000x000000020x10c0fa00
0x00fd52e0 <bogus+ 16>:0x00003fff0x10c0f3000x000000000x00fd6000
<bochs:8> calc ds:0x3004
0x10003004 268447748
<bochs:9> creg
CR0=0x8000001b: PG cd nw ac wp ne ET TS em MP PE
CR2=page fault laddr=0x10002fac
CR3=0x00000000
PCD=page-level cache disable=0
PWT=page-level writes transparent=0
CR4=0x00000000: osxmmexcpt osfxsr pce pge mce pae pse de tsd pvi vme
<bochs:10> xp /68w 0
[bochs]:
0x00000000 <bogus+ 0>:0x000010270x000020070x000030070x00004027
0x00000010 <bogus+ 16>:0x000000000x0002ace40x000000000x00000000
0x00000020 <bogus+ 32>:0x000000000x000000000x000000000x00000000
0x00000030 <bogus+ 48>:0x000000000x000000000x000000000x00000000
0x00000040 <bogus+ 64>:0x00ffe0270x000000000x000000000x00000000
0x00000050 <bogus+ 80>:0x000000000x000000000x000000000x00000000
0x00000060 <bogus+ 96>:0x000000000x000000000x000000000x00000000
0x00000070 <bogus+ 112>:0x000000000x000000000x000000000x00000000
0x00000080 <bogus+ 128>:0x00ff30270x000000000x000000000x00000000
0x00000090 <bogus+ 144>:0x000000000x000000000x000000000x00000000
0x000000a0 <bogus+ 160>:0x000000000x000000000x000000000x00000000
0x000000b0 <bogus+ 176>:0x000000000x000000000x000000000x00ffb027
0x000000c0 <bogus+ 192>:0x00ff60270x000000000x000000000x00000000
0x000000d0 <bogus+ 208>:0x000000000x000000000x000000000x00000000
0x000000e0 <bogus+ 224>:0x000000000x000000000x000000000x00000000
0x000000f0 <bogus+ 240>:0x000000000x000000000x000000000x00ffa027
0x00000100 <bogus+ 256>:0x00fa70270x000000000x000000000x00000000
<bochs:11> xp /w 0+64*4
[bochs]:
0x00000100 <bogus+ 0>:0x00fa7027
<bochs:12> page 0x10003004
linear page 0x10003000 maps to physical page 0x00fa6000
<bochs:13> xp /w 0x00fa6004
[bochs]:
0x00fa6004 <bogus+ 0>:0x12345678
END
1.
獲得邏輯地址。
根據ldtr與gdtr,尋找LDT表的在GDT中實體地址。
檢視LDT內容,得到線性地址。
檢視線性地址在頁表中對應的頁目錄號,將所得頁框號與偏移地址拼接得到實體地址。
2. 發現線性地址的獲得與上次相同,而實體地址卻與上次不同,因為系同會隨機分配空閒實體地址,對映時邏輯地址是我們指定的。
//=====================================================================================
這次試驗需要寫的程式碼量很少,需要修改的地方比挺多。
需要修改
mm/makefile
mm/memory.c
kernel/system_call.s
include/linux/sys.h
include/unistd.h這幾個檔案來新增系統呼叫shmat() 與 shmget() 兩個系統呼叫。
kernal/makefile 和第四次實驗一樣就好。
需要編寫
mm/shm.c
producer.c
consumer.c 三個檔案,其實後兩個只需要改寫一下上一次的pc.c就可以了。
mm/nakefile 修改成這樣
shm.s 後面的一大坨是中間檔案,依賴檔案什麼的,詳細看我部落格裡的轉載。
- CC =gcc-3.4 -march=i386
- CFLAGS =-m32 -g -Wall -O -fstrength-reduce -fomit-frame-pointer \
- -finline-functions -nostdinc -I../include
- AS =as --32
- AR =ar
- LD =ld
- LDFLAGS =-m elf_i386
- CPP =gcc-3.4 -E -nostdinc -I../include
- .c.o:
- $(CC) $(CFLAGS) \
- -c -o $*.o {1}lt;
- .s.o:
- $(AS) -o $*.o {1}lt;
- .c.s:
- $(CC) $(CFLAGS) \
- -S -o $*.s {1}lt;
- OBJS = memory.o page.o shm.o
- all: mm.o
- mm.o: $(OBJS)
- $(LD) -m elf_i386 -r -o mm.o $(OBJS)
- clean:
- rm -f core *.o *.a tmp_make
- for i in *.c;do rm -f `basename $i .c`.s;done
- dep:
- sed '/\#\#\# Dependencies/q' <Makefile> tmp_make
- (for i in *.c;do $(CPP) -M $i;done) >> tmp_make
- cp tmp_make Makefile
- ### Dependencies:
- shm.s shm.o: shm.c ../include/linux/kernel.h ../include/unistd.h
- memory.o: memory.c ../include/signal.h ../include/sys/types.h \
- ../include/asm/system.h ../include/linux/sched.h \
- ../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \
- ../include/linux/kernel.h
memory.c 的修改方法 如果執行程式時出現trying to free free page 錯誤 可以單純的把panic註釋掉,防止程式中斷。
呼叫shmat()成功時,mam_map[] 對應的數值將會加一。
因為我們沒有寫int shmdt(const void *shmaddr) 這個用來釋放共享記憶體的函式。程序結束時,系統會自動檢測程序中對映的共享記憶體
並釋放該對映,並將mam_map[]減一。
如果你的shm沒寫好,或呼叫shmat失敗,程式退出時會出現,上述錯誤。
如果shm寫的好,memory.c 是不用修改的。
不過本人比較懶。還是修改memory.c方便啊 : P
- /*
- * Free a page of memory at physical address 'addr'. Used by
- * 'free_page_tables()'
- */
- void free_page(unsigned long addr)
- {
- if (addr < LOW_MEM) return;
- if (addr >= HIGH_MEMORY)
- panic("trying to free nonexistent page");
- addr -= LOW_MEM;
- addr >>= 12;
- if (mem_map[addr]) {mem_map[addr]--;return;}
- mem_map[addr]=0;
- //panic("trying to free free page");
- }
其他三個檔案,修改過很多次了,我也懶得說了。
producer.c這樣寫
當我們使用系統呼叫時,需要包含進<unistd.h>之前定義的符號 __LIBRARY__
頁的大小為4kb
key 為10
shmat()返回一個指標,指向對映的虛擬記憶體的首地址。
- #define __LIBRARY__
- #include <unistd.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <sys/types.h>
- #include <fcntl.h>
- #define EINVAL 22
- #define ENOMEM 12
- #define N 600
- #define KEYNUM 10
- #define PAGE 4096
- _syscall2(int,sem_open, constchar*, name, unsigned int , value)
- _syscall1(int, sem_wait, sem_t *, sem)
- _syscall1(int, sem_post, sem_t *, sem)
- _syscall1(int, sem_unlink, constchar *, name)
- _syscall2(int