linux/mm/memory.c/put_page

// put_page用来完成物理页面与一个线性地址页面的挂接,从而将一个
// 线性地址空间内的页面落实到物理地址空间内,copy_page_tables函数
// 只是为一个进程提供了在线性地址空间的一个页表及1024页内存,而当时
// 并未将其对应的物理内存上。put_page函数则负责为copy_page_tables开
// 的“空头支票”买单。
// page为物理地址,address为线性地址
unsigned long put_page(unsigned long page,unsigned long address)
{
unsigned long tmp, *page_table;


/* NOTE !!! This uses the fact that _pg_dir=0 */


// 要映射的线性地址只能在主内存区,你不能给内存起始1M范围内映射线性地址
// 因为LOW_MEM内是给内核用的,且不属于分页内存范围。
if (page < LOW_MEM || page >= HIGH_MEMORY)
printk("Trying to put page %p at %p\n",page,address);
// (page-LOW_MEM)>>12得到page这个物理地址对应的页号
// mem_map[(page-LOW_MEM)>>12] !=1是检查这个page地址对应的物理内存页面
// 是不是已经注册过的页面(用get_free_page函数申请,申请时会再mem_map中
// 注册这个页面,也就是把这个页面对应的mem_map项加1。所以此处==1就代表
// 这个物理页面是刚申请好备用的,只有这种物理页面才能被映射到一个线性地
// 址。所以这里!=1就要警告)
if (mem_map[(page-LOW_MEM)>>12] != 1)
printk("mem_map disagrees with %p at %p\n",page,address);
// page_table得到address线性地址页面在页目录表中对应表项的首地址指针,这个
// 指针用来得到页表基地址,然后寻址就进行到了页表级。再配合address的次10位
// 就能寻址到address对应的内存页面基地址了。最后12bit用来在页面内寻址。
page_table = (unsigned long *) ((address>>20) & 0xffc);
// 检验address对应的页目录表项内容,即页表地址是不是有效地,若页表有效,则
// 直接把页表地址给page_table;若页表无效,则调用get_free_page函数在mem_map
// 数组内申请一个空闲页面,并将这个空闲页面设置为用户级、只读、存在,再将
// 新申请并处理好的页面地址赋值给page_table
if ((*page_table)&1)
page_table = (unsigned long *) (0xfffff000 & *page_table);
else {
if (!(tmp=get_free_page()))
return 0;
*page_table = tmp|7;
page_table = (unsigned long *) tmp;
}
// 上面已经得到了一个有效地page_table了,现在就要将page这个物理页面和address
// 这个线性地址处的页面挂接起来了。挂接的方法就是在page_table中,将address对应
// 的页表项中的内容(即address这个地址所在的页面基地址)设置为page这个物理地址
// |7没什么好说的,这里值得关注的是page_table竟然还可以当做数组来用···刚开始
// 着实吃了一惊,不过仔细想想page_table本来就是个指针,而1024个页表项也和数组
// 结构一样的,用数组的方式来访问也是可行的(当然我还是觉得用指针+偏移量更好理解)
// 再次感叹C语言的灵活啊
// 再说明下(address>>12)&0x3ff吧,毕竟自己没看出来,还是看了赵炯博士的注释才发现
// 的。这个操作实际是取出address次10位表示页面在页表内的偏移值。这样用这个偏移值
// 结合page_table这个页表首地址,就能找到address所在的页面基地址了。
page_table[(address>>12) & 0x3ff] = page | 7;
/* no need for invalidate */
return page;
}
这个错误是由于文件路径中包含空格而导致的。为了解决这个错误,你需要在文件路径中的包含空格的地方添加双引号。例如,将 "C:/Program Files/Xilinx/verilog/src/glbl.v" 改为 "C:/Program Files/Xilinx/verilog/src/glbl.v"。\[1\] 另外,你提到了一个关于使用ModelSim进行仿真时出现的错误。这个错误是由于在do文件中指定的设计单元文件路径中包含了空格,导致无法以读取模式打开文件。为了解决这个问题,你需要在文件路径中的包含空格的地方添加双引号。例如,将 "D:/diamond" 改为 "D:/diamond projects/cpu_if/src/cpu_if.v"。\[3\] 至于你提到的另一个错误,"Error: (vlog-7) Failed to open design unit file "C:/Xilinx/Vivado/2018.3/data/ip/xpm/xpm_memory/hdl/xpm_memory.sv" in read mode.",这个错误是由于无法以读取模式打开指定的设计单元文件。可能的原因是文件路径不正确或文件不存在。请确保文件路径正确,并检查文件是否存在。如果文件存在并且路径正确,那么可能是文件权限或其他问题导致无法打开文件。你可以尝试更改文件权限或使用其他方法来打开文件。 #### 引用[.reference_title] - *1* [Failed to open design unit file "%XILINX%/verilog/src/glbl.v](https://blog.csdn.net/alan5555/article/details/9378009)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [modelsim10.4仿真错误Error: (vlog-7) Failed to open design unit file "XXXXX" in read mode解决办法](https://blog.csdn.net/llf021421/article/details/79181118)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

朱有鹏老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值