version 2 of mmap

master
forever-learner 2 years ago
parent 2394428ba7
commit 3e50ff7954

@ -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(address<mmap->endaddr)
{
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;
}
}

Loading…
Cancel
Save