From 3e50ff795448c8ac427b41d10dab7c22a0ca5fb7 Mon Sep 17 00:00:00 2001 From: forever-learner <2360561713@qq.com> Date: Thu, 30 Jun 2022 10:58:28 +0800 Subject: [PATCH] version 2 of mmap --- linux/kernel/sys.c | 124 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 112 insertions(+), 12 deletions(-) diff --git a/linux/kernel/sys.c b/linux/kernel/sys.c index 3a7a7b0..8b4d8d1 100644 --- a/linux/kernel/sys.c +++ b/linux/kernel/sys.c @@ -463,7 +463,42 @@ int sys_umask(int mask) return (old); } +static int my_share(unsigned long address, struct task_struct * p) +{ + unsigned long from; + unsigned long to; + unsigned long from_page; + unsigned long to_page; + unsigned long phys_addr; + + from_page = to_page = ((address>>20) & 0xffc); + from_page += ((current->start_code>>20) & 0xffc); + to_page += ((p->start_code>>20) & 0xffc); + + from = *(unsigned long *) from_page; + from &= 0xfffff000; + from_page = from + ((address>>10) & 0xffc); + phys_addr = *(unsigned long *) from_page; + to = *(unsigned long *) to_page; + if (!(to & 1)) + if (to = get_free_page()) + *(unsigned long *) to_page = to | 7; + else + return 0; + to &= 0xfffff000; + to_page = to + ((address>>10) & 0xffc); + if (1 & *(unsigned long *) to_page) + return 0; + /* share them: write-protect */ + *(unsigned long *) to_page = *(unsigned long *) from_page; + phys_addr -= LOW_MEM; + phys_addr >>= 12; + mem_map[phys_addr]++; + return 1; +} + // rememeber to sync when munmap exit manual + long sys_mmap(void * start,size_t len,...)// int prot,int flags,int fd,off_t off { printk("start mmaping\n"); @@ -475,27 +510,37 @@ long sys_mmap(void * start,size_t len,...)// int prot,int flags,int fd,off_t off int *ll=&len;printk("%d,%d,%d,%d,%d\n",*ll,*(ll+1),*(ll+2),*(ll+3),*(ll+4)); va_end(args); printk("%d,%d,%d,%ld\n",prot,flags,fd,off); */ + int block; size_t l=len; struct buffer_head * bh; char *temp,*p1,*p2; void * buf=start; int tempprot=0; + //因为new.h和namei.c定义不一样,要修改 if(prot &PROT_READ) tempprot |=4; if(prot &PROT_EXEC) tempprot |=1; if(prot &PROT_WRITE) tempprot |=2; - //特殊量 - if(!len || off<0 || (off%PAGE_SIZE)) return MAP_FAILED; + + //特殊量len>0 off%4096==0 prot至少有read权限 + if(len<=0 || off<0 || (off%PAGE_SIZE)) + { + if(len<=0) + printk("the len of the wanting bytes must be positive"); + else + printk("offset must be the mul of 4096"); + return MAP_FAILED; + } if(!(prot& PROT_READ)) return MAP_FAILED; - //permissions of the file - printk("end of permissions0\n"); + + //permissions of the file ,搬运函数namei.c::permissions printk("fd: %d\n",fd); struct m_inode *inode=current->filp[fd]->f_inode; printk("end of permissions\n"); int mode = inode->i_mode; if (inode->i_dev && !inode->i_nlinks) - {printk("end of permissions1\n");;return MAP_FAILED;} + {printk("end of permissions1\n");return MAP_FAILED;} else if (current->euid==inode->i_uid) mode >>= 6; else if (current->egid==inode->i_gid) @@ -507,6 +552,9 @@ long sys_mmap(void * start,size_t len,...)// int prot,int flags,int fd,off_t off } //end of permission check printk("end of permissions\n"); + + //设置用户空间的虚拟地址,初始为32MB处,这样写在brk增长至32MB时会有bug,我们忽略 + //同时,当栈向下增长到一定程度时,也会和当前地址冲突,我们忽略 if(start<=current->brk || start>=current->start_stack-0x8000 || start==NULL) { if(!current->mmap_tail) @@ -514,24 +562,76 @@ long sys_mmap(void * start,size_t len,...)// int prot,int flags,int fd,off_t off else buf=current->mmap_tail->endaddr; } + //申请mmap struct mmap_struct *mmap=(struct mmap_struct *)malloc(sizeof(struct mmap_struct)); - mmap->address=buf;mmap->size=len; - mmap->endaddr=buf+(len + 0xfff)&0xfffff000; - mmap->rw=prot;mmap->ps=flags; + mmap->address=buf; + mmap->size=len; + mmap->endaddr=(unsigned long)buf+(len + 0xfff)&0xfffff000; + mmap->rw=prot; + mmap->ps=flags; mmap->next=NULL; + //加入current->mmap if(!current->mmap) - {current->mmap=current->mapp_tail=mapp;} + {current->mmap=current->mmap_tail=mmap;} else - current->mmap_tail->next=mapp; + current->mmap_tail->next=mmap; printk("buf: %x\n",(unsigned long )buf); + //分配物理页 + + unsigned long from; + unsigned long to; + unsigned long from_page; + unsigned long to_page; + unsigned long phys_addr; + unsigned long tpage; + unsigned long address=mmap->address; + while(addressendaddr) + { + from_page = ((mmap->address>>20) & 0xffc); + from_page += ((current->start_code>>20) & 0xffc);//页目录 + if(!(*(unsigned long *)from_page&1)) //页表项不存在,申请页面 + if(!(tpage=get_free_page())) + { + printk("out of memory.\n"); + return MAP_FAILED; + } + else + *(unsigned long *)from_page= tpage | 7; + from=*(unsigned long *)from_page; //页表项 + from &= 0xfffff000; + from_page = from + ((address>>10) & 0xffc); + if(!(*(unsigned long *)from_page & 1)) //物理页不存在 + if(!(tpage=get_free_page())) + { + printk("out of memory.\n"); + return MAP_FAILED; + } + else + *(unsigned long *)from_page= tpage | 7; + *(unsigned long *)from_page &= (prot&PROT_WRITE); //分配读写权限 + if(flags & MAP_SHARED) + { + struct task_struct ** p; + + for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) { + if (!*p) + continue; + if (current == *p) + continue; + if(!my_share(address,*p)) + printk("share failed at task:pid=%d",(*p)->pid); + } + } + address+=PAGE_SIZE; + } + //read and put in if (!(block = inode->i_zone[0])) return NULL; if (!(bh = bread(inode->i_dev,block))) return NULL; temp = (char *) bh->b_data; - printk("end of mmap\n"); p1=temp;p2=buf; while(l--) put_fs_byte(*(p1++),p2++); @@ -542,4 +642,4 @@ int sys_munmap() { return -1; -} \ No newline at end of file +}