当前位置: 首页 > wzjs >正文

广州做外贸网站多少钱大都会app最新版本下载

广州做外贸网站多少钱,大都会app最新版本下载,丈哥seo博客,动态和静态网站的区别TOC 实验内容 背景: 在 xv6 中,fork()系统调用会将父进程的所有用户空间内存复制到子进程中。如果父进程很大,复制操作可能会花费很长时间。在子进程中,fork()通常会紧接着 exec(),这会丢弃复制的内存,通…

TOC

实验内容

  • 背景:
    • 在 xv6 中,fork()系统调用会将父进程的所有用户空间内存复制到子进程中。如果父进程很大,复制操作可能会花费很长时间。
    • 在子进程中,fork()通常会紧接着 exec(),这会丢弃复制的内存,通常不会使用大部分内存。
  • 解决方案:
    • 延迟分配
    • 写时复制
    • COW fork() 为子进程创建一个页表,用户内存的 PTE 指向父进程的物理页。COW fork() 将父进程和子进程中的所有用户 PTE 标记为只读。当任一进程尝试写入这些 COW 页面时,CPU 将引发页面故障。内核页面故障处理程序检测到这种情况,为故障进程分配一页物理内存,将原始页面复制到新页面,并在故障进程的相关 PTE 中修改为指向新页面,这次 PTE 标记为可写。当页面故障处理程序返回时,用户进程将能够写入其页面的副本。
  • 具体任务
    • 在 xv6 内核中实现copy-on-write fork。如果你修改后的内核能够成功执行 cowtest和usertests -q程序,那么你就完成了任务。

实现逻辑

在这里插入图片描述

修改内容

  • kernel/riscv.h中添加PTE_COW标志位
#define PTE_COW (1L << 8) //自定义COW标志位 lab5
  • kernel/kalloc.c添加页映射计数数组、相关函数(修改时使用锁)
// lab5
struct {struct spinlock lock;    // 引用计数专用锁int count[(PHYSTOP - KERNBASE) / PGSIZE];  // 引用计数数组
}kref;
// 增加引用计数
void kref_incr(uint64 pa) {acquire(&kref.lock);int idx = (pa - KERNBASE) / PGSIZE;kref.count[idx]++;release(&kref.lock);
}
// 减少引用计数
void kref_decr(uint64 pa) {int idx = (pa - KERNBASE) / PGSIZE;acquire(&kref.lock);if (kref.count[idx] <= 0) panic("kref_decr: invalid refcount");kref.count[idx]--;release(&kref.lock);
}
// 查询引用次数
int kref_count(uint64 pa) {acquire(&kref.lock);int idx = (pa - KERNBASE) / PGSIZE;release(&kref.lock);return kref.count[idx];
}
  • kernel/kalloc.c中修改初始化、分配页和释放页函数
