哈工大操作系统实验 5 地址映射与共享

来源:互联网 发布:java long 最大长度 编辑:程序博客网 时间:2024/06/05 18:06

//=====================================================================================


========================================================================
                       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 后面的一大坨是中间文件,依赖文件什么的,详细看我博客里的转载。

http://blog.csdn.net/wangyi_lin/article/details/7020002

[html] view plain copy
  1. CC  =gcc-3.4 -march=i386  
  2. CFLAGS  =-m32 -g -Wall -O -fstrength-reduce -fomit-frame-pointer \  
  3.     -finline-functions -nostdinc -I../include  
  4. AS  =as --32  
  5. AR  =ar  
  6. LD  =ld  
  7. LDFLAGS =-m elf_i386  
  8. CPP =gcc-3.4 -E -nostdinc -I../include  
  9.   
  10. .c.o:  
  11.     $(CC) $(CFLAGS) \  
  12.     -c -o $*.o {1}lt;  
  13. .s.o:  
  14.     $(AS) -o $*.o {1}lt;  
  15. .c.s:  
  16.     $(CC) $(CFLAGS) \  
  17.     -S -o $*.s {1}lt;  
  18.   
  19. OBJS    = memory.o page.o shm.o  
  20.   
  21. all: mm.o  
  22.   
  23. mm.o: $(OBJS)  
  24.     $(LD) -m elf_i386 -r -o mm.o $(OBJS)  
  25.   
  26. clean:  
  27.     rm -f core *.o *.a tmp_make  
  28.     for i in *.c;do rm -f `basename $i .c`.s;done  
  29.   
  30. dep:  
  31.     sed '/\#\#\# Dependencies/q' < Makefile > tmp_make  
  32.     (for i in *.c;do $(CPP) -M $i;done) >> tmp_make  
  33.     cp tmp_make Makefile  
  34.   
  35. ### Dependencies:  
  36. shm.s shm.o: shm.c ../include/linux/kernel.h ../include/unistd.h  
  37. memory.o: memory.c ../include/signal.h ../include/sys/types.h \  
  38.   ../include/asm/system.h ../include/linux/sched.h \  
  39.   ../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \  
  40.   ../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

[cpp] view plain copy
  1. /* 
  2.  * Free a page of memory at physical address 'addr'. Used by 
  3.  * 'free_page_tables()' 
  4.  */  
  5. void free_page(unsigned long addr)  
  6. {  
  7.     if (addr < LOW_MEM) return;  
  8.     if (addr >= HIGH_MEMORY)  
  9.         panic("trying to free nonexistent page");  
  10.     addr -= LOW_MEM;  
  11.     addr >>= 12;  
  12.     if (mem_map[addr]) {mem_map[addr]--;return;}  
  13.     mem_map[addr]=0;  
  14.     //panic("trying to free free page");  
  15. }  


其他三个文件,修改过很多次了,我也懒得说了。


producer.c这样写 

当我们使用系统调用时,需要包含进<unistd.h>之前定义的符号 __LIBRARY__

页的大小为4kb

key 为10

shmat()返回一个指针,指向映射的虚拟内存的首地址。

[cpp] view plain copy
  1. #define   __LIBRARY__  
  2. #include <unistd.h>  
  3. #include <stdlib.h>  
  4. #include <stdio.h>  
  5. #include <sys/types.h>  
  6. #include <fcntl.h>  
  7.   
  8.   
  9. #define EINVAL      22  
  10. #define ENOMEM      12  
  11. #define N               600  
  12. #define KEYNUM          10  
  13. #define PAGE            4096  
  14.     _syscall2(int,sem_open, const char*, name, unsigned int , value)  
  15.     _syscall1(int, sem_wait, sem_t  *, sem)  
  16.     _syscall1(int, sem_post, sem_t  *, sem)  
  17.     _syscall1(int, sem_unlink, const char  *, name)  
  18.     _syscall2(int, shmget, key_t, key, size_t, size)  
  19.         _syscall2(void *, shmat, int, trueaddress, const void*, shmaddr)  
  20.   
  21.   
  22. int main()  
  23. {  
  24.         int trueaddress, i,* offsetaddress;  
  25.         sem_t   *empty, *full, *mutex;  
  26.         empty = (sem_t *)sem_open("empty",10);  
  27.         full  = (sem_t *)sem_open("full", 0);  
  28.         mutex = (sem_t *)sem_open("mutex", 1);  
  29.         trueaddress = shmget((key_t)KEYNUM,PAGE);  
  30.         if(trueaddress==-EINVAL) {  
  31.                 printf("larger than size of one page!");  
  32.                 goto exits;  
  33.         }else if(trueaddress==-ENOMEM)  {  
  34.                 printf("no free page!");   
  35.                 goto exits;  
  36.         }  
  37.         else offsetaddress = (int*)shmat(trueaddress,NULL);  
  38.   
  39.   
  40.         for( i = 0 ; i < N; i++) {  
  41.                 sem_wait(empty);  
  42.                 sem_wait(mutex);  
  43.                 offsetaddress[i%10] = i;  
  44.                 sem_post(mutex);  
  45.                 sem_post(full);  
  46.        }  
  47. exits:  
  48.         fflush(stdout);  
  49.         sem_unlink("empty");  
  50.         sem_unlink("full");  
  51.         sem_unlink("mutex");  
  52.         return 0;  
  53. }  

