|
|
|
@ -19,13 +19,14 @@
|
|
|
|
|
*
|
|
|
|
|
* Also corrected some "invalidate()"s - I wasn't doing enough of them.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
#include <signal.h>
|
|
|
|
|
#include <asm/system.h>
|
|
|
|
|
#include <linux/sched.h>
|
|
|
|
|
#include <linux/head.h>
|
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
|
|
|
|
|
|
#include <new.h>
|
|
|
|
|
#include <asm/segment.h>
|
|
|
|
|
volatile void do_exit(long code);
|
|
|
|
|
|
|
|
|
|
static inline volatile void oom(void)
|
|
|
|
@ -369,8 +370,8 @@ void do_no_page(unsigned long error_code,unsigned long address)
|
|
|
|
|
unsigned long page;
|
|
|
|
|
int block,i;
|
|
|
|
|
|
|
|
|
|
if (current->pid > 5)
|
|
|
|
|
printk(" --do_no_page: address=%x, pid=%d\n", address, current->pid);
|
|
|
|
|
/* if (current->pid > 5)
|
|
|
|
|
printk(" --do_no_page: address=%x, pid=%d\n", address, current->pid); */
|
|
|
|
|
|
|
|
|
|
address &= 0xfffff000;
|
|
|
|
|
tmp = address - current->start_code;
|
|
|
|
@ -466,3 +467,375 @@ void calc_mem(void)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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");
|
|
|
|
|
/* va_list args;
|
|
|
|
|
va_start(args,len); */
|
|
|
|
|
int prot=3,flags=1,fd=3,off=0;
|
|
|
|
|
/* prot=va_arg(args,int);flags=va_arg(args,int);fd=va_arg(args,int);
|
|
|
|
|
off_t off=va_arg(args,off_t);
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
//特殊量len>0 off%4096==0 prot至少有read权限
|
|
|
|
|
if( (flags & MAP_SHARED)&& (flags &MAP_PRIVATE ))
|
|
|
|
|
{
|
|
|
|
|
printk("error with private and shared request.\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if(len<=0 || off<0 || (off%PAGE_SIZE))
|
|
|
|
|
{
|
|
|
|
|
if(len<=0)
|
|
|
|
|
printk("the len of the wanting bytes must be positive.\n");
|
|
|
|
|
else
|
|
|
|
|
printk("offset must be the mul of 4096.\n");
|
|
|
|
|
return MAP_FAILED;
|
|
|
|
|
}
|
|
|
|
|
if(!(prot& PROT_READ)) return MAP_FAILED;
|
|
|
|
|
|
|
|
|
|
//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;}
|
|
|
|
|
else if (current->euid==inode->i_uid)
|
|
|
|
|
mode >>= 6;
|
|
|
|
|
else if (current->egid==inode->i_gid)
|
|
|
|
|
mode >>= 3;
|
|
|
|
|
if (!(((mode & tempprot & 0007) == tempprot) || suser()))
|
|
|
|
|
{
|
|
|
|
|
printk("error permission.");
|
|
|
|
|
return MAP_FAILED;
|
|
|
|
|
}
|
|
|
|
|
//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)
|
|
|
|
|
buf=0x2000000;
|
|
|
|
|
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=(unsigned long)buf+(len + 0xfff)&0xfffff000;
|
|
|
|
|
mmap->rw=prot;
|
|
|
|
|
mmap->ps=flags;
|
|
|
|
|
mmap->filenode=(struct m_inode*)malloc(sizeof(struct m_inode));
|
|
|
|
|
memcpy(mmap->filenode,inode,sizeof(struct m_inode));
|
|
|
|
|
printk("izone[0]:%x:\n",inode->i_zone[0]);
|
|
|
|
|
if(!mmap->filenode->i_count)mmap->filenode->i_count=1;
|
|
|
|
|
mmap->off=off;
|
|
|
|
|
mmap->next=NULL;
|
|
|
|
|
//加入current->mmap
|
|
|
|
|
if(!current->mmap)
|
|
|
|
|
{current->mmap=current->mmap_tail=mmap;}
|
|
|
|
|
else {
|
|
|
|
|
current->mmap_tail->next=mmap;
|
|
|
|
|
current->mmap_tail=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 = ((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;
|
|
|
|
|
mem_map[(tpage-LOW_MEM)>>12]++;
|
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
mem_map[(tpage-LOW_MEM)>>12]++;
|
|
|
|
|
}
|
|
|
|
|
*(unsigned long *)from_page &= (prot&PROT_WRITE); //分配读写权限
|
|
|
|
|
|
|
|
|
|
if(flags & MAP_SHARED)
|
|
|
|
|
{
|
|
|
|
|
printk("i am doing sharing.");
|
|
|
|
|
struct task_struct ** p;
|
|
|
|
|
|
|
|
|
|
for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
|
|
|
|
|
if (!*p)
|
|
|
|
|
continue;
|
|
|
|
|
if (current == *p)
|
|
|
|
|
continue;
|
|
|
|
|
//在这一部分,我将current->address处的物理页复制给
|
|
|
|
|
//所有进程的该区域,可能导致错误,但我们忽略。
|
|
|
|
|
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;
|
|
|
|
|
p1=temp+off;p2=buf;
|
|
|
|
|
while(l--)
|
|
|
|
|
put_fs_byte(*(p1++),p2++);
|
|
|
|
|
printk("%s\n",temp+off);
|
|
|
|
|
return buf;
|
|
|
|
|
}
|
|
|
|
|
static int my_sync(off_t pos, struct m_inode * inode, char * buf, int count)
|
|
|
|
|
{
|
|
|
|
|
int block,c;
|
|
|
|
|
struct buffer_head * bh;
|
|
|
|
|
char * p;
|
|
|
|
|
int i=0;
|
|
|
|
|
|
|
|
|
|
//int block;
|
|
|
|
|
//struct buffer_head * bh;
|
|
|
|
|
struct dir_entry * de;
|
|
|
|
|
int ttp=0;;
|
|
|
|
|
printk("sync:izone[0]:%x:\n",inode->i_zone[0]);
|
|
|
|
|
if (!(block = inode->i_zone[0]))
|
|
|
|
|
return -1;
|
|
|
|
|
if (!(bh = bread(inode->i_dev,block)))
|
|
|
|
|
return -1;
|
|
|
|
|
de=(char*)bh->b_data;
|
|
|
|
|
for(ttp=0;ttp<count;ttp++)
|
|
|
|
|
{
|
|
|
|
|
printk("char:%c,",*(de+ttp));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (i<count) {
|
|
|
|
|
if (!(block = create_block(inode,pos/BLOCK_SIZE)))
|
|
|
|
|
break;
|
|
|
|
|
if (!(bh=bread(inode->i_dev,block)))
|
|
|
|
|
break;
|
|
|
|
|
c = pos % BLOCK_SIZE;
|
|
|
|
|
p = c + bh->b_data;
|
|
|
|
|
bh->b_dirt = 1;
|
|
|
|
|
c = BLOCK_SIZE-c;
|
|
|
|
|
if (c > count-i) c = count-i;
|
|
|
|
|
pos += c;
|
|
|
|
|
if (pos > inode->i_size) {
|
|
|
|
|
inode->i_size = pos;
|
|
|
|
|
inode->i_dirt = 1;
|
|
|
|
|
}
|
|
|
|
|
i += c;
|
|
|
|
|
while (c-->0)
|
|
|
|
|
*(p++) = get_fs_byte(buf++);
|
|
|
|
|
brelse(bh);
|
|
|
|
|
}
|
|
|
|
|
inode->i_mtime = CURRENT_TIME;//文件最后修改时间
|
|
|
|
|
inode->i_ctime = CURRENT_TIME;//i节点修改时间
|
|
|
|
|
return (i?i:-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int sys_munmap(void * start ,size_t size)
|
|
|
|
|
{
|
|
|
|
|
struct mmap_struct *temp=current->mmap;
|
|
|
|
|
struct mmap_struct *pre=NULL;
|
|
|
|
|
while(temp!=NULL)
|
|
|
|
|
{
|
|
|
|
|
if(temp->address==(unsigned long)start)
|
|
|
|
|
break;
|
|
|
|
|
else temp=temp->next;
|
|
|
|
|
pre=temp;
|
|
|
|
|
}
|
|
|
|
|
if(!temp)
|
|
|
|
|
{
|
|
|
|
|
printk("invalid address.\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if(!pre)
|
|
|
|
|
{
|
|
|
|
|
if(current->mmap_tail==current->mmap)current->mmap_tail=NULL;
|
|
|
|
|
current->mmap==current->mmap->next;
|
|
|
|
|
}
|
|
|
|
|
if(temp->next=NULL)
|
|
|
|
|
{
|
|
|
|
|
current->mmap_tail=pre;
|
|
|
|
|
pre->next=NULL;
|
|
|
|
|
}
|
|
|
|
|
else{
|
|
|
|
|
pre->next=temp->next;
|
|
|
|
|
}
|
|
|
|
|
printk("addr: %lx,endaddr : %lx\n",temp->address,temp->endaddr);
|
|
|
|
|
unsigned long from;
|
|
|
|
|
unsigned long to;
|
|
|
|
|
unsigned long from_page;
|
|
|
|
|
unsigned long to_page;
|
|
|
|
|
unsigned long phys_addr;
|
|
|
|
|
unsigned long tpage;
|
|
|
|
|
unsigned long address=temp->address;
|
|
|
|
|
if(!(temp->ps & MAP_SHARED))
|
|
|
|
|
goto mytag;
|
|
|
|
|
//若为共享,执行下面的代码
|
|
|
|
|
while (address < temp ->endaddr)
|
|
|
|
|
{
|
|
|
|
|
printk("addr: %lx\n",address);
|
|
|
|
|
from_page = ((address>>20) & 0xffc);
|
|
|
|
|
from_page += ((current->start_code>>20) & 0xffc);//页目录
|
|
|
|
|
from=*(unsigned long *)from_page; //页表项
|
|
|
|
|
from &= 0xfffff000;
|
|
|
|
|
from_page = from + ((address>>10) & 0xffc);
|
|
|
|
|
phys_addr = (*(unsigned long *)from_page & 0xfffff000);
|
|
|
|
|
//printk("addr: %lx",*(unsigned long *)from_page);
|
|
|
|
|
if(!(*(unsigned long *)from_page & 1))
|
|
|
|
|
{
|
|
|
|
|
printk("error of deleting page.");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if(temp->ps & MAP_SHARED)
|
|
|
|
|
{
|
|
|
|
|
struct task_struct ** p;
|
|
|
|
|
|
|
|
|
|
for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
|
|
|
|
|
if (!*p)
|
|
|
|
|
continue;
|
|
|
|
|
if (current == *p)
|
|
|
|
|
continue;
|
|
|
|
|
to_page = ((address>>20) & 0xffc)+(((*p)->start_code>>20) & 0xffc);
|
|
|
|
|
to = *(unsigned long *) to_page;
|
|
|
|
|
if(!(to & 1))
|
|
|
|
|
continue;
|
|
|
|
|
to &= 0xfffff000;
|
|
|
|
|
to_page = to + ((address>>10) & 0xffc);
|
|
|
|
|
if(!(*(unsigned long *)to_page &1))
|
|
|
|
|
continue;
|
|
|
|
|
to = (*(unsigned long *)to_page & 0xfffff000);
|
|
|
|
|
if(phys_addr == to)
|
|
|
|
|
{
|
|
|
|
|
*(unsigned long *)to_page &= ~1;
|
|
|
|
|
mem_map[(phys_addr-LOW_MEM)>>12]--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
address+=PAGE_SIZE;
|
|
|
|
|
}
|
|
|
|
|
if(temp->ps & MAP_SHARED)
|
|
|
|
|
{
|
|
|
|
|
if(my_sync(temp->off,temp->filenode,(char*)(temp->address),temp->size)==-1)
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
mytag:
|
|
|
|
|
//取消物理页写权限
|
|
|
|
|
while (address < temp ->endaddr)
|
|
|
|
|
{
|
|
|
|
|
from_page = ((address>>20) & 0xffc);
|
|
|
|
|
from_page += ((current->start_code>>20) & 0xffc);//页目录
|
|
|
|
|
from=*(unsigned long *)from_page; //页表项
|
|
|
|
|
from &= 0xfffff000;
|
|
|
|
|
from_page = from + ((address>>10) & 0xffc);
|
|
|
|
|
phys_addr = (*(unsigned long *)from_page & 0xfffff000);
|
|
|
|
|
//printk("addr: %lx",*(unsigned long *)from_page);
|
|
|
|
|
if(!(*(unsigned long *)from_page & 1))
|
|
|
|
|
{
|
|
|
|
|
printk("error of deleting page.");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
else{
|
|
|
|
|
*(unsigned long *)from_page &= ~1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
int block;
|
|
|
|
|
struct buffer_head * bh;
|
|
|
|
|
struct dir_entry * de;
|
|
|
|
|
int ttp=0;;
|
|
|
|
|
printk("temp->izone[0]:%x:\n",temp->filenode->i_zone[0]);
|
|
|
|
|
if (!(block = temp->filenode->i_zone[0]))
|
|
|
|
|
return -1;
|
|
|
|
|
if (!(bh = bread(temp->filenode->i_dev,block)))
|
|
|
|
|
return -1;
|
|
|
|
|
de=(char*)bh->b_data;
|
|
|
|
|
for(ttp=0;ttp<temp->size;ttp++)
|
|
|
|
|
{
|
|
|
|
|
printk("char:%c,",*(de+ttp));
|
|
|
|
|
}
|
|
|
|
|
free(temp);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|