linux进程——fork()函数

1、fork()函数简介

(1)函数原型

#include <sys/types.h>
#include<unistd.h>

pit_t fork(void)

(2)功能

  • fork用于在已存在的进程中创建一个新的进程。
  • 创建的新进程我们称之为子进程,原进程我们称为父进程。

(3)返回类型及返回值

fork()函数的返回类型为 pid_t 类型,这时基本系统数据类型,它的实际类型是一个int类型。

1)创建子进程成功,返回两次(父进程和子进程各返回一次,后面解释为什么返回两次):

  • 子进程返回0
  • 父进程返回新创建子进程的进程id(pid_t类型)。

2)创建子进程失败,返回-1。

2、fork 函数是如何创建一个子进程的

内核为子进程创建了一个新的task_struct结构。子进程几乎是父进程的克隆体,它将获得父进程数据空间pc指针等资源的副本。

父子进程虽几乎一样,但是仍有些差别,例如

  • process id 进程ID
  • 父进程ID
  • 子进程ID 等

3、父子进程的具体在内存中的结构如下图所示

在这里插入图片描述
可以看出,父进程和子进程在物理内存中的代码段是共享的,但是堆栈内存是独立的( 图中只画出了栈内存,但是堆内存也是独立的)。

4、调用fork函数一次,为什么返回两次?

(1)返回两次的原因是:

子进程复制时复制了父进程的堆栈段,也包括pc指针,而pc指针就是正要执行的程序,所以两个进程都停留在fork函数中,等待返回。因此fork函数会返回两次,一次是在父进程中返回,另一次是在子进程中返回,这两次的返回值是不一样的(fork 的两次返回是内核帮我们实现的)。

(2)两次返回的区别

fork被调用一次,但返回两次,子进程和父进程各返回一次,并且子进程里返回值是0,而在父进程里其返回值是子进程的进程ID。

(3)两次返回有区别的原因

函数返回时pid所在栈段被复制并填写了不同的返回值,也就是两个进程拥有不同的堆栈区,函数执行完成后,返回到各自栈区的值是不同的。

5、fork出来的子进程,它和父进程执行的先后顺序?

我们无法确定fork之后是子进程先运行还是父进程先运行,这依赖于系统的(schedule算法,即内核调度算法)实现。

  • 如果父进程先运行完,那么子进程就会变成孤儿进程。此时系统会遍历属于回收的父进程的子进程,并将这些进程交由init进程 来接管,init进程就成为它的父进程。
  • 如果子进程,在父进程结束前先结束,且父进程一直不退出。那么子进程就会变成僵尸进程

6、 我们在写程序时,父进程死掉后,一般不让它退出,为什么?

因为父亲死了,init进程就将会成为其子进程的父亲。为了避免init被塞进太多的进程,则需要父进程不退出。

7、 为什么需要僵尸状态?

因为子进程的退出状态很重要,它可以返回子进程的死亡状态。因为,只有回收了子进程的退出状态,才能清理僵尸状态进程的资源(代表进程的struct 结构)。

8、新建一个进程的函数为什么起名为fork?

fork 单词的中文意思是叉子,而新创建一个进程,就像是一个叉子。如下图:
在这里插入图片描述

posted @ 2020-03-02 16:30  江南又一春  阅读(782)  评论(0编辑  收藏  举报