consumer.c  这样写

 

[cpp] view plain copy
  1. #define   __LIBRARY__  
  2. #include <unistd.h>  
  3. #include <stdlib.h>  
  4. #include <stdio.h>  
  5. #include <sys/types.h>  
  6. #include <fcntl.h>  
  7.   
  8.   
  9. #define N               600  
  10. #define KEYNUM          10  
  11. #define PAGE            4096  
  12.   
  13.         _syscall2(int,sem_open, const char*, name, unsigned int , value)  
  14.         _syscall1(int, sem_wait, sem_t  *, sem)  
  15.         _syscall1(int, sem_post, sem_t  *, sem)  
  16.         _syscall1(int, sem_unlink, const char  *, name)  
  17.         _syscall2(int, shmget, key_t, key, size_t, size)  
  18.         _syscall2(void *, shmat, int, trueaddress, const void*, shmaddr)  
  19.   
  20. int main()  
  21. {  
  22.         int trueaddress, i, *offsetaddress;  
  23.         sem_t   *empty, *full, *mutex;  
  24.   
  25.         empty = (sem_t *)sem_open("empty",10);  
  26.         full  = (sem_t *)sem_open("full", 0);  
  27.         mutex = (sem_t *)sem_open("mutex", 1);  
  28.         trueaddress = shmget((key_t)KEYNUM, PAGE);  
  29.         offsetaddress = (int*)shmat(trueaddress,NULL);  
  30.         for( i = 0 ; i < N; i++){  
  31.                 sem_wait(full);  
  32.                 sem_wait(mutex);  
  33.                 printf("%d\n",offsetaddress[i%10]);  
  34.                 fflush(stdout);  
  35.                 sem_post(mutex);  
  36.                 sem_post(empty);  
  37.     }  
  38.   
  39.         sem_unlink("empty");  
  40.         sem_unlink("full");  
  41.         sem_unlink("mutex");  
  42.         return 0;  
  43. }  


shm.c这样写

brk是进程代码和数据总长度和未初始化的数据区bss的总长度,修改这个指针可以为进程释放和动态分配内存。

vector数组里存储的是实际地址。

[cpp] view plain copy
  1. #pragma once  
  2. #define __LIBRARY__  
  3. #include <unistd.h>  
  4. #include <linux/mm.h>  
  5. #include <linux/sched.h>  
  6. #include <asm/system.h>  
  7. #include <linux/kernel.h>  
  8. #define ENOMEM      12  
  9. #define EINVAL      22  
  10. int vector[20]={0};  
  11. int sys_shmget(key_t key, size_t size){  
  12.         int free;  
  13.         if(vector[key]!=0) return vector[key];  
  14.         else{    
  15.                 if(size > 1024*4) return -EINVAL; else;  
  16.                 if(!(free = get_free_page())) return -ENOMEM;     
  17.                 else vector[key] = free;   
  18.                 return vector[key];  
  19.         }     
  20. }  
  21.   
  22. void* sys_shmat(int shmid, const void *shmaddr){  
  23.         if(!shmid) return -EINVAL;  
  24.         put_page(shmid, current->start_code + current->brk);  
  25.         return current->brk;  
  26. }  
0 0
原创粉丝点击