进程的创建之fork()函数

一、引子:

就像世上万物都有产生、发展、消亡的过程,每个进程都有被创建、执行一些程序以及最后消亡的过程,在Linux系统中,第一个进程是系统固有的、与生俱来的或者说是由内核的设计者安排好的,内核在引导并完成了基本的初始化以后,就有了系统的第一进程。并且所有的进程都是由这个原始进程或者它的子孙后代所创建,都是这个进程的“后代”。

在Linux系统中,一个新的进程一定要由一个已经存在的进程复制出来,而不是创建出来(而所谓的创建就是复制)而这里说的创建其实就是把原来的进程分配的资源、包括属于最低限度的task_struct数据结构和系统空间栈、堆进行共享;还要设置这个进程的系统空间栈,使的这个进程很像新的进程,其实你们都被骗了,以为这个进程是刚刚创建好的,其实这个进程更像是一个“克隆体”。当这个进程被调度运行的时候,其返回地址,也就是下一条指令进行恢复运动。其实这个新的进程就像新生儿一样,但是它却可以独立行走,拥有自己的独立意识。


二、进程类概念详解:

父进程(Parent Process)指已创建一个或多个子进程的进程。

子进程:指的是由另一进程(对应称之为父进程)所创建的进程。

第一进程:所有进程的祖先叫做进程0,idle进程或者swapper进程,它是在Linux的初始化阶段从无到有的创建的内核进程(该进程描述符使用的是静态分配的数据结构,其他进程都是动态分配的。进程0调用start_kernel()函数初始化内核需要的所有数据结构,激活中断,创建一个进程1 的内核进程(init进程)

孤儿进程: 当父进程结束以后, 子进程未结束, 子进程的父进程变为 init 。 

僵死进程(僵尸进程): 父进程未结束, 而子进程结束, 父进程未获取子进程的退出数据, 这时, 子进程成为僵死进程。  

进程1:init进程,init 这个进程是守护进程。 init 类型与孤儿院, 负责处理这些孤儿进程退出以后的一些状态 。


三、Linux进程的创建趣味分析:

由上述所说,进程是由复制而来,那么到底是怎么复制的呢,具体是怎么实现的呢,以及又有什么坑等着我们去填埋呢。首先讲解进程的创建就像是一个已经存在的“父进程”进行 生物上细胞分裂一样地复制出一个和自己一样的“子进程”,这里的一样指的是几乎一样,一些细节后序 将会做出补充,这里所谓的“细胞分裂”只是抽象化的进行解释一下,实际上复制出来的子进程有自己的task_struc结构和系统空间堆栈,与它的父进程共享父进程所拥有的资源。例如父进程打开了五个文件,那么子进程也有五个打开的文件,而且这些文件的当前读写指针也停在相同的地方。所以这些做的就是“复制”的操作。Linux提供了一个系统调用函数叫fork()函数,刚好用来作为进程的复制,那么它到底有什么特点呢,我们接着进行fork()函数的分析。


四、fork()函数

fork()函数定义:

fork()函数是Linux系统上用来创建进程的一个系统调用函数,它是一个有趣的函数,为什么这么说呢?因为若成功调用一次则返回两个值,子进程返回0,父进程返回子进程标记(即子进程的pid(Linux中,每个进程有一个pid,类型pid_t,由getpid()取得)用法(pid_t fpid  =  fork()));否则,出错返回 -1。fork函数将运行着的程序分成2个(几乎)完全一样的进程,每个进程都启动一个从代码的同一位置开始执行的线程。这两个进程中的线程继续执行,就像是两个用户同时启动了该应用程序的两个副本一样。

为什么fork()函数会返回两次呢?

由于在复制时复制了父进程的堆栈段,所以两个进程都停留在fork()函数中,等待返回。因此fork()函数会返回两次,一次是在父进程中返回,另一次是在子进程中返回,这两次的返回值是不一样的。 fork()调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:

1.在父进程中,fork()函数返回新创建子进程的pid;

2.在子进程中,fork()函数返回0;

3.如果出现错误,则fork()函数返回一个负值。

理解:解释fork()函数返回的值为什么在父子进程中不同。"其实就相当于链表,进程形成了链表,父进程的fork()函数返回的值指向子进程的pid(进程id), 因为子进程没有子进程,所以其fork()函数返回的值为0(类似于与单链表的null)."

五、扩充:

1. getpid(); 用于获取调用 getpid 这个函数的进程的 pid;

2. getppid(); 用户获取调用 getppid 这个函数的进程的父进程 pid;

3. 调用 fork 函数的进程为新进程的父进程。即就是,通过 fork 创建的进程与原进程是父子关系。

4. fork 之后,父子进程之间的数据共享问题:

全局数据----------------------不共享
栈区数据----------------------不共享
堆区数据----------------------不共享


5.文件描述符问题:

子进程能不能使用 fork 之前 open 返回的文件描述符?

如图所示:

答案:父进程对于文件描述符共享,并且共享文件偏移量


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值