//=====================================================================================
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>: 0x52d00068 0x000082fd
<bochs:6> xp /8w 0x0052d0fd
[bochs]:
0x0052d0fd <bogus+ 0>: 0x00000000 0x00000000 0x00000000 0x00000000
0x0052d10d <bogus+ 16>: 0x00000000 0x00000000 0x00000000 0x00000000
<bochs:7> xp /8w 0x00fd52d0
[bochs]:
0x00fd52d0 <bogus+ 0>: 0x00000000 0x00000000 0x00000002 0x10c0fa00
0x00fd52e0 <bogus+ 16>: 0x00003fff 0x10c0f300 0x00000000 0x00fd6000
<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>: 0x00001027 0x00002007 0x00003007 0x00004027
0x00000010 <bogus+ 16>: 0x00000000 0x0002ace4 0x00000000 0x00000000
0x00000020 <bogus+ 32>: 0x00000000 0x00000000 0x00000000 0x00000000
0x00000030 <bogus+ 48>: 0x00000000 0x00000000 0x00000000 0x00000000
0x00000040 <bogus+ 64>: 0x00ffe027 0x00000000 0x00000000 0x00000000
0x00000050 <bogus+ 80>: 0x00000000 0x00000000 0x00000000 0x00000000
0x00000060 <bogus+ 96>: 0x00000000 0x00000000 0x00000000 0x00000000
0x00000070 <bogus+ 112>: 0x00000000 0x00000000 0x00000000 0x00000000
0x00000080 <bogus+ 128>: 0x00ff3027 0x00000000 0x00000000 0x00000000
0x00000090 <bogus+ 144>: 0x00000000 0x00000000 0x00000000 0x00000000
0x000000a0 <bogus+ 160>: 0x00000000 0x00000000 0x00000000 0x00000000
0x000000b0 <bogus+ 176>: 0x00000000 0x00000000 0x00000000 0x00ffb027
0x000000c0 <bogus+ 192>: 0x00ff6027 0x00000000 0x00000000 0x00000000
0x000000d0 <bogus+ 208>: 0x00000000 0x00000000 0x00000000 0x00000000
0x000000e0 <bogus+ 224>: 0x00000000 0x00000000 0x00000000 0x00000000
0x000000f0 <bogus+ 240>: 0x00000000 0x00000000 0x00000000 0x00ffa027
0x00000100 <bogus+ 256>: 0x00fa7027 0x00000000 0x00000000 0x00000000
<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 后面的一大坨是中间文件,依赖文件什么的,详细看我博客里的转载。
http://blog.csdn.net/wangyi_lin/article/details/7020002
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, const char*, name, unsigned int , value)
_syscall1(int, sem_wait, sem_t *, sem)
_syscall1(int, sem_post, sem_t *, sem)
_syscall1(int, sem_unlink, const char *, name)
_syscall2(int, shmget, key_t, key, size_t, size)
_syscall2(void *, shmat, int, trueaddress, const void*, shmaddr)
int main()
{
int trueaddress, i,* offsetaddress;
sem_t *empty, *full, *mutex;
empty = (sem_t *)sem_open("empty",10);
full = (sem_t *)sem_open("full", 0);
mutex = (sem_t *)sem_open("mutex", 1);
trueaddress = shmget((key_t)KEYNUM,PAGE);
if(trueaddress==-EINVAL) {
printf("larger than size of one page!");
goto exits;
}else if(trueaddress==-ENOMEM) {
printf("no free page!");
goto exits;
}
else offsetaddress = (int*)shmat(trueaddress,NULL);
for( i = 0 ; i < N; i++) {
sem_wait(empty);
sem_wait(mutex);
offsetaddress[i%10] = i;
sem_post(mutex);
sem_post(full);
}
exits:
fflush(stdout);
sem_unlink("empty");
sem_unlink("full");
sem_unlink("mutex");
return 0;
}
consumer.c 这样写
#define __LIBRARY__
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#define N 600
#define KEYNUM 10
#define PAGE 4096
_syscall2(int,sem_open, const char*, name, unsigned int , value)
_syscall1(int, sem_wait, sem_t *, sem)
_syscall1(int, sem_post, sem_t *, sem)
_syscall1(int, sem_unlink, const char *, name)
_syscall2(int, shmget, key_t, key, size_t, size)
_syscall2(void *, shmat, int, trueaddress, const void*, shmaddr)
int main()
{
int trueaddress, i, *offsetaddress;
sem_t *empty, *full, *mutex;
empty = (sem_t *)sem_open("empty",10);
full = (sem_t *)sem_open("full", 0);
mutex = (sem_t *)sem_open("mutex", 1);
trueaddress = shmget((key_t)KEYNUM, PAGE);
offsetaddress = (int*)shmat(trueaddress,NULL);
for( i = 0 ; i < N; i++){
sem_wait(full);
sem_wait(mutex);
printf("%d\n",offsetaddress[i%10]);
fflush(stdout);
sem_post(mutex);
sem_post(empty);
}
sem_unlink("empty");
sem_unlink("full");
sem_unlink("mutex");
return 0;
}
shm.c这样写
brk是进程代码和数据总长度和未初始化的数据区bss的总长度,修改这个指针可以为进程释放和动态分配内存。
vector数组里存储的是实际地址。
#pragma once
#define __LIBRARY__
#include <unistd.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <asm/system.h>
#include <linux/kernel.h>
#define ENOMEM 12
#define EINVAL 22
int vector[20]={0};
int sys_shmget(key_t key, size_t size){
int free;
if(vector[key]!=0) return vector[key];
else{
if(size > 1024*4) return -EINVAL; else;
if(!(free = get_free_page())) return -ENOMEM;
else vector[key] = free;
return vector[key];
}
}
void* sys_shmat(int shmid, const void *shmaddr){
if(!shmid) return -EINVAL;
put_page(shmid, current->start_code + current->brk);
return current->brk;
}