哈工大操作系统实验 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>: 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;
}


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值