fork()函数 —— 父子进程资源问

fork()函数功能——创建新进程

1、父子进程有独立的数据段、堆、栈,共享代码段

  Linux中每个进程都有4G的虚拟地址空间(独立的3G用户空间和共享的1G内核空间),fork()创建的子进程也不例外。子进程资源的由来:

  1、1G内核空间既然是所有进程共享,因此fork()创建的子进程自然也将拥有;

  2、3G的用户空间是从父进程进程而来。

  fork()创建子进程时继承了父进程的数据段、代码段、栈段、堆,注意从父进程继承来的是虚拟地址空间,同时也复制了页表(没有复制物理块)。因此,此时父子进程拥有相同的虚拟地址,映射的物理内存也是一致的(独立的虚拟地址空间,共享父进程的物理内存)。

  由于父进程和子进程共享物理页面,内核将其标记为“只读”(类似mmap)的private的方式),父子双方均无法对其修改。无论父进程和子进程何时试图对一个共享的页面执行写操作,就产生一个错误,这时内核就把这个页复制到一个新的页面给这个进程,并标记为可写,同时修改页表,把原来的只读页面标记为“可写”,留给另外一个进程使用——写时复制技术。

  注意:内核在为子进程分配物理内存时,并没有将代码段对应的数据另外复制一份给子进程,最终父子进程代码段映射的是同一块物理内存(代码段在单个进程内部本来就是只读的)。  

  每个进程的虚拟地址空间都可以是0到4G,只不过其中只有一部分有权访问,每个进程可以有不同的映射。两次运行同一个程序就是使用的相同的虚拟地址,但是映射到的物理地却是不一样的。每个进程都有自己的虚拟地址空间,不同进程的相同的虚拟地址显然可以对应不同的物理地址。因此地址相同(虚拟地址)而值不同没什么奇怪。

写时复制技术参见:http://www.cnblogs.com/wuchanming/p/4495479.html

2、一次调用两次执行

  参见:http://blog.csdn.net/shenwansangz/article/details/39184789

3、 竞争条件

  Linux是一个多用户操作系统,在同一时间会有许多的用户在争夺系统的资源.有时进程为了早一点完成任务就创建子进程来争夺资源. 一旦子进程被创建,父子进程一起从fork处继续执行,相互竞争系统的资源.有时候我们希望子进程继续执行,而父进程阻塞,直到子进程完成任务.这个时候我们可以调用wait或者waitpid系统调用.

  对子进程来说,fork返回给它0,但它的pid绝对不会是0;之所以fork返回0给它,是因为它随时可以调用getpid()来获取自己的pid;fork之后父子进程除非采用了同步手段,否则不能确定谁先运行,也不能确定谁先结束。认为子进程结束后父进程才从fork返回的,这是不对的,fork不是这样的,vfork才这样。

4、fork之后跟随exec

  fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,出于效率考虑,linux中引入了“写时复制“技术,也就是只有进程空间的各段的内容要发生变化时,才会将父进程的内容复制一份给子进程。由于写时复制,在fork之后exec之前两个进程有独立的虚拟地址空间,共享物理内存。只有其中一方需要写操作时,再为子进程的数据段、栈、堆分配物理空间。但在子进程上调用exec时,会清空栈、堆,以及和父进程共享的空间,重新加载新的代码段,这样避免了“写时复制”拷贝共享页面的机会,父进程也同时独自拥有了原来共享的物理内存(可对其读写操作)。

  fork出来子进程之后,父子进程哪个先调度直接决定了是否需要拷贝的问题?内核一般会先调度子进程,因为很多情况下子进程是要马上执行exec,而避免无用的复制。如果父进程先调度很可能写共享页面,会产生“写时复制”的无用功。所以,一般是子进程先调度滴。

  在网上看到还有个细节问题就是,fork之后内核会通过将子进程放在队列的前面,以让子进程先执行,以免父进程执行导致写时复制,而后子进程执行exec系统调用,因无意义的复制而造成效率的下降。

  如果不是因为exec,子进程执行时很可能修改内存,内核会给子进程的数据段、堆栈段分配相应的物理空间(至此两者有各自的进程空间,互不影响),而代码段继续共享父进程的物理空间(两者的代码完全相同)。而如果是因为exec,由于两者执行的代码不同,子进程的代码段也会分配单独的物理空间。

5、fork()函数的实现过程

  http://blog.csdn.net/shenwansangz/article/details/39184789

时间: 2024-10-06 09:06:06

fork()函数 —— 父子进程资源问的相关文章

通过fork函数创建进程的跟踪,分析linux内核进程的创建

