diff --git a/linux/mm/memory.c b/linux/mm/memory.c index e7f6a52..c6b672b 100644 --- a/linux/mm/memory.c +++ b/linux/mm/memory.c @@ -147,7 +147,7 @@ int free_page_tables(unsigned long from,unsigned long size) * 1 Mb-range, so the pages can be shared with the kernel. Thus the * special case for nr=xxxx. */ -int copy_page_tables(unsigned long from,unsigned long to,long size) +int copy_page_tables(unsigned long from,unsigned long to,long size ) { unsigned long * from_page_table; unsigned long * to_page_table; @@ -809,3 +809,160 @@ mytag: +/* + 直接让esp(子进程)指向另一个进程(当前进程)的地址; + 修改eip对应的指令,改为ret 0xec8353c3 ps:应该只有0xc3有用 + 由于eip只执行一条指令,我们将eip指向栈,将ret压入栈即可; + 在这里我们只实现了int (*fn)(void *) 一种函数类型,并且要求fn内以exit结尾 + 于是我们只需修改八字节即可; + 下面写的不对,不能指向另一个进程的地址,只能修改物理页了。 +*/ +/* int do_clone(int nr,long tmp,int (*fn)(void *), void *child_stack, int flag) +{ + //设置压栈表,方便操作; + long stack[1024]; + unsigned long len=0; + task[nr]->tss.esp=(unsigned long) child_stack - 8; + stack[0] = (unsigned long) fn; + task[nr]->tss.eip = (unsigned long) child_stack - 4; + stack[1]= 0xec8353c3; + //栈区赋值; + len = 8; + char *p1=stack ,*p2=(char *)((unsigned long)child_stack-len); + while(len--) + put_fs_byte(*(p1++),p2++); + return 0; +} */ +/* child_stack-4 00 00 00 00 */ + /* child_stack-8 00 00 00 00 */ + /* child_stack-12 arg */ + /* child_stack-16 fn */ //esp + /* child_stack-20 00 00 00 00 */ + /* child_stack-24 00 00 00 00 */ + /* child_stack-28 00 00 00 00 */ + /* child_stack-32 0x000000c3 */ +/* +int do_clone(int nr,long tmp,int (*fn)(void *), void *child_stack, int flag) +{ + void * argv =NULL; + //共享物理页:写法有缺陷,可能child——stack跨页 + //子进程task[nr]的页表项获取,目的是更新成child——stacK的物理页 + unsigned long nrfrom_page,nrfrom,from_page,from,tpage,address; + address = task[nr]->tss.esp; + nrfrom_page = ((address>>20) & 0xffc); + nrfrom_page += ((task[nr]->start_code>>20) & 0xffc);//页目录 + nrfrom=*(unsigned long *)nrfrom_page; //页表项 + if(!(nrfrom&1)) //无页表项分配一个 + { + if(!(tpage=get_free_page())) + { + printk("out of memory.\n"); + return -1; + } + else + { + *(unsigned long *)nrfrom_page= tpage | 7; + mem_map[(tpage-LOW_MEM)>>12]++; + } + } + nrfrom &= 0xfffff000; + nrfrom_page = nrfrom + ((address>>10) & 0xffc); + + //获取child_stack的物理页,并将其复制给task[nr]; + address=(unsigned long) child_stack; + 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 -1; + } + 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 -1; + } + else + { + *(unsigned long *)from_page= tpage | 7; + mem_map[(tpage-LOW_MEM)>>12]++; + } + //复制给nr + *(unsigned long *)nrfrom_page = *(unsigned long *)from_page; + unsigned long stack[128]; + unsigned long off=(unsigned long)child_stack & 0xfff; + if(off < 32) + { + printk("地址跨页,我也没办法.\n"); + return -1; + } + + //更新esp,让其指向child_stack同样偏移的地点; + //注意:这里child_stack 指向的是高地址,要向下面push. + task[nr]->tss.esp &=0xfffff000; + task[nr]->tss.esp |=off - 16; + //eip 只有一条ret //所以传进来的fn必须以exit结尾,不能return , + //因为我不会return这个玩意push ebp 又pop 啥的 + task[nr]->tss.eip &=0xfffff000; + task[nr]->tss.eip |=off - 32; + //ret eip + + stack[0]=0x000000c3; + stack[4]=(unsigned long)fn; + stack[5]=(unsigned long)argv; + char * p1=stack, *p2=(unsigned long) child_stack - 32,len=32; + while(len--) + put_fs_byte(*(p1++),p2++); + printk("nr:%d::fn:%x\n",nr,(unsigned long )fn); + return 0; +} +*/ +int copy_page_tables_clone(unsigned long from,unsigned long to,long size ) +{ + unsigned long * from_page_table; + unsigned long * to_page_table; + unsigned long this_page; + unsigned long * from_dir, * to_dir; + unsigned long nr; + + if ((from&0x3fffff) || (to&0x3fffff)) + panic("copy_page_tables called with wrong alignment"); + from_dir = (unsigned long *) ((from>>20) & 0xffc); /* _pg_dir = 0 */ + to_dir = (unsigned long *) ((to>>20) & 0xffc); + size = ((unsigned) (size+0x3fffff)) >> 22; + for( ; size-->0 ; from_dir++,to_dir++) { + if (1 & *to_dir) + panic("copy_page_tables: already exist"); + if (!(1 & *from_dir)) + continue; + from_page_table = (unsigned long *) (0xfffff000 & *from_dir); + if (!(to_page_table = (unsigned long *) get_free_page())) + return -1; /* Out of memory, see freeing */ + *to_dir = ((unsigned long) to_page_table) | 7; + nr = (from==0)?0xA0:1024; + for ( ; nr-- > 0 ; from_page_table++,to_page_table++) { + this_page = *from_page_table; + if (!(1 & this_page)) + continue; + *to_page_table = this_page; + if (this_page > LOW_MEM) { + *from_page_table = this_page; + this_page -= LOW_MEM; + this_page >>= 12; + mem_map[this_page]++; + } + } + } + invalidate(); + return 0; +} \ No newline at end of file