Linux内核只有进程,没有线程的概念。非要说区别,那就是线程没有自己的单独的地址空间(mm_struct),线程和其父进程共享地址空间。
pthread调用fork(..|CLONE_VM|...)来创建新的进程,子进程与父进程共享VM空间。注意,这里实际上是共享mm_struct结构,子进程甚至没有创建自己的mm_struct结构。如果没有指定CLONE_VM属性参数,子进程会创建自己的VM地址空间,包括mm_struct, vma_struct, pgd, pmd, pte等等。只不过这些结构的内容和父进程的完全一致,直接从父进程拷贝过来的。
COW (Copy On Write)
Linux创建新的进程时,如果父进程的地址空间为可写,则在创建子进程的地址空间时,将父子进程的地址空间都改为只读。这样,父子进程就能以只读方式共享相同的物理页面,不需要为子进程创建新的物理页面来copy数据,节约了时间和空间。之后,如果子进程试图写这片地址空间,则会产生一个page fault,page fault handler函数会检查,判定这是一个COW属性的页面,并为子进程分配一个可写的新页面后返回。子进程就可以在这新的独占的页面上进行写操作,此后父子进程对各自的页面进行操作,互不干扰,没有关联。
COW这种机制只是对创建进程这个操作的一种优化处理,避免花费大量的时间空间来为子进程准备数据,因为子进程可能并不需要这些数据。当子进程真正需要修改这些数据时,才为其分配空间。这是一种lazy computation的概念。COW不是用来在父子进程间进行数据同步的。