作者:吴乐 山东师范大学 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.实验过程 1.打开gdb,设置断点 2.跟踪到do_fork处 3.跟踪到copy_process断点处. 4.跟踪到ret_from_fork子进程创建完成. 二.代码部分分析 Fork的系统调用代码在linux/arch/i386/kernel/process.c中:       asmlinkage int sys_fork(s

4进程原语:fork()函数,getpid()函数和getppid()函数,getuid()函数,getgid()函数,vfork()

 1fork()函数 子进程复制父进程的0到3g空间和父进程内核中的PCB,但id号不同.fork调用一次返回两次,有以下特点: A:父进程中返回子进程ID B:子进程中返回0 C:读时共享,写时复制 2fork()依赖的头文件 #include <unistd.h> 3fork()函数说明: pid_tfork(void); 通过该函数创建一个子进程 4案例说明: 总结: A因为读时共享和写时复制,子进程会复制父进程的代码,但是从fork下开始执行.但是,当在fork前定义父子进程都用到

fork函数返回值问题

fork是最难理解的概念之一:它执行一次却返回两个值. 首先我们来看下fork函数的原型: #include <sys/types.h> #include <unistd.h> pid_t fork(void); 返回值: 负数:如果出错,则fork()返回-1,此时没有创建新的进程.最初的进程仍然运行. 零:在子进程中,fork()返回0 正数:在负进程中,fork()返回正的子进程的PID 其次我们来看下如何利用fork创建子进程. 创建子进程的样板代码如下所示: pid_t

linux fork函数与vfork函数

man vfork: NAME vfork - create a child process and block parent SYNOPSIS #include <sys/types.h> #include <unistd.h> pid_t vfork(void); DESCRIPTION Standard description (From POSIX.1) The vfork() function has the same effect as fork(2), except

关于fork函数中的内存复制和共享

原来刚刚开始做linux下面的多进程编程的时候,对于下面这段代码感到很奇怪, 1 #include<unistd.h> 2 #include<stdio.h> 3 #include<string.h> 4 #include<stdlib.h> 5 #include<stdarg.h> 6 #include<errno.h> 7 #define LEN 2 8 void err_exit(char *fmt,...); 9 int ma

深入浅出--UNIX多进程编程之fork()函数

0前言 上周都在看都在学习unix环境高级编程的第八章--进程控制.也就是这一章中,让我理解了unix中一些进程的原理.下面我就主要按照进程中最重要的三个函数来进行讲解.让大家通过阅读这一篇文章彻底明白进程这点事.希望对大家有所帮助. 1进程环境 在学习进程之前,一定要了解一下unix的进程环境.系统如何对进程终止,和一个程序启动终止,程序运行的原理等,这些都有助于你理解进程的运行原理.这些内容都在我的上一篇文章中,请关注:http://blog.csdn.net/wallwind/articl

Linux下的 fork 函数

之前只是了解到linux中的fork函数是用来创建进程,并没有太多的去学习,这里学习记录如下. 撰写不易,转载需注明出处:http://blog.csdn.net/jscese/article/details/44401389 本文来自 [jscese]的博客! 定义: 来自百科的解释:fork函数将运行着的程序分成2个(几乎)完全一样的进程,每个进程都启动一个从代码的同一位置开始执行的线程.这两个进程中的线程继续执行,就像是两个用户同时启动了该应用程序的两个副本. 通俗的来理解,就是程序跑到f

C/C++网络编程7——多进程服务器端之fork函数

通过前面几节的内容,我们已经可以实现基本的C/S结构的程序了,但是当多个客户端同时向服务器端请求服务时,服务器端只能按顺序一个一个的服务,这种情况下,客户端的用户是无法忍受的.所以虚实现并发的服务器端. 并发服务器端的实现方法: 1:多进程服务器端:通过创建多个进程提供服务. 2:多路复用服务器:用过捆绑并统一管理I/O对象提供服务. 3:多线程服务器:通过生成与客户端等量的线程提供服务. 多进程服务器端: 进程:可执行程序的一次执行过程. 在linux下可通过fork()函数创建一个进程. #

UNIX环境编程学习笔记(19)——进程管理之fork 函数的深入学习

lienhua342014-10-07 在“进程控制三部曲”中,我们学习到了 fork 是三部曲的第一部,用于创建一个新进程.但是关于 fork 的更深入的一些的东西我们还没有涉及到,例如,fork 创建的新进程与调用进程之间的关系.父子进程的数据共享问题等.fork 是否可以无限制的调用?如果不行的话,最大限制是多少?另外,我们还将学习一个 fork 的变体 vfork. 1 fork 创建的新进程与调用进程之间的关系 UNIX 操作系统中的所有进程之间的关系呈现一个树形结构.除了进程 ID