为了正常的体验网站,请在浏览器设置里面开启Javascript功能!
首页 > pintos project2 无法加载正确运行用户程序

pintos project2 无法加载正确运行用户程序

2018-03-18 8页 doc 23KB 34阅读

用户头像

is_554469

暂无简介

举报
pintos project2 无法加载正确运行用户程序pintos project2 无法加载正确运行用户程序 我的系统版本 Ubuntu 12.04 AMD64的 gcc 4.6.3的。 装了pintos 和bochs pintos project1 已经通过。27个test已经通过 现在的问题: 进入project2 后出现了用户文件加载失败。照网上的一个改法,改了后又出现page fault at c0000008. 下面先看一下是怎么遇到问题的。 我是照那个英文的官方文档做的: 1. 编译example里的文件,这是我们用的用户文件。 wyg@wyg...
pintos project2 无法加载正确运行用户程序
pintos project2 无法加载正确运行用户程序 我的系统版本 Ubuntu 12.04 AMD64的 gcc 4.6.3的。 装了pintos 和bochs pintos project1 已经通过。27个test已经通过 现在的问题: 进入project2 后出现了用户文件加载失败。照网上的一个改法,改了后又出现page fault at c0000008. 下面先看一下是怎么遇到问题的。 我是照那个英文的官方文档做的: 1. 编译example里的文件,这是我们用的用户文件。 wyg@wyg-pc:~$ cd OSstep/pintos8/src/examples/ wyg@wyg-pc:~/OSstep/pintos8/src/examples$ make 完成后如下: 我们要用的是里的echo可执行文件 2. 进入src/userprog 文件夹 3. 然后make 编译好后在当前目录下出现了build 文件夹 4. 进入build文件夹: cd build 5. 制作大小为2M的虚拟硬盘:pintos-mkdisk filesys.dsk --filesys-size=2 此时多了一个filesys.dsk,这就是虚拟硬盘了。 6. 化虚拟硬盘 pintos -f -q 出现上图说明成功。。 7. 复制echo文件到 pintos 的虚拟硬盘filesys.dsk pintos -p ../../example/echo -a echo -- -q 执行后出现: 说明成功。 8. 接下来运行用户文件 pintos run echo 为什么不是pintos run ‘echo x’呢,因为我们还未实现参数分离功能,这样会把”echo x”当成一个文件名,显然不存在”echo x”这个文件,加载,必然失败。 看似成功了,其实不然,当然也有可能成功了,如果你已经成功,那就不必做任何修改。如何验证成功与否,后面会提到。 我就在这种失败的情况下写了好久,最后发现,根本没有加载echo文件。 9. 打开src/userprog/process.c 找到start_process (void *file_name_)数 如下图修改:选中的是要新加的 然后make 再 pintos run echo 我是很不幸,出现 load user program failed-_-! 唉,program 打错了。。只是个输出提示而已。。 但已经证明的是用户程序echo根本没有加载。。。 10.于是我百度了下,原来是elf文件有问题。这个echo 是个elf文件,但是其中的入口地址是0x0000000. 而pintos 去不映射0x1000以下的内存,所以失败了。 11.找到load函数,经过调试发现是下图中的 if(validate_segment(&phdr, file))失败了, 12.所以进入validate_segment(&phdr, file)这个函数,找到问题所在了。原来是 if(phdr->p_vaddr>PGSIZE)失败了 于是我照网上据说,把if(phdr->p_vaddr<PGSIZE)改为if(phdr->p_offset<PGSIZE) 还要改load 函数中代码,如下图选中部分为新加的。 这样做是在pintos 内部改了用户程序的入口地址,以满足pintos 的要求。 这是我在网上看到的。 .我们在载入elf文件时需要做一系列检查,主要是为了确认elf文件的存储空间占用情况, 代码段入口等。这些信息一般都保存在elf文件的executable header和program header 里。在这里,我们遇到了一个小问题导致载入elf文件失败,需要载入的elf文件的header中标明, 第一个loader部分占用虚存从0x000000开始,然而pintos操作系统 默认虚存的低0x1000位 置不被映射,即不被映射,但是我们注意到,首个loader段实际用到的地址是从offset开 始的,正好是0x1000,那么函数validate_segment()的判别机制要有所修改,将 if (phdr> p_vaddr < PGSIZE)改为 if (phdr> p_offset < PGSIZE)。这样做的话可 以成功载入elf文件,不过这么做的后果是分配用户内存空间时,仍就会映射到虚存的,这是 pintos所不允许的,为了解决这个问题,我们在函数load()里做一下修改,如果我们发现读出的 mem_page==0,我们需要手动将其设置为0x1000,这样做实际上是将一个条件判断所作的工作手动 实现了,因为我们无法控制由make得到的elf文件,我们只能从load函数中做修改。 13.接下来还是make pintos run echo 又有问题:出现了page fault at 0xc0000008 14. rights violation error reading page in user context 用户程序访问了内核的页,所以出现了page fault 15我们反汇编一下用户程序echo 方法是:objdump -d ../../example/echo >echo.txt 用vi编辑器打开生成的echo.txt文件 vim echo.txt 仔细观察发现问题了: 在08048130:<_start>:中,开始两行就有问题 sub $0x1c,%esp mov 0x24(%esp),%eax 我也不知道这是干什么。 但是0x24-0x1c=8 不就是c0000008? 现在我们须要知道pintos的用户栈的范围 PHYS_BASE=0xC0000000 也就是3G 再看看pintos 源代码中设置用户栈的函数 在load()函数中有调用,如下图 找到setup_stack()函数的实现代码: 看这个函数发现,esp被设置成了PHYS_BASE (*esp=PHYS_BASE) 也就是说,用户的栈指针esp=0xc0000000 当然栈是向下扩展的,把数据压入栈只会让esp减小,不会越界访问大小PHYS_BASE的内存,可是 sub $0x1c,%esp //esp=esp-0x1c mov 0x24(%esp),%eax //把内存(esp+0x24)这个地址里的内容装入eax 这两句,先把esp 减小0x1c,又要访问esp+0x24内存位置的数据。 那esp不就是0xc0000000-0x1c+0x24=0xc0000008了,这就是在用户程序中访问了核心内存,引发了page fault at c0000008. 解决: 既然是这样,那我们在 setup_stack()函数中把esp减小8不就OK了? 看下图: 我减了0x20,只要大于8就行。 这样做会不会引发什么问题呢,我也不清楚,在此时:2013年8月25日17:26分我还不清楚,但是后续写代码中如果遇到问题再补充。 我的思考: 当代码从高优先级ring0到低优先级ring3切换时要切换栈,要复制ring0 的栈里的一部分东西到ring3的栈,此时我们这样做,可能会找不到ring0代码传给ring3代码的参数。。。 16(再次make pintos run echo 出现了system call! 这里是由于我们没有实现系统调用,而printf函数要调用 write. 这个我们要后来实现。 17. 当然,经过几天的纠结,你可能还是不相信现在就OK了,我这里有一个证明方法: 虽然目前在echo 中不能使用printf 函数; 我已经想办法证明了echo这个用户程序已经被运行了。。 证明方法:我在echo.c中加入 了 int *t=0xC0000008; *t=3;编译.....弄好,运行后:出现了 page fault at 0xC0000008,无权访问这个位置。我又改了*t=0xC0000009,运行后出现page fault at 0xC0000009;这说明了*t=3;这句运行了,也就是说 运行到了echo.c中的代码。 我还在调试的时候 在 syscall_handler() { printf("system call"); //在这句设了断点 } 在gdb中用bt指令看了调用栈,发现, 如果在echo.c中有printf 函数,的确是在 write 这个函数中执行了int 0x30. 而删除了echo.c中所有printf函数,当然echo.c中其实那个main函数已经是空的了,此时在tell 这个函数中执行了int 0x30; 原因尚未搞清楚。。不过,每个用户程序结束时都要调用exit这个函数,里面也有int 0x30..总之现在可以确定的是,用户程序(echo)已经可以被加载并且执行了。。接下来应该可以进入任务了,完成那些系统调用。。。 18.这样的用户程序和main线程是同一优先线,将被交替执行 可能出现了用户程序还没运行完而main线程先结束,这就是为什么上而的system call~ 会出现在Execution ‘echo’ complete之后。 当然这是要通过实现process_wait()函数来解决父子进程同步问题。现在我们只要把用户进程优先级改高一些,做个测试。 看到,用户进程的优先级被设为了PRI_DEFAULT+1,而main线程的优先级为PRI_DEFAULT 还是make pintos run echo 看到systmep call!已经在 Executing ‘echo’和 Execution of ‘echo’ complete. 之间了。。 -----------------2013年8月25日 今日阅读英文文档,猛然发现 3.2 Suggested Order of Implementation We suggest first implementing the following, which can happen in parallel: ? Argument passing (see Section 3.3.3 [Argument Passing], page 29). Every user program will page fault immediately until argument passing is implemented. For now, you may simply wish to change *esp = PHYS_BASE; to *esp = PHYS_BASE - 12; in setup_stack(). 真是欲哭无泪。。这么多天白折腾了。。 --------------------2013年8月26日星期一 7时56分51秒
/
本文档为【pintos project2 无法加载正确运行用户程序】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索