linux copy on write源码分析(基于linux0.11)

2024-03-27 21:38

本文主要是介绍linux copy on write源码分析(基于linux0.11),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

写时复制是有一块内存,由多个进程共享,属性是只读的,当有一个进程对这块内存进行写的时候,系统会先申请一块新的内存给他写。比如进程fork的时候,父子进程对应的物理地址都一样,这时候会在页表项中记录该物理地址是只读的,有一个进程写的时候,就会触发写保护异常。执行写时复制。

在触发写保护异常的时候,处理器会给系统提供两个信息。一个在系统栈中的错误码,一个在cr2寄存器中保存的引起异常的线性地址。错误码一般会告诉系统这些信息。

——P 标志表明异常是由于一个不存在页(0)还是访问权限违例或是使用了保留位(1)。
——W/R 标志表明引起异常的内存访问是读(0)还是写(1)。
——U/S 标志表明异常发生时处理器是在用户态(1)执行还是在管理态(0)执行。

下面我们分析这个过程,首先,在系统初始化的时候,注册了14号中断异常处理程序为page_fault。

// 缺页和写保护异常处理函数
set_trap_gate(14,&page_fault)

page_fault是汇编实现的

_page_fault:// 交换两个寄存器的值,esp指向的位置保存了错误码xchgl %eax,(%esp)// 压栈寄存器pushl %ecxpushl %edxpush %dspush %espush %fs// 内核数据段描述符movl $0x10,%edxmov %dx,%dsmov %dx,%esmov %dx,%fs// 如果是缺页异常,cr2保存了引起缺页的线性地址movl %cr2,%edx// 线性地址(有的话)和错误码入参pushl %edxpushl %eax// 1和eax与,结果放到ZF中testl $1,%eax// zf=0则跳转,即0是写异常,1是缺页异常jne 1fcall _do_no_page// 跳到标签2jmp 2f
1:	call _do_wp_page
// 出栈,返回中断,会重新执行异常指令
2:	addl $8,%esppop %fspop %espop %dspopl %edxpopl %ecxpopl %eaxire

处理程序是do_wp_page

