进程控制(三)---fork函数

  Linux系统提供了 fork 函数用来创建子进程。fork 函数和普通的函数相比,其特殊的地方在于 fork 函数被调用一次,但是会返回两次。一次返回时在父进程中,另一次返回值是在子进程中。

====================================================

函数原型:

返回值:

  • 调用失败时返回 -1 给父进程,而且子进程也不会被创建。
  • 调用成功时,在父进程中返回 子进程的进程 ID,在子进程中返回 0

====================================================

  使用 fork 函数创建出的子进程会复制父进程的地址空间,包括 代码段、数据段、堆和栈,而且子进程也会复制父进程的 PCB ,但是进程 ID 肯定是会不一样的。由此可见,父进程和子进程是相互独立的,各自有各自的地址空间(虽然虚拟地址都是相同的,但是映射的物理地址肯定是不相同的)。如果子进程修改了一个变量值,那么并不会影响父进程中的变量值。

  考虑到如果每次创建子进程时都要复制父进程的地址空间,而且通常在fork之后,就会利用exec函数去执行不同的程序,所以又要去清理子进程的代码段和数据段。这样一来,降低了效率。所以如今的 fork 都会采用一种“写时复制(Copy On Write)”的技术来改进这个缺点。这种技术的特点是“读时共享,写时复制”,当子进程想要读数据的时候,和父进程共享地址空间;当子进程想要写数据的时候,才去对父进程进行复制,而且只复制父进程中被修改的那一“页”。这样就减少了复制父进程地址空间的时间,提高了效率。

=======================================================

  fork 函数被调用时,在内核中的调用流程?

  当我们在应用程序中调用 fork 函数的时候,首先会通过中断指令进入到内核态中(x86架构下使用int指令,arm架构下使用swi指令),然后通过系统调用号来找到 sys_fork 函数,最终 sys_fork 函数会调用 do_fork 函数。

  fork 函数在创建子进程的时候,子进程和父进程复制页表项,且内核将页表项设置为只读权限,当父子进程尝试去修改页的内容的时候,再去为子进程修改新的页表项,页的内容是从父进程复制而来。 vfork 函数会复制父进程的页表项,但是除非调用 exec 族函数,否则子进程不会创建新的页表项。

时间: 2024-12-27 20:24:47

进程控制(三)---fork函数的相关文章

小何讲进程: Linux进程控制编程 (fork、vfork)

所谓进程控制,就是系统使用一些具有特定功能的程序段来创建进程.撤消进程以及完成进程在各种状态之间的转换, 从而达到多进程高效率并发执行和协调资源共享的目的.进程控制是进程管理和处理机管理的一个重要任务. 1. fork()创建进程 在Linux系统中,除了系统启动之后的第一个进程(根进程)由系统来创建外, 其余所有进程都必须由已存在的进程来创建新创建的进程叫子进程,而创建子进程的进程叫父进程, 具有相同父进程的进程叫兄弟进程. 在Linux中创建一个新进程的方法是使用fork()函数. fork

Linux系统编程_8_进程控制之fork_wait_waitpid函数

fork函数: #include <unistd.h> pid_t fork(void); fork用来创建一个子进程: 特点: fork调用后会返回两次,子进程返回0,父进程返回子进程的进程ID:fork返回后,子进程和父进程都从fork函数的下一条语句開始运行: 注意: fork之后,操作系统会复制一个与父进程全然同样的子进程,虽说是父子关系.可是在操作系统看来,他们更像兄弟关系,这两个进程共享代码空间,可是数据空间是互相独立的,子进程数据空间中的内容是父进程的完整拷贝.指令指针也全然同样

进程标识符与fork函数

ID为0的进程通常是调度进程,常被称为交换进程(swapper),是内核中的系统进程. ID为1的进程叫做init进程,是一个普通用户进程,不属于内核,由内核调用. 一个现有进程可以调用fork函数创建一个新进程(子进程).fork函数被调用一次,返回两次.子进程返回值为0,父进程返回值为子进程的进程ID. 当fork出一个子进程后,子进程便拥有独立的数据段.堆.栈的副本,但父.子进程共享正文段(关于程序分布见文章"C程序的存储空间布局").但现在很多实现并不完全复制数据段.堆.栈,开

【Linux编程】进程标识符与fork函数

ID为0的进程一般是调度进程.常被称为交换进程(swapper),是内核中的系统进程. ID为1的进程叫做init进程,是一个普通用户进程,不属于内核,由内核调用. 一个现有进程能够调用fork函数创建一个新进程(子进程).fork函数被调用一次.返回两次. 子进程返回值为0.父进程返回值为子进程的进程ID. 当fork出一个子进程后,子进程便拥有独立的数据段.堆.栈的副本,但父.子进程共享正文段(关于程序分布见文章"C程序的存储空间布局").但如今非常多实现并不全然复制数据段.堆.栈

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

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

Linux系统编程_9_进程控制之exec 函数

exec函数 当进程调用exec函数时,该进程的执行程序完全的替换为新程序.新程序从它的main函数开始执行: 使用fork函数创建一个子进程后,子进程往往会使用exec函数去执行另一个程序. 注意:调用exec函数并不会创建新进程,所以创建前后的进程ID不会改变,exec只是用一个全新的程序替换了当前正在运行的程序的代码段.数据段.堆.栈. #include <unistd.h> extern char **environ; int execl(const char *path, const

(疑问)进程控制(五)---vfork 函数

vfork 函数和 fork 函数类似,也可以用来创建子进程,但是和 fork 创建的子进程有以下几点不同: fork 创建的子进程和父进程之间的执行顺序是不确定的,取决的调度算法的实现.而 vfork 函数创建的子进程 一定是先于父进程执行的,父进程会阻塞到当子进程中调用了 exec 或者 exit函数后,才会被唤醒开始执行. fork 创建的子进程和父进程是各自独立的地址空间,而 vfork 创建出的子进程在子进程调用 exec 或者 exit函数之前都是和父进程共享地址空间的. vfork

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前定义父子进程都用到

第八章:进程控制

8.1:引言 本章介绍Unix的进程控制,包括创建新进程.执行程序和进程终止.还将说明进程属性的各种ID--实际.有效和保存的用户和组ID,以及它们如何受到进程控制原语的影响.还包括解释器文件和system函数,最后讲述大多数Unix系统所提供的进程会计机制. 8.2:进程标识符 每个进程都有一个非负整型表示的唯一进程ID.虽然是唯一的,但是进程ID却可以重用,当一个进程终止后,其进程ID就可以再次使用了.Unix使用延迟重用算法,避免新进程的ID等于最近终止的进程的ID. 除了进程ID,每个进