做这个实验大致上消耗了我三天时间,本来我是想在10月10号之前搞完的,但最终还是消耗到了现在,搞计算机行业或许真的要有一颗强大的心理。不然你真的回被各种各样的bug给搞麻来。从前天开始我就不停的在调试修改的过程中,而且由于自己不太明白如何在linux-0.11上利用gdb调试,以至于我只能不停的利用增加printf来试这样的方式来调试,其调试过程无疑是十分痛苦的。但好歹是走到了这一步,只剩下最后两个实验了,希望自己能够在10月15号之前搞完吧。
声明这个实验严格意义上来说其实我并不算做出来了,因为实验要求的是要自己建立两个进程,分别为生产者进程和消费者进程,然后通过其进程之间共享内存来实现进程通信。然而,我也没想到原来我的前一个实验有问题,以至于如果分成两个进程的话会导致失败,在尝试了多种方法无果后,我只能选择利用在一个进程中利用fork()形成父子进程来做,也就是前一个实验那种情况。
实验对于这个实验,其实相比于前两个实验来说,我觉得反而更加简单,把蓝桥实验楼上的实验册看一下,对地址映射有个较为全面的认识,然后自己再看看相关系统调用以及参考参考博客就差不多了,其中特别要注意逻辑地址,虚拟地址,线性地址,物理地址的概念。
就我自己理解来看,逻辑地址就是段偏移量,指的是对于段头的相对位置,虚拟地址就是段标识符:段偏移量,其中段标识符通过gdt表或者ldt表找到段描述符,而在段描述符中就存储着段基址,也就是线性地址的段基址,其中段基址加上偏移量就是线性地址。之后再通过线性地址映射到物理地址上,物理地址也就是数据存储的真实地址。
这个实验还有一个难点就是空闲虚拟地址的寻找,就此实验楼给了提示,在linux内核注释那本书上的13-6图上说明了程序虚拟内存情况。
如果自己能够在细心一点的话,就能够发现在pcb中就存储着这些信息。
shm.c
#include#include typedef struct{ int key; unsigned long addr; }shm_t; typedef int key_t; shm_t shm[20]; int flag; void __init__(){ int i; for(i=0;i<20;i++){ shm[i].key=0; } } int sys_shmget(key_t key,size_t size,int shmflag){ if(!flag){ __init__(); flag=1; } if(size>4096){ errno=EINVAL; return -1; } int i,shmid=-1; for(i=0;i<20;++i){ if(shm[i].key==key)return i; } unsigned long addr_t=get_free_page(); if(!addr_t){ errno=ENOMEM; return -1; } for(i=0;i<20;++i){ if(!shm[i].key){ shm[i].key=key; shm[i].addr=addr_t; shmid=i; break; } } return shmid; } void* sys_shmat(int shmid,const void*shmaddr,int shmflag){ if(shmid<0){ errno=EINVAL; return -1; } unsigned long logic_addr=current->start_code+current->brk; int ret=put_page(shm[shmid].addr,logic_addr); if(!ret){ //printk("errorn"); errno=EINVAL; return -1; } return current->brk; }
test_pc
//由于上个实验有问题,其信号量必须要全局,故只能如此 #define __LIBRARY__ #include#include #include #include #include #include #include #include #define ALLNUM 750 #define CUSTOMERNUM 5 #define BUFFERSIZE 10 typedef int key_t; _syscall1(int,sem_wait,sem_t*,sem); _syscall1(int,sem_post,sem_t*,sem); _syscall1(int,sem_unlink,const char*,name); _syscall2(sem_t*,sem_open,const char*,name,unsigned int,value); _syscall3(int,shmget,key_t,key,size_t,size,int,shmflg); _syscall3(void*,shmat,int,shmid,const void*,shmaddr,int,shmflg); void Producer(); void Consumer(); int InPos=0; int OutPos=0; sem_t *empty,*full,*mutex; int main(int argc, char **argv) { pid_t pid; empty=sem_open("empty",10); full=sem_open("full",0); mutex=sem_open("mutex",1); pid=fork(); if(pid!=0) { Producer(); } else { Consumer(); } wait(NULL); wait(NULL); sem_unlink("empty"); sem_unlink("full"); sem_unlink("mutex"); return 0; } void Producer() { int i=0; int shmid; void *shm=NULL; int *shared; int ans; shmid=shmget((key_t)1234,sizeof(int)*BUFFERSIZE,0); if(shmid==-1){ fprintf(stderr,"shmat failed 4n"); exit(0); } shm=shmat(shmid,0,0); if(shm==(void*)-1){ fprintf(stderr,"shmat failed 5n"); exit(0); } shared=(int*)shm; for(i=0;i 结果
下一实验再见~



