辛星浅析Linux中的进程基本知识以及fork的简单理解
2015-03-26 00:18
393 查看
进程可以看作是程序的一次执行过程,在Linux下,每个进程有唯一的PID标识进程,PID是一个从1到32768的正整数,其中1一般是init,其他的进程从2开始依次编号,当用完了32768之后,从2重新开始。
Linux中有一个进程表的结构来存储当前正在进行的进程,我们可以用ps aux或者ps ef来查看正在进行的进程。进程在Linux中呈树状结构,init是根节点,其他的进程均有父进程。某进程的父进程就是启动这个进程的进程,这个进程叫做父进程的子进程。
fork的作用就是复制一个与当前进程一样的进程,新进程的所有数据,比如变量、环境变量、程序计数器等都和原进程一直,但是它是一个全新的进程,而且作为原进程的子进程。
出于效率的考虑,Linux引入了写时复制的技术,也就是只有进程空间的隔断的内容需要发生变化时,才会将父进程的内容复制一份给子进程。在fork之后exec之前两个进程使用的是相同的物理空间,也就是相同的内存区,子进程的代码段、数据段、堆栈段都是指向父进程的物理空间的,也就是说,虽然两者的虚拟空间不同,但是对应的物理空间是同一个。
当子进程有更改相应段的行为发生时,再为子进程相应的段分配物理空间,如果不是因为exec,内核会给子进程的数据段、堆栈段分配相应的物理空间,至此两者都有了各自的进程空间,而且互不影响,而代码段会继续共享父进程的物理空间。如果是因为exec,由于两者执行的代码不同,子进程的代码段也会分配单独的物理空间。
在fork之后内核会通过将子进程放到队列的前面,来让子进程先执行,以免父进程执行导致写时复制,而后子进程执行exec系统调用,因为无意义的复制而造成效率的下降。
也就是说,通过写时复制技术,内核只为新生成的子进程创建虚拟空间结构,它们用来复制父进程的虚拟结构,但是不为这些段分配物理内存,它们共享父进程的物理空间,但是当子进程有更改相应段的行为发生时,再为子进程相应的段分配物理空间。
而vfork则是内核连子进程的虚拟地址空间结构也不创建了,直接共享了父进程的虚拟空间,也就直接共享了父进程的物理空间。
传统的fork调用是把所有的资源复制给新创建的进程,这种实现过于简单且效率地下,因为它拷贝的数据也许并不共享,如果新进程打算立即执行一个新的映像,那么所有的拷贝都将前功尽弃。
Linux的fork使用了写时拷贝,它可以推迟甚至避免拷贝数据,内核此时并不复制整个进程地址空间,而是让父进程和子进程共享同一个拷贝,在写入数据时,数据才会被复制,从而使各个进程拥有自己的拷贝。也就是说,资源的复制只在需要的时候才进行,在此之前,是以只读方式共享的。
也就是说,fork的实际开销就是复制父进程的页表给子进程创建的唯一的进程描述符,在一般情况下,进程创建后都会马上运行一个可执行文件,这种优化可以避免拷贝大量根本不会使用的数据,因为UNIX强调进程快速执行的能力,所以这个优化还是蛮重要的。
Linux中有一个进程表的结构来存储当前正在进行的进程,我们可以用ps aux或者ps ef来查看正在进行的进程。进程在Linux中呈树状结构,init是根节点,其他的进程均有父进程。某进程的父进程就是启动这个进程的进程,这个进程叫做父进程的子进程。
fork的作用就是复制一个与当前进程一样的进程,新进程的所有数据,比如变量、环境变量、程序计数器等都和原进程一直,但是它是一个全新的进程,而且作为原进程的子进程。
出于效率的考虑,Linux引入了写时复制的技术,也就是只有进程空间的隔断的内容需要发生变化时,才会将父进程的内容复制一份给子进程。在fork之后exec之前两个进程使用的是相同的物理空间,也就是相同的内存区,子进程的代码段、数据段、堆栈段都是指向父进程的物理空间的,也就是说,虽然两者的虚拟空间不同,但是对应的物理空间是同一个。
当子进程有更改相应段的行为发生时,再为子进程相应的段分配物理空间,如果不是因为exec,内核会给子进程的数据段、堆栈段分配相应的物理空间,至此两者都有了各自的进程空间,而且互不影响,而代码段会继续共享父进程的物理空间。如果是因为exec,由于两者执行的代码不同,子进程的代码段也会分配单独的物理空间。
在fork之后内核会通过将子进程放到队列的前面,来让子进程先执行,以免父进程执行导致写时复制,而后子进程执行exec系统调用,因为无意义的复制而造成效率的下降。
也就是说,通过写时复制技术,内核只为新生成的子进程创建虚拟空间结构,它们用来复制父进程的虚拟结构,但是不为这些段分配物理内存,它们共享父进程的物理空间,但是当子进程有更改相应段的行为发生时,再为子进程相应的段分配物理空间。
而vfork则是内核连子进程的虚拟地址空间结构也不创建了,直接共享了父进程的虚拟空间,也就直接共享了父进程的物理空间。
传统的fork调用是把所有的资源复制给新创建的进程,这种实现过于简单且效率地下,因为它拷贝的数据也许并不共享,如果新进程打算立即执行一个新的映像,那么所有的拷贝都将前功尽弃。
Linux的fork使用了写时拷贝,它可以推迟甚至避免拷贝数据,内核此时并不复制整个进程地址空间,而是让父进程和子进程共享同一个拷贝,在写入数据时,数据才会被复制,从而使各个进程拥有自己的拷贝。也就是说,资源的复制只在需要的时候才进行,在此之前,是以只读方式共享的。
也就是说,fork的实际开销就是复制父进程的页表给子进程创建的唯一的进程描述符,在一般情况下,进程创建后都会马上运行一个可执行文件,这种优化可以避免拷贝大量根本不会使用的数据,因为UNIX强调进程快速执行的能力,所以这个优化还是蛮重要的。
相关文章推荐
- 辛星浅析Linux中的进程基本知识以及fork的简单理解
- 8_14 日学到的新知识(简单的工厂模式的实现, MVC 模式的基本概念,软件工程中的四种开发模型, 以及软件工程中的一些小知识点)
- 用类名做方法的返回值类型 在学习Java的初始阶段,很多同学使用基本数据类型定义变量和引用类型定义变量以及使用类名做方法的返回值类型常常不知所以。今天我以自己的解读方式和个人的理解作一个简单的解释,和
- Linux进程理解与实践(一)基本概念和编程概述(fork,vfork,cow)
- 简单理解http请求及Socket,以及基本的数据传输协议,三次握手
- android 进程和线程的区别,以及系统的进程的基本知识
- vc小程序---右键菜单栏的建立以及简单的数据库连接的基本知识(PopMenu)
- Linux进程理解与实践(一)基本概念和编程概述(fork,vfork,cow)
- 理解openstack中与虚拟机相关一些简单网络知识-3.计算节点的网络拓扑以及网络分配
- JBoss 4.0.2集群指南(一)---基本知识以及简单的配置方法
- DNS基本的理论知识以及简单的安装配置你掌握了吗?
- 简单理解ASP.NET MVC基本知识
- JDBC的基本概念理解以及简单实现
- 在ASP.NET Atlas中调用Web Service——创建Mashup调用远端Web Service(基础知识以及简单示例)
- 用于测试C++/C程序员的基本编程技能、编程质量以及对C++/C的理解程度的一份考卷试题
- .Net 应用程序与进程的简单理解
- 复杂事件处理(Complex Event Processing)--1. 基本概念:事件,事件关系,事件处理的简单抽象理解
- 用于测试C++/C程序员的基本编程技能、编程质量以及对C++/C的理解程度的一份考卷试题
- 有关super,this,以及含有参数的简单理解
- 七、发生交通事故后的自救、急救等基本知识,以及常见危险化学品等知识