http://www.cnblogs.com/chenglei/archive/2009/08/06/1540175.html
inux内核在使用fork创建进程时,基本上会使用Copy-On-Write(COW)技术。这里解释一下COW技术以及为什么在fork中使用。
WIKI上对COW的解释:
Copy-on-write (sometimes referred to as "COW") is an optimization strategy used in computer programming. The fundamental idea is that if multiple callers ask for resources which are initially indistinguishable, they can all be given pointers to the same resource. This function can be maintained until a caller tries to modify its "copy" of the resource, at which point a true private copy is created to prevent the changes becoming visible to everyone else. All of this happens transparently to the callers. The primary advantage is that if a caller never makes any modifications, no private copy need ever be created.
意思上就是:在复制一个对象的时候并不是真正的把原先的对象复制到内存的另外一个位置上,而是在新对象的内存映射表中设置一个指针,指向源对象的位置,并把那块内存的Copy-On-Write位设置为1.
这样,在对新的对象执行读操作的时候,内存数据不发生任何变动,直接执行读操作;而在对新的对象执行写操作时,将真正的对象复制到新的内存地址中,并修改新对象的内存映射表指向这个新的位置,并在新的内存位置上执行写操作。
这个技术需要跟虚拟内存和分页同时使用,好处就是在执行复制操作时因为不是真正的内存复制,而只是建立了一个指针,因而大大提高效率。但这不是一直成立的,如果在复制新对象之后,大部分对象都还需要继续进行写操作会产生大量的分页错误,得不偿失。所以COW高效的情况只是在复制新对象之后,在一小部分的内存分页上进行写操作。
COW在编程中被广泛应用。
特别是在操作系统当中,当一个程序运行结束时,操作系统并不会急着把其清除出内存,原因是有可能程序还会马上再运行一次(从磁盘把程序装入到内存是个很慢的过程),而只有当内存不够用了,才会把这些还驻留内存的程序清出。
而对于Linux内核空间创建进程时的fork,由于在内核空间已经由代码决定不使用COW技术(参见mm/memory.c Line 221)。从而由内核空间的进程0(main)创建进程1(init)不使用COW,系统对此次新进程创建进行了特殊处理(存在疑问,同样是fork,如何实现对这个fork的特殊处理,估计是schedule,看到再解决了)。进程0和进程1同时使用着内核代码区内(<=1M)相同的代码和数据内存页面(640KB),只是执行代码不在一处,因此他们也同时使用着相同的用户堆栈区。在为进程1(init)复制其父进程(进程0)的页目录和页表项时,进程0的640KB页表项的属性没有改动过(仍然可读写),但是进程1的640KB对应的页表项却被设置成只读。因此当进程1(init)开始执行时,对用户堆栈的入栈操作将导致页面写保护异常,从而使得内核的内存管理程序为进程1在主内存区中分配一内存页面,并把进程0中的页面内容复制到新的页面上。从此时开始,进程1开始有自己独立的内存页面,由于此时的内存页面在主内存区,因此进程1中继续创建新的子进程时可以采用COW技术。
在Linux内核首先通过move_to_user_mode转移到用户模式下执行,至此main函数就以进程0的身份运行。而进程0是所有将创建进程的父进程,他创建进程1(init)时,fork的结果就是进程1与进程0拥有完全相同的内存空间、堆栈,这时进程0和进程1的内存还都在Linux内核空间中。
内核调度进程运行时次序是随机的,有可能在进程0创建了进城1之后仍然允许进程0,由于两个进程共享内存空间,为了不出现冲突问题,就必须要求进程0在进程1执行堆栈操作(进程1的堆栈操作会导致页面保护异常,从而使得进程1在主内存区得到新的用户页面区,此时进程1和进程0才算是真正独立,如前面所述)之前禁止使用用户堆栈区。所以进程0在执行了fork(创建了进程1)之后的pause使用内嵌的方式,保证进程0(main)不会弄乱堆栈。
进程1中如果执行fork以及exec,此时的页面空间已经到了主内存区,就可以使用COW了。
相关推荐
Linux中的写时拷贝(Copy-On-Write, COW)技术是一种高效且节省资源的内存管理策略,尤其在处理进程创建如`fork()`时显得尤为重要。COW的基本思想是在数据未被修改前,多个进程可以共享同一份数据的物理副本,从而...
为了提高效率,Linux采用写时复制(Copy-On-Write, COW)技术,使得父子进程共享同一份物理内存页,只有当其中一个进程尝试修改时,才会真正复制内存。这种设计大大减少了内存资源的消耗,提高了创建新进程的效率。 ...
`fork()`会复制父进程的所有资源,包括内存空间,但这个复制并非完全意义上的物理复制,而是采用了一种称为“写时复制”(Copy-on-Write, COW)的技术。这意味着在创建之初,父子进程共享同一份内存映像,只有在一方...
Linux使用clone系统调用实现fork,其名称源于其使用写时拷贝(Copy-On-Write, COW)技术来优化内存复制。在fork之后,子进程与父进程共享同一地址空间,只有在写入时才会真正复制页面,从而提高了效率。 exec系列...
然而,复制并非字面意义上的物理复制,而是采用写时复制(Copy-On-Write,COW)技术,只有当某个进程试图修改已复制的数据时,才会真正分配新的内存并复制数据。 二、Fork的返回值与父子进程的交互 2.1 返回值:在...
但请注意,它们是共享的,直到有写操作发生,这时才会发生写时复制(Copy-On-Write, COW)。 2. **返回值**:`fork()`调用后,执行流被分成两个分支,一个是父进程,另一个是子进程。两者都会继续执行`fork()`之后...
进程出生时会分配资源,如通过`fork()`创建子进程时会使用Copy-On-Write(COW)策略避免不必要的内存复制。进程死亡时,子进程可能会被父进程清理,或者在父进程死亡后由系统接管。 第四部分讨论了进程的分类和调度...
#### 写时拷贝技术(Copy-on-Write) 写时拷贝是一种优化技术,在Linux中被广泛应用于进程创建过程。当父进程通过`fork()`创建子进程时,并不会立即复制整个内存空间,而是共享同一段物理内存。只有当其中一个进程...
新创建的子进程会得到父进程数据的一个副本,但这副本实际上是一开始时共享父进程的物理内存页的,这就是“写时拷贝”技术(Copy-On-Write, COW)的实现。当父进程或子进程中的任何一个试图修改这些共享的内存页时,...
#### 七、写时复制(Copy-On-Write, COW) 当子进程通过`fork()`函数创建时,虽然它继承了父进程的内存空间,但实际上并没有立即复制这些内存数据。这种机制被称为写时复制(COW)。这意味着直到子进程尝试修改某个...
- 使用写时复制(Copy-On-Write, COW)机制。 - 在创建子进程时,并不立即复制物理内存页面。相反,子进程和父进程共享相同的物理页面。 - 当其中一个进程试图修改一个共享页面时,内核会为该进程分配一个新的...
在`fork()`之后,尽管数据段和堆栈段在逻辑上被复制,但实际的物理复制只有在其中一个进程修改数据时才会发生,这种机制称为写时复制(Copy-On-Write,COW),有助于减少内存开销。 除了`fork()`,Linux还提供了`...
在上图的存储空间布局中,父子进程只共享正文段,其余的都各自有独立的副本 (通常使用 copy-on-write 的策略,速度比较快)。 fork 的两种用法 1.父子进程同时执行不同的代码段 典型应用:Web 服务器。 以下代码是...
“写时复制”(Copy-on-Write,COW)是Linux快速创建进程的关键技术。在COW机制下,子进程初始时与父进程共享同一份物理内存,只有当其中一个进程尝试修改内存时,才会真正复制页面。例如,如果子进程试图修改某个...
然而,为了提高效率,现代Linux采用了写时复制(Copy-On-Write, COW)技术,使得父子进程在一开始共享内存页面,只有当一方试图修改时才会复制页面,避免了不必要的资源浪费。此外,execve系统调用允许进程执行新的...
而进程创建,如通过`fork()`或`vfork()`,则通常不会共享这些资源,即使使用了copy-on-write技术来延迟内存复制,仍存在一定的开销。 调度是操作系统中一个至关重要的概念,它决定了进程和线程何时能获得CPU执行...
在早期实现中,这些副本是完全独立的,但现在大多数系统采用写时复制(Copy-On-Write,COW)技术。这意味着只要父子进程不修改这些区域,它们可以共享同一物理内存,从而提高了效率。 3. **不确定性与并发执行**: ...
- 为提高效率,Linux采用写时拷贝(Copy-on-Write)策略,子进程在创建时并不复制父进程的完整虚拟内存,只有当一方尝试修改时才会创建独立的副本。 6. **`fork()`系统调用**: - `fork()`调用创建一个与父进程几乎...