void
kinit()
{// lab5 初始化计数数组for (int i = 0; i < (PHYSTOP - KERNBASE) / PGSIZE; i++) kref.count[i] = 0;initlock(&kref.lock, "kref");initlock(&kmem.lock, "kmem");freerange(end, (void*)PHYSTOP);
}void
kfree(void *pa)
{struct run *r;if(((uint64)pa % PGSIZE) != 0 || (char*)pa < end || (uint64)pa >= PHYSTOP)panic("kfree");// lab5acquire(&kmem.lock);if ( kref_count((uint64)pa) > 1) {kref_decr((uint64)pa);  // 引用计数减 1release(&kmem.lock);return;}acquire(&kref.lock);kref.count[((uint64)pa - KERNBASE) / PGSIZE] = 0;  // 清零后释放  release(&kref.lock);// Fill with junk to catch dangling refs.memset(pa, 1, PGSIZE);r = (struct run*)pa;// acquire(&kmem.lock); 去掉这个重复锁r->next = kmem.freelist;kmem.freelist = r;release(&kmem.lock);
}void *
kalloc(void)
{struct run *r;acquire(&kmem.lock);r = kmem.freelist;if(r){kmem.freelist = r->next;// lab5acquire(&kref.lock);kref.count[((uint64)r - KERNBASE) / PGSIZE] = 1;  // 初始化为 1    release(&kref.lock);}release(&kmem.lock);if(r)memset((char*)r, 5, PGSIZE); // fill with junkreturn (void*)r;
}
 - 只有当页的映射数为1时才能释放- 分配页时增加数组计数
  • kernel/vm.c中添加写时分配的实现形式
int cow_alloc(pagetable_t pagetable, uint64 va) {va = PGROUNDDOWN(va);  // 对齐到页边界// 检查va大小,在walk之前,否则无法应对恶意输入地址if(va >= MAXVA)return -1;pte_t *pte = walk(pagetable, va, 0);if (!pte || !(*pte & PTE_V) || !(*pte & PTE_COW)) {return -1;  // 非法地址或非 COW 页}uint64 pa = PTE2PA(*pte);  // 原物理地址// 如果引用计数为 1,直接恢复写权限if (kref_count(pa) == 1) {  *pte |= PTE_W;*pte &= ~PTE_COW;sfence_vma(); // 刷新 TLBreturn 0;}// 分配新页并复制数据char *new_pa = kalloc();if (!new_pa) return -1;  // 内存不足memmove(new_pa, (char*)pa, PGSIZE);  // 复制原页内容// 更新页表项:新页可写,清除 COW 标志uint64 flags = (PTE_FLAGS(*pte) | PTE_W ) & ~PTE_COW;*pte = PA2PTE(new_pa) | flags;kfree((void*)pa);  // 减少原页的引用计数sfence_vma(); // 刷新 TLBreturn 0;
}
  • kernel/vm.c中的修改
int
uvmcopy(pagetable_t old, pagetable_t new, uint64 sz)
{pte_t *pte;uint64 pa, i;uint flags;for(i = 0; i < sz; i += PGSIZE){if((pte = walk(old, i, 0)) == 0)panic("uvmcopy: pte should exist");if((*pte & PTE_V) == 0)panic("uvmcopy: page not present");// lab5 只考虑可写页面标记cow,否则会使不可写的页在cow处理后变为可写!if(*pte & ~PTE_W){*pte = (*pte & ~PTE_W) | PTE_COW; // 清除父进程的写权限,标记为 COW 页}pa = PTE2PA(*pte); // 获取物理地址flags = PTE_FLAGS(*pte);kref_incr(pa); //增加引用计数// 子进程页表继承只读 + COW 标志,映射到同一物理页if(mappages(new, i, PGSIZE, (uint64)pa, flags) != 0){kref_decr(pa);goto err;}    }return 0;err:uvmunmap(new, 0, i / PGSIZE, 1);return -1;
}int
copyout(pagetable_t pagetable, uint64 dstva, char *src, uint64 len)
{uint64 n, va0, pa0;pte_t *pte;while(len > 0){va0 = PGROUNDDOWN(dstva);if(va0 >= MAXVA)return -1;pte = walk(pagetable, va0, 0);// lab5去掉pte_w检查,进行常规检查if(pte == 0 || (*pte & PTE_V) == 0 || (*pte & PTE_U) == 0 ) return -1;// 禁止写入代码页(PTE_X)if (*pte & PTE_X) {return -1;}// lab5 if(*pte & PTE_COW){// cow页uint64 pa = PTE2PA(*pte); // 对应的物理页地址if(kref_count(pa) > 1){// 该物理页被多次映射,需重新分配if( cow_alloc(pagetable, va0) < 0 ){return -1;}// 获取新的ptepte = walk(pagetable, va0, 0);if( pte == 0 || (*pte & PTE_V) == 0 || (*pte & PTE_U) == 0 || (*pte & PTE_W) == 0){return -1;}sfence_vma(); // 刷新TLB}else{// 该物理页只有一次映射*pte |= PTE_W;*pte &= ~PTE_COW;sfence_vma(); // 刷新TLB}} else {// 非 COW 页:检查是否可写if ((*pte & PTE_W) == 0) {return -1; // 目标页不可写,返回错误}}pa0 = PTE2PA(*pte);n = PGSIZE - (dstva - va0);if(n > len)n = len;memmove((void *)(pa0 + (dstva - va0)), src, n);len -= n;src += n;dstva = va0 + PGSIZE;}return 0;
}
  • kernel/trap.c中添加陷入处理
void
usertrap(void)
{int which_dev = 0;if((r_sstatus() & SSTATUS_SPP) != 0)panic("usertrap: not from user mode");// send interrupts and exceptions to kerneltrap(),// since we're now in the kernel.w_stvec((uint64)kernelvec);struct proc *p = myproc();// save user program counter.p->trapframe->epc = r_sepc();if(r_scause() == 8){// system callif(killed(p))exit(-1);// sepc points to the ecall instruction,// but we want to return to the next instruction.p->trapframe->epc += 4;// an interrupt will change sepc, scause, and sstatus,// so enable only now that we're done with those registers.intr_on();syscall();} else if( r_scause() == 15 ){ //lab5 页写入错误 // 写时错误uint64 va = r_stval();         // 获取触发错误的虚拟地址// 检查虚拟地址是否合法(在用户地址空间内)if (va >= p->sz || va < PGSIZE) {printf("usertrap: invalid va %p\n", va);setkilled(p);}// 处理 COW 错误(分配新页并更新页表)if (cow_alloc(p->pagetable, va) < 0) {   // 调用 COW 处理函数printf("usertrap: cow_alloc failed\n");setkilled(p);}} else if((which_dev = devintr()) != 0){// ok} else {printf("usertrap(): unexpected scause %p pid=%d\n", r_scause(), p->pid);printf("            sepc=%p stval=%p\n", r_sepc(), r_stval());setkilled(p);}if(killed(p))exit(-1);// give up the CPU if this is a timer interrupt.if(which_dev == 2)yield();usertrapret();
}

测试结果

$cowtest
simple: ok
simple: ok
three: ok
three: ok
three: ok
file: ok
ALL COW TESTS PASSED
$usertests -q
...
test sbrklast: OK
test sbrk8000: OK
test badarg: OK
ALL TESTS PASSED

文章转载自:

http://oB7R0TZA.jzmqk.cn
http://DX1Eveay.jzmqk.cn
http://lCnP3oaT.jzmqk.cn
http://KNjtOxXN.jzmqk.cn
http://YG6xOse0.jzmqk.cn
http://PD4BRDv1.jzmqk.cn
http://REjUSKHb.jzmqk.cn
http://7eSNGDIU.jzmqk.cn
http://HuMSyt7E.jzmqk.cn
http://95VO7hZO.jzmqk.cn
http://mvOwriNO.jzmqk.cn
http://uzZ0z13j.jzmqk.cn
http://xu6pKiza.jzmqk.cn
http://VDb9Tzsu.jzmqk.cn
http://7EzAnOwM.jzmqk.cn
http://e9OqSR38.jzmqk.cn
http://l5wL7dtG.jzmqk.cn
http://W2PLaydq.jzmqk.cn
http://tGIOXHlB.jzmqk.cn
http://kDHOzDmw.jzmqk.cn
http://JFlk0WVP.jzmqk.cn
http://k41YK1Eq.jzmqk.cn
http://da3L8qMN.jzmqk.cn
http://rZfjaPyS.jzmqk.cn
http://s7z8gMn3.jzmqk.cn
http://7ujqA6hN.jzmqk.cn
http://sK3KeZfe.jzmqk.cn
http://W6hzfdvv.jzmqk.cn
http://9FkukYph.jzmqk.cn
http://NnqmJyGP.jzmqk.cn
http://www.dtcms.com/wzjs/687975.html

相关文章:

  • 做版面的网站一个简单的html网页
  • 性能网站建设子网站怎么建设
  • 网站收录突然全部没有了做资金盘网站
  • 网站开发的技术类型有哪些公众平台安全助手
  • 宁德网站开发公司在线文字编辑器
  • 电商网站wordpress在建设局网站备案怎么弄
  • 常州自助建站中国建设人才平台网站
  • 网站怎么做文件上传西安seo网站设计公司
  • iis网站重定向设置网站服务器配置要求
  • wordpress汽配网站医疗网站建设方案
  • 有没有做语文题的网站扫wordpress漏洞工具
  • asp网站开发后如何交付信息设计网站
  • 医学关键词 是哪个网站做国际贸易网登录
  • 做企业门户网站都高新区网站建设
  • 湖南网站建设网络公司鹤壁市城乡一体化示范区
  • 网站开发任务清单一个vps可以建多少网站
  • 自己做网站能做付费链接吗wordpress月会员
  • 怎么把百度地图放到网站上wordpress用户注册插件
  • 哪里购买网站广告位WordPress主题启用出现错误
  • 鞍山网站开发公司杭州建设工程招标平台官网
  • 社保网站做员工用工备案因网站建设关闭的公告
  • 哈尔滨网站设计有哪些步骤军队网站建设方案
  • 网站访问速度慢的原因seo优化网站技术排名百度推广
  • 网站微商城的建设运营实践和思考无忧ppt模板下载 免费
  • 优秀的个人博客网站正规软件开发培训机构
  • 莆田联客易外贸网站建设推广网站被k
  • 用wordpress建站的好处5118站长平台
  • 昌宁网站建设wordpress电影主题会员
  • 注册域名后网站建设网课编程
  • 做 视频在线观看网站wordpress源码整合