Linux内存管理之进程创建的写时拷贝技术

Unix的进程创建很特别。许多其他的操作系统都提供了产生进程的机制,首先在新的地址空间创建进程,读入可执行的文件,最后开始执行。Unix采用了与众不同的实现方式,它把上述步骤分解到两个单独的函数中去执行:fork()和exec()。(这里的exec是指exec一族的函数,内核实现了execve函数,在此基础上还实现了execlp、execle、execv和execvp等)。首先fork通过拷贝当前进程创建一个子进程。子进程与父进程的区别仅仅在于PID(每个进程是唯一的)、PPID(父进程的进程号,子进程将其设置为被拷贝进程的PID)和某些资源和统计量(例如,挂起的信号,它没有必要被继承)。exec函数负责读取可执行文件并将其载入地址空间开始运行。


上面我们先简单的述说了linux内核产生进程的机制,在述说写时拷贝技术之前,下面我们先详细说明下fork和exec都做了哪些事情:

或许许多朋友可能对fork和exec的调用比较模糊的,学过c语言的都知道,Linux下某个进程的地址空间分为:代码段、数据段、堆空间和栈空间。代码段是用来存放运行的代码的,数据段是用来存放全局变量的和static变量,堆空间是进程调用malloc分配地址空间的,栈是用来存放程序的临时变量的。


fork()函数:

linux通过clone系统调用实现fork。这个调用通过一系列的参数标志来指明父、子进程需要共享的资源。fork和vfork和__clone库函数都是根据各自需要的参数标志去调用clone,然后clone去调用do_fork:

do_fork完成了创建中的大部分工作,它定义在kernel/fork.c文件中。该函数调用copy_process函数,然后让进程开始运行。copy_process函数完成的工作如下:

(1)调用dup_task_struct为新进程创建一个内核栈、thread_info结构和task_struct,这些值与当前进程的值相同。此时,子进程和父进程的描述符完全相同。

(2)检查并确保新创建这个子进程后,当前用户所拥有的进程数目没有超出给它分配的资源的限制

(3)子进程着手使自己与父进程区别开来。进程描述符内的许多成员都要被清0或设为初始值。那些不是继承而来的进程描述符成员,主要是统计信息。task_struct中的大多数数据都依然未被修改

(4)子进程的状态设置为TASK_UNINTERRUPTIBLE,以保证它不会投入运行

(5)copy_process调用copy_flag以更新task_struct的flags成员。表明进程是否拥有超级用户权限的PF_SUPERPRIV标志被清0.表用进程还没有调用exec函数PF_FORKNOEXEC标志被设置

(6)调用alloc_pid为新进程分配一个有效的PID

(7)根据传递给clone的参数标志,copy_process拷贝或共享打开的文件、文件系统信息、信号处理函数、进程地址空间和命名空间等。在一般情况下,这些资源会被给定进程的所有进程共享;否则,这些资源对每个进程是不同的,因此被拷贝到这里。

(8)最后

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值