写时复制页面保护机制是一种优化,内存管理器利用它可以节约内存。
当进程为一个包含读/写页面的内存区对象映射了一份写时视图,而并非在映射该视图时创建一份进程私有的拷贝(Hewlett Packard OpenVMS操作系统就是这样做的)时,内存管理器将页面拷贝的动作推迟到页面被写入数据的时候。所有现代的UNIX系统也都使用了这项技术。如:2个进程正在共享3个页面,每个页面都被标记为写时复制,但是这2个进程都不打算修改页面上的任何数据。
如果这2个进程中任何一个线程对一个页面执行了写操作,则产生一个内存管理错误。内存管理器看到,此写操作作用在一个写时复制的页面上,所以,它不是将此错误报告为访问违例,而是在物理内存中分配一个新的读/写页面,并且把原始页面中的内容拷贝到新的页面中。同时也更新一下该进程中对应的页面映射信息,使它指向新的页面位置,然后解除异常,从而使得刚才产生错误的那条指令得以重新执行。这一次,写操作成功了。但是,新拷贝的页面现在对于执行写操作的那个进程来说是私有的,对于其它仍然在共享这一写时复制页面的进程来说,它是不可见的。每个往共享页面中写入数据的进程都将获得它自己的私有拷贝。
写时复制的一个应用是:在调试器中实现断点支持。例如:在默认情况下,代码页面在起始时都是只能执行的。然而,如果一个程序员在调试一个程序时设置了一个断点,则调试器必须在代码中加入一条断点指令。它是这样做的:首先将该页面的保护模式改变为PAGE_EXECUTE_READWRITE,然后改变指令流。因为代码页面是所映射的内存区的一部分,所以内存管理器为设置了断点的那个进程创建一份私有拷贝,同时其它进程仍然使用原先未经修改的代码页面。
写时复制是“延迟计算(lazy evaluation)”这一计算技术(evaluation technique)的一个例子,内存管理器广泛地使用了延迟计算的技术。延迟计算使得只有当绝对需要时才执行一个昂贵的操作--如果该操作从来也不需要的话,则它不会浪费任何一点时间。
POSIX 子系统利用写时复制来实现 fork 函数,当一个UNIX 应用程序调用fork 函数来创建另一个进程时,新进程所做的第一件事是调用exec 函数,用一个可执行程序来重新初始化它的地址空间。 在fork中,新进程不是拷贝整个地址空间,而是通过将页面标记为写时复制的方式,与父进程共享这些页面。如果子进程在这些页面中写入数据了,则生成一份进程私有的拷贝。如果没有写操作,则2个进程继续共享页面,不会执行拷贝动作。不管怎么样,内存管理器只拷贝一个进程试图要写入数据的那些页面,而不是整个地址空间。
想了解写时复制错误的比率,查看性能计数器:Memory: Write Copies/Sec 。
分享到:
相关推荐
在调用Fork函数时,系统会执行一个系统调用(通常通过INT 80H中断),内核会为新进程分配内存空间,设置任务状态段(Task Status Segment,TSS)和其他必要的数据结构,以便新进程可以独立运行。 ### 三、Task ...
在Linux系统中,进程是资源分配的基本单位,而线程则是处理器调度的基本单位。进程之间通过特定的方式进行通信和同步,而创建新进程则是实现这些操作的基础。本文将详细介绍`fork()`函数的工作原理及其在Linux环境中...
#### 四、为什么子进程从fork后开始执行? 如果子进程也从 `main()` 函数的开头重新执行所有指令,那么它在执行到 `fork()` 时又会创建一个新的子进程,这样就会形成无限递归的进程创建过程,最终导致系统资源耗尽...
当一个进程调用`fork()`时,系统会创建一个新的进程——子进程,这个过程被称为进程复制。子进程会继承父进程的大部分属性,如打开的文件描述符、环境变量等。`fork()`返回两次,一次在父进程中返回子进程的PID...
- **--slavedelay**: 用于设置从节点相对于主节点的复制延迟时间,单位为秒。这可以帮助防止主节点上的更改立即传播到所有从节点,从而减少数据丢失的风险。 - **--autoresync**: 如果从节点与主节点失去同步,...
- **手动降级主节点**: 可以使用`rs.stepDown(50)`命令将当前主节点降级为从节点,其中50表示等待的时间(单位为秒)。 #### 六、MongoDB 常用配置参数 1. `--version`: 查看MongoDB版本。 2. `-h` 或 `--help`: ...
这个程序应该能够模拟一个作业的执行,该作业有320条指令,分页后为32页,内存中只有4个页面可供使用。程序需要跟踪页面的访问情况,根据所选的页面置换算法决定何时替换页面,并记录缺页次数。 【Linux进程】 在...
在创建进程时,fork()函数会将父进程的资源复制一份给子进程,但这只是一个假象,因为真正的复制只有在写时才会发生。vfork()函数与fork()函数类似,但它会将子进程优先于父进程,直到子进程结束。clone()函数则是...
进程可以视为一个执行中的程序的实例,它包含了程序代码、其当前值、变量状态、程序计数器、寄存器状态以及系统资源如文件句柄等信息。而线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的...
新创建的子进程会得到父进程数据的一个副本,但这副本实际上是一开始时共享父进程的物理内存页的,这就是“写时拷贝”技术(Copy-On-Write, COW)的实现。当父进程或子进程中的任何一个试图修改这些共享的内存页时,...
fork创建子进程的机制包括写时复制,子进程要copy父进程的代码段、堆栈段、数据段、PCB进程控制块。PCB控制块是linux内核管理进程的数据结构。 僵尸进程和孤儿进程是进程状态的两种特殊情况。孤儿进程是指parent先...
在内存管理方面,子进程与父进程共享虚拟内存空间,但采用写时拷贝技术,即只有当某个进程尝试修改共享内存时,才会真正复制这部分内存,以避免不必要的数据复制。 进程同步是操作系统中实现多进程协同工作的重要...
qlBitRate是一个 QuickLook 插件,它将在 QuickLook 窗口的标题栏中显示 MP3 文件的比特率(以 kbps 为单位)和文件名。 这个插件已经过测试,可以在 OS X 10.7-10.10 中使用。 安装 预编译 解压缩文件 将文件移动...
当进程创建子进程时,Linux使用写时拷贝技术来优化内存的使用。子进程一开始并不复制父进程的整个地址空间,而是复制地址空间的引用。只有当父进程或子进程试图修改地址空间中的内容时,实际的物理内存复制才会发生...
当调用`fork()`时,当前进程(父进程)将被复制一份,形成一个新的进程(子进程)。`fork()`返回值在父进程和子进程中有所不同:在父进程中,它返回新创建子进程的PID(进程ID),而在子进程中,`fork()`返回0。因此...
在Linux中,进程创建通常是通过`fork()`和`exec()`系统调用来实现的,`fork()`用于复制一个已有进程,而`exec()`则用于替换新进程的内存空间,加载新的程序执行。 3. **动态分区**:在操作系统中,动态分区是一种...
在操作系统中,进程被视为资源分配的最小单位,每个进程都有自己的虚拟地址空间,保证了不同进程间的资源隔离。 2. **并发执行的实质**: 并发执行并不意味着多个事件在同一时刻同时发生,而是指在操作系统层面,...
幸好 UNIX 自有其解决的办法,大家知道,一般 CPU 都是以“页”为单位分配空间的,而数据段和堆栈段都是由许多“页”构成的,fork 函数复制这两个段,只是“逻辑”上的,并非“物理”上的。 在 Linux 中,还有很多...
`--slavedelay` 设置从节点相对于主节点的复制延迟,单位为秒。 #### 三、MongoDB 主从备份配置详解 1. **主节点与从节点的关系** 主节点负责处理客户端的写入请求,并将这些操作同步到从节点。从节点主要用于...