/** This routine handles present pages, when users try to write* to a shared page. It is done by copying the page to a new address* and decrementing the shared-page counter for the old page.** If it's in code space we exit with a segment error.*/void do_wp_page(unsigned long error_code,unsigned long address)
{
#if 0
/* we cannot do this yet: the estdio library writes to code space */
/* stupid, stupid. I really want the libc.a from GNU */if (CODE_SPACE(address))do_exit(SIGSEGV);
#endif/*address为线性地址,address>>10 = address>>12<<2,得到页表项的地址,address>>20 = address>>22<<2,得到页目录项地址,页目录项里存着页表地址+页表偏移得到页表项地址*/un_wp_page((unsigned long *)(((address>>10) & 0xffc) + (0xfffff000 &*((unsigned long *) ((address>>20) &0xffc)))));}
// 共享的页面被写入的时候会执行该函数。该函数申请新的一页物理地址,解除共享状态
void un_wp_page(unsigned long * table_entry)
{unsigned long old_page,new_page;// table_entry是页表项地址,算出该页的物理首地址old_page = 0xfffff000 & *table_entry;// LOW_MEM以下是内核使用的内存。old_page对应的物理页引用数为1,可以直接修改内容,置可写标记位(第二位)if (old_page >= LOW_MEM && mem_map[MAP_NR(old_page)]==1) {*table_entry |= 2;invalidate();return;}// 分配一个新的物理页if (!(new_page=get_free_page()))oom();// 页的引用数减一,因为有一个进程不使用这块内存了if (old_page >= LOW_MEM)mem_map[MAP_NR(old_page)]--;// 修改页表项的内容,使其指向新分配的内存页,置用户级、有效、可读写、可执行标记位*table_entry = new_page | 7;// 刷新tlbinvalidate();// 把数据赋值到新分配的页上copy_page(old_page,new_page);
}
// 把一页的内容从from复制到to
#define copy_page(from,to) \
__asm__("cld ; rep ; movsl"::"S" (from),"D" (to),"c" (1024):"cx","di","si")

这篇关于linux copy on write源码分析(基于linux0.11)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/853467

相关文章

SpringBoot中六种批量更新Mysql的方式效率对比分析

《SpringBoot中六种批量更新Mysql的方式效率对比分析》文章比较了MySQL大数据量批量更新的多种方法,指出REPLACEINTO和ONDUPLICATEKEY效率最高但存在数据风险,MyB... 目录效率比较测试结构数据库初始化测试数据批量修改方案第一种 for第二种 case when第三种

解决1093 - You can‘t specify target table报错问题及原因分析

《解决1093-Youcan‘tspecifytargettable报错问题及原因分析》MySQL1093错误因UPDATE/DELETE语句的FROM子句直接引用目标表或嵌套子查询导致,... 目录报js错原因分析具体原因解决办法方法一:使用临时表方法二:使用JOIN方法三:使用EXISTS示例总结报错原

Linux进程CPU绑定优化与实践过程

《Linux进程CPU绑定优化与实践过程》Linux支持进程绑定至特定CPU核心,通过sched_setaffinity系统调用和taskset工具实现,优化缓存效率与上下文切换,提升多核计算性能,适... 目录1. 多核处理器及并行计算概念1.1 多核处理器架构概述1.2 并行计算的含义及重要性1.3 并

Linux线程之线程的创建、属性、回收、退出、取消方式

《Linux线程之线程的创建、属性、回收、退出、取消方式》文章总结了线程管理核心知识:线程号唯一、创建方式、属性设置(如分离状态与栈大小)、回收机制(join/detach)、退出方法(返回/pthr... 目录1. 线程号2. 线程的创建3. 线程属性4. 线程的回收5. 线程的退出6. 线程的取消7.

Linux下进程的CPU配置与线程绑定过程

《Linux下进程的CPU配置与线程绑定过程》本文介绍Linux系统中基于进程和线程的CPU配置方法,通过taskset命令和pthread库调整亲和力,将进程/线程绑定到特定CPU核心以优化资源分配... 目录1 基于进程的CPU配置1.1 对CPU亲和力的配置1.2 绑定进程到指定CPU核上运行2 基于

golang程序打包成脚本部署到Linux系统方式

《golang程序打包成脚本部署到Linux系统方式》Golang程序通过本地编译(设置GOOS为linux生成无后缀二进制文件),上传至Linux服务器后赋权执行,使用nohup命令实现后台运行,完... 目录本地编译golang程序上传Golang二进制文件到linux服务器总结本地编译Golang程序

Linux下删除乱码文件和目录的实现方式

《Linux下删除乱码文件和目录的实现方式》:本文主要介绍Linux下删除乱码文件和目录的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux下删除乱码文件和目录方法1方法2总结Linux下删除乱码文件和目录方法1使用ls -i命令找到文件或目录

MySQL中的LENGTH()函数用法详解与实例分析

《MySQL中的LENGTH()函数用法详解与实例分析》MySQLLENGTH()函数用于计算字符串的字节长度,区别于CHAR_LENGTH()的字符长度,适用于多字节字符集(如UTF-8)的数据验证... 目录1. LENGTH()函数的基本语法2. LENGTH()函数的返回值2.1 示例1:计算字符串

Linux在线解压jar包的实现方式

《Linux在线解压jar包的实现方式》:本文主要介绍Linux在线解压jar包的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux在线解压jar包解压 jar包的步骤总结Linux在线解压jar包在 Centos 中解压 jar 包可以使用 u

linux解压缩 xxx.jar文件进行内部操作过程

《linux解压缩xxx.jar文件进行内部操作过程》:本文主要介绍linux解压缩xxx.jar文件进行内部操作,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、解压文件二、压缩文件总结一、解压文件1、把 xxx.jar 文件放在服务器上,并进入当前目录#