fork()函数解析

fork()总述:

     fork调用用于创建一个新进程,把当前的进程分为父进程和子进程,新进程称为子进程,而原进程称为父进程。fork调用一次,返回两次,这两个返回分别带回它们各自的返回值,其中在父进程中的返回值是子进程的PID,而子进程中的返回值则返回 0。

    新创建的子进程几乎但是不完全与父进程相同。子进程得到与父进程用户级虚拟地址空间相同的一份拷贝,(包括文本、数据和bss段、堆以及用户栈),子进程还获得与父进程任何打开文件描述符相同的拷贝,所以当父进程调用fork时,子进程可以读写父进程中打开的任何文件。

 

fork()内核处理过程:

       为了描述和控制进程的运行,系统为每一个进程定义了一个数据结构——进程控制块,它是进程实体的一部分。PCB是进程存在的唯一标志。进程控制块中的信息包括进程标识符、处理机状态、进程调度信息、进程控制信息。然而PCB在linux中具体实现是 task_struct数据结构。
      Linux下用于创建进程的API有三个fork,vfork和clone,这三个函数分别是通过系统调用sys_fork,sys_vfork以及sys_clone实现的 (基于x86架构的)。而且这三个系统调用,都是通过do_fork来实现的,只是传入了不同的参数。所以我们可以得出结论:所有的子进程是在do_fork实现创建和调用的。下面我们就来整理一下整个进程的在用户态到内核态的过程是怎么样的。

fork系统调用如下: 

而 do_fork()的实现,主要是靠copy_process()函数完成的,整个过程实现如下:

1.p = dup_task_struct(current);为子进程创建一个内核栈、thread_iofo和task_struct,这里完全copy父进程的内容,所以到目前为止,父进程和子进程是没有任何区别的。

2.为子进程在其内存上建立内核堆栈

3.对子进程task_struct任务结构体中部分变量进行初始化设置,检查所有的进程数目是否已经超出了系统规定的最大进程数,如果没有的话,那么就开始设置进程描诉符中的初始值,从这开始,父进程和子进程就开始区别开了。

4.把父进程的有关信息复制给子进程,建立共享关系

5.把子进程加入到可运行队列中,但设置子进程的状态为不可被TASK_UNINTERRUPTIBLE,从而保证这个进程现在不能被投入运行,因为还有很多的标志位、数据等没有被设置

6.复制标志位(falgs成员)以及权限位(PE_SUPERPRIV)和其他的一些标志

7.调用get_pid()给子进程获取一个有效的并且是唯一的进程标识符PID

8.return ret_from_fork;返回一个指向子进程的指针,开始执行

 

例0